• Field, method, and class access control modifiers must be respected.
• No unsafe casts (e.g., attempts to convert an int to a pointer).
• All branch instructions are to legal points within the same method.
Of fundamental importance is the approach to memory, and pointers. In assembly
and C/C++, integers and pointers are interchangeable, so an integer can be used as a
memory address. We can write it in assembly like this:
R e l e c t i o n
mov eax , [ STAT ] ; Move 4 bytes from addr STAT into eax
The lowest level of the Java security architecture involves the design of the Java Vir‐
tual Machine and the bytecodes it executes. The JVM does not allow any kind of
direct access to individual memory addresses of the underlying system, which pre‐
vents Java code from interfering with the native hardware and operating system.
These intentional restrictions on the JVM are reflected in the Java language itself,
which does not support pointers or pointer arithmetic.
Neither the language nor the JVM allow an integer to be cast to an object reference
or vice versa, and there is no way whatsoever to obtain an object's address in mem‐
ory. Without capabilities like these, malicious code simply cannot gain a foothold.
Recall from Chapter 2 that Java has two types of values—primitives and object refer‐
ences. Theses are the only things that can be put into variables. Note that “object
contents” cannot be put into variables. Java has no equivalent of C's struct and
always has pass-by-value semantics. For reference types, what is passed is a copy of
the reference—which is a value.
References are represented in the JVM as pointers—but they are not directly manip‐
ulated by the bytecode. In fact, bytecode does not have opcodes for “access memory
at location X.”
Instead, all we can do is access fields and methods—bytecode cannot call an arbi‐
trary memory location. This means that the JVM always knows the difference
between code and data. In turn, this prevents a whole class of stack overflow and
To apply knowledge of classloading, it's important to fully understand
This is an abstract class that is fully functional and has no abstract methods. The
abstract modifier exists only to ensure that users must subclass ClassLoader if
they want to make use of it.
In addition to the aforementioned defineClass() method, we can load classes via a
public loadClass() method. This is commonly used by the URLClassLoader sub‐
class, that can load classes from a URL or file path.
We can use URLClassLoader to load classes from the local disk like this: