Figure 5-2. Runtime data areas shared among all threads.
Figure 5-3. Runtime data areas exclusive to each thread.
The Class Loader Subsystem
Loading, Linking and Initialization
The class loader subsystem is responsible for more than just locating and importing the binary data for classes. It must also verify the correctness of imported classes, allocate and initialize memory for class variables, and assist in the resolution of symbolic references. These activities are performed in a strict order:
- Loading: finding and importing the binary data for a type
- Linking: performing verification, preparation, and (optionally) resolution
- Verification: ensuring the correctness of the imported type
- Preparation: allocating memory for class variables and initializing the memory to default values
- Resolution: transforming symbolic references from the type into direct references.
- Initialization: invoking Java code that initializes class variables to their proper starting values.
Figure 5-5. Splitting an object across a handle pool and object pool.
Figure 5-6. Keeping object data all in one place.
Figure 5-7. Keeping the method table close at hand.
Figure 5-8. One possible heap representation for arrays.
The Program Counter
Each thread of a running program has its own pc register, or program counter, which is created when the thread is started. The pc register is one word in size, so it can hold both a native pointer and a
returnAddress. As a thread executes a Java method, the pc register contains the address of the current instruction being executed by the thread. An “address” can be a native pointer or an offset from the beginning of a method’s bytecodes. If a thread is executing a native method, the value of the pc register is undefined.