Masterminds of Programming: Conversations with the Creators of Major Programming Languages (Theory in Practice (O'Reilly))

This Year Stack Overflow 2
This Month Stack Overflow 2


by anonymous   2017-08-20

I will paste an interesting answer given by the James Gosling in the Book Masterminds of Programming.

Well, I’ve heard it said that effectively you have two compilers in the Java world. You have the compiler to Java bytecode, and then you have your JIT, which basically recompiles everything specifically again. All of your scary optimizations are in the JIT.

James: Exactly. These days we’re beating the really good C and C++ compilers pretty much always. When you go to the dynamic compiler, you get two advantages when the compiler’s running right at the last moment. One is you know exactly what chipset you’re running on. So many times when people are compiling a piece of C code, they have to compile it to run on kind of the generic x86 architecture. Almost none of the binaries you get are particularly well tuned for any of them. You download the latest copy of Mozilla,and it’ll run on pretty much any Intel architecture CPU. There’s pretty much one Linux binary. It’s pretty generic, and it’s compiled with GCC, which is not a very good C compiler.

When HotSpot runs, it knows exactly what chipset you’re running on. It knows exactly how the cache works. It knows exactly how the memory hierarchy works. It knows exactly how all the pipeline interlocks work in the CPU. It knows what instruction set extensions this chip has got. It optimizes for precisely what machine you’re on. Then the other half of it is that it actually sees the application as it’s running. It’s able to have statistics that know which things are important. It’s able to inline things that a C compiler could never do. The kind of stuff that gets inlined in the Java world is pretty amazing. Then you tack onto that the way the storage management works with the modern garbage collectors. With a modern garbage collector, storage allocation is extremely fast.

Masterminds of Programming

by anonymous   2017-08-20

1 - Reflection (as a concept) is indeed orthogonal to safety/security.

There was a big emphasis in the design of java to make it a safe platform, with static typing, security manager, disciplined usage of class loader, and no way to screw pointers/memory. You can read the interview of James Gosling in Masterminds of programming, which is interesting about that.

But the more reflective power you have the harder it is to ensure things are safe as they should. Reflection defeat notably static typing and can lead to run-time errors.

But more subtle things can happen as well. For instance class loaders -- which can be considered as reflective hook in the system -- were not designed properly in the early version of Java leading to potential type replacement. The article Dynamic class loading in the JVM, by Gilad Bracha, is insightful on such issues.

Reflection can not be turned off altogether; it's always possible to reflect on its own public fields/methods. Reflection on private structures with AccessibleObject.setAccessible can however be disabled, because it breaks encapsulation. With access to private fields, etc. inspection and modification of internal data is possible. It can lead to various malicious exploits, e.g.

  • strings are not immutable anymore and can be changed (see this question)
  • you can reveal sensible information of objects you don't own
  • ... other exploits ...

Finally there are other mechanism that put security in jeopardy, notably sun.misc.Unsafe which gives direct access to the memory -- pointers are back.

2 - Now, the question is whether reflection (in practice) leads to that many risks.

I've read the link pointed by @dbyrne but it's mostly about .net. Also I don't know exactly what is disabled for Google App. Is it the ReflectPermission only, or other permission of the security manager? One danger is clearly to get access to the file system and mess around.

The problem of access to private data and breaking encapsulation can be argued in practice. Writing secure code is indeed extremely hard, and even without changing the access modifier you can subclass classes in an inappropriate way -- unless they are final, or even better, sealed -- and pass them around. This is for instance what defensive copying try to protect against.

Type-safety is also anyway threatened by run-time error because of downcast, so this point can also be argued.

In a shared/hosted environment, the security is relative. At the language level, you can for instance not prevent a module form consuming 100% of CPU or consuming all memory up to a OutOfMemoryException. Such concerns need to be addressed by other means, typically at the OS level, with virtualization and quotas.

So my personal answer, would be: reflection is a security risk, but not that big in practice if compared to other potential attack vectors.