The HotSpot VM Runtime is responsible for launching the HotSpot VM and the shutdown of the HotSpot VM. This section provides an overview of what occurs within the HotSpot VM prior to it executing a Java program and what it does when a Java program terminates or exits. A large amount of detail is presented in this section, perhaps more than necessary for purposes of performance tuning. But it is included to give you sense of the complexity involved in the starting and stopping of a Java application.
The component that starts the HotSpot VM is called the launcher. There are several HotSpot VM launchers. The most commonly used launcher is the java command on Unix/Linux and on Windows the java and javaw commands. It is also possible to launch an embedded JVM through the JNI interface, JNI_CreateJavaVM.
In addition, there is also a network-based launcher called javaws,which is used by Web browsers to launch applets. The trailing “ws” on the javaws is often referred to as “web start.” Hence the term “Java web start” for the javaws launcher.
The launcher executes a sequence of operations to start the HotSpot VM. These steps are summarized here:
1. Parse command line options.
Some of the command line options are consumed immediately by the launcher such as -client or – server, which determines the JIT compiler to load. Other command line options are passed to the launched HotSpot VM.
2. Establish the Java heap sizes and the JIT compiler type (client or server) if these options are not explicitly specified on the command line.
If Java heap sizes and JIT compiler are not explicitly specified as a command line option, these are ergonomically established by the launcher. Ergonomic defaults vary depending on the underlying system configuration and operating system. Ergonomic choices made by the HotSpot VM.
3. Establish environment variables such as LD_LIBRARY_PATH and CLASSPATH.
4. If the Java Main-Class is not specified on the command line, the launcher fetches the Main-Class name from the JAR’s manifest.
5. Create the HotSpot VM using the standard Java Native Interface method JNI_CreateJavaVM in a newly created nonprimordial thread.
In contrast to a nonprimordial thread, a primordial thread is the first thread allocated by an operating system kernel when a new process is launched. Hence, when a HotSpot VM is launched, the primordial thread is the first thread allocated by the operating system kernel running in the newly created HotSpot VM process.
Creating the HotSpot VM in a nonprimordial thread provides the ability to customize the HotSpot VM such as changing the stack size on Windows. More details of what happens in the HotSpot VM’s implementation of JNI_CreateJavaVM are provided in the “JNI_CreateJavaVM Details” sidebar.
6. Once the HotSpot VM is created and initialized, the Java Main-Class is loaded and the launcher gets the Java main method’s attributes from the Java Main-Class.
7. The Java main method is invoked in the HotSpot VM using the Java Native Interface method CallStaticVoidMethod passing it the marshaled arguments from the command line.
At this point the HotSpot VM is executing the Java program specified on the command line.
Once a Java program, or Java main method completes its execution, the HotSpot VM must check and clear any pending exceptions that may have occurred during the program’s or method’s execution. Additionally, both the method’s exit status and program’s exit status must be passed back to their caller’s. The Java main method is detached from the HotSpot VM using the Java Native Interface method DetachCurrentThread. When the HotSpot VM calls DetachCurrentThread, it decrements the thread count so the Java Native Interface knows when to safely shut down the HotSpot VM and to ensure a thread is not performing operations in the HotSpot VM along with there being no active Java frames on its stack. Specific details of the operations performed by the HotSpot VM’s Java Native Interface method implementation of DestroyJavaVM is described in the “DestroyJavaVM Details” sidebar.
The HotSpot VM’s implementation of the JNI_CreateJavaVM method performs the following sequence of operations when it is called during the launch of the HotSpot VM.
1. Ensure no two threads call this method at the same time and only one HotSpot VM instance is created in the process.
Because the HotSpot VM creates static data structures that cannot be reinitialized, only one HotSpot VM can be created in a process space once a certain point in initialization is reached. To the engineers who develop the HotSpot VM this stage of launching a HotSpot VM is referred to as the “point of no return.”
2. Check to make sure the Java Native Interface version is supported, and the output stream is initialized for garbage collection logging.
3. The OS modules are initialized such as the random number generator, the current process id, high-resolution timer, memory page sizes, and guard pages. Guard pages are no-access memory pages used to bound memory region accesses. For example, often operating systems put a guard page at the top of each thread stack to ensure references off the end of the stack region are trapped.
4. The command line arguments and properties passed in to the JNI_CreateJavaVM method are parsed and stored for later use.
5. The standard Java system properties are initialized, such as java.version, java.vendor, os.name, and so on.
6. The modules for supporting synchronization, stack, memory, and safepoint pages are initialized.
7. Libraries such as libzip, libhpi, libjava, and libthread are loaded.
8. Signal handlers are initialized and set.
9. The thread library is initialized.
10. The output stream logger is initialized.
11. Agent libraries (hprof, jdi), if any are being used, are initialized and started.
12. The thread states and the thread local storage, which holds thread specific data required for the operation of threads, are initialized.
13. A portion of the HotSpot VM global data is initialized such as the event log, OS synchronization primitives, perfMemory (performance statistics memory), and chunkPool (memory allocator).
14. At this point, the HotSpot VM can create threads. The Java version of the main thread is created and attached to the current operating system thread. However, this thread is not yet added to the known list of threads.
15. Java level synchronization is initialized and enabled.
16. bootclassloader, code cache, interpreter, JIT compiler, Java Native Interface, system dictionary, and universe are initialized.
17. The Java main thread is now added to the known list of threads. The universe, a set of required global data structures, is sanity checked. The HotSpot VMThread, which performs all the HotSpot VM’s critical functions, is created. At this point the appropriate JVMTI events are posted to notify the current state of the HotSpot VM.
18. The following Java classes java.lang.String, java.lang.System, java.lang.Thread, java.lang.ThreadGroup, java.lang.reflect.Method, java.lang.ref.Finalizer, java.lang.Class, and the rest of the Java System classes are loaded and initialized. At this point, the HotSpot VM is initialized and operational, but not quite fully functional.
19. The HotSpot VM’s signal handler thread is started, the JIT compiler is initialized, and the HotSpot’s compile broker thread is started. Other HotSpot VM helper threads such as watcher threads and stat sampler are started. At this time the HotSpot VM is fully functional.
20. Finally, the JNIEnv is populated and returned to the caller and the HotSpot VM is ready to service new JNI requests.
The DestroyJavaVM method can be called from the HotSpot launcher to shut down the HotSpot VM when errors occur during the HotSpot VM launch sequence. The DestroyJavaVM method can also be called by the HotSpot VM during execution, after the HotSpot VM has been launched, when a very serious error occurs.
The shutdown of the HotSpot VM takes the following steps through the DestroyJavaVM method:
1. Wait until there is only one nondaemon thread executing noting that the HotSpot VM is still functional.
2. Call the Java method java.lang.Shutdown.shutdown(), which invokes the Java level shutdown hooks and runs Java object finalizers if finalization-on-exit is true.
3. Prepare for HotSpot VM exit by running HotSpot VM level shutdown hooks (those that were registered through JVM_OnExit()), stop the following HotSpot VM threads: profiler, stat sampler, watcher, and garbage collector threads. Post status events to JVMTI, disable JVMTI, and stop the Signal thread.
4. Call the HotSpot method JavaThread::exit() to release Java Native Interface handle blocks, remove guard pages, and remove the current thread from known threads list. From this point on the HotSpot VM cannot execute any Java code.
5. Stop the HotSpot VM thread. This causes the HotSpot VM to bring the remaining HotSpot VM threads to a safepoint and stop the JIT compiler threads.
6. Disable tracing at the Java Native Interface, HotSpot VM, and JVMTI barriers.
7. Set HotSpot “vm exited” flag for threads that may be running in native code.
8. Delete the current thread.
9. Delete or remove any input/output streams and release PerfMemory (performance statistics memory) resources.
10. Finally return to the caller.