Java virtual host loading process
Briefly, well-known java.exe is a Java class file executive, but actually Java.exe program is just an enclosure, which will load jvm.dll (under Windows, under the Windows platform, under Linux and Solaris In fact, it is: libjvm.so, this dynamic connection library is the actual operation of the Java virtual machine. Wonderful Java.exe programs find and load the JVM.dll dynamic library, and call it to perform the Class file execution process. Source code, "Javatm 2 SDK, Standard Edition, V1.4.2 Fcscommunity Source Release", can be downloaded from Sun official website, the source code of the main analysis is: J2SE / SRC / Share / Bin / Java.c J2SE / SRC / Windows / bin / java_md.c 'Java program' source code so-called 'Java program', including java.exe / javaac.exe / javadoc.exe in JDK, Java_args macro to control generation Code, if the macro is not defined, compiling file control generation java.exe otherwise compiling file control to generate other 'Java programs'. For example: J2se / Make / Java / Javac / Makefile (this is a Javac compilation file): $ (cd) ../.. @ @ release = $ (substlease) full_version = $ ( Full_Version) J2SE / Make / Sun / Javac / Javac / Makefile (Call by Makefile): Java_Args = "{/" - j-ms8m / ", / "com.sun.tools.javac.main/"} " The JavaC.exe program generated by the same Java.c code will directly call the Java class method: com.sun.tools.javac.main, which makes it like a direct running EXE file, not defined Java_args Java.exe programs will call the class methods in the passing parameters. From Java.c's main entry function, the main () function is the process of reassigning parameter pointers in the main () function. Then call the function: CreateExecutionenvironment, the function mainly looks for the Directory of the Java runtime environment, and the JVM.DLL of the virtual machine core dynamic connection library file path. According to the operating system, this function has different implementations, but the general processing logic is the same, we look at the process of the Windows platform (J2SE / SRC / Windows / Bin / Java_MD.c). The CreateExecutionenvironment function is mainly divided into three steps: a, look up the JRE path. B, load the virtual machine dynamic connection library (JVM.DLL) parameter specified in JVM.CFG. C, take the jvm.dll file path. Implementation: a, lookup JRE path is made in java_md.c: getJrepath is implemented.
This function first calls the getApplicationHome function, the GetApplicationHome function calls the WindowsAPI function getModuleFileName takes the absolute path of the Java.exe program, take my JDK installation path as an example: "D: /java/j2sdk1.4.2_04/bin/java.exe" Then, then remove the file name to take the absolute path to: "D: /java/j2sdk1.4.2_04/bin", will then remove the last level directory, now the absolute path is: "D: /java/j2sdk1.4.2_04". Then the getjrepath function continues to determine if the Java.dll file that has just been taken / bin / java.dll is existing, if there is, "D: /java/J2SDK1.4.2_04" is the JRE path, otherwise it is determined " D: /java/j2sdk1.4.2_04 "Path / JRE / BIN / JAVA.DLL file exists," D: /java/j2sdk1.4.2_04/jre "is the JRE path. If the above two cases do not exist, look up from the registry (see Functions getPublicjrehome). Function: GetPublicJREHome to find HKEY_LOCAL_MACHINE / Software / JavaSoft / Java Runtime Environment / CurrentVersion key "current JRE version," judgment "current JRE version" is the version number as 1.4, if it is then taken HKEY_LOCAL_MACHINE / Software / JavaSoft / Java Runtime Environment / "Current JRE Release Number" / JavaHome is located as the JRE path. The JRE path returned by my JDK is: "D: /java/j2sdk1.4.2_04/jre". B, loading the JVM.cfg virtual machine dynamic connection library profile is implemented in java.c: ReadkNownVMS implementation. The function first combines the absolute path of the JVM.cfg file, JRE path / lib / arch (CPU architecture) / jvm.cfgarch (CPU architecture) is judged by the getarch function in java_md.c, the Windows platform in this function Only two cases: Win64 'IA64', other situations are 'i386'. My I386 so JVM.CFG file absolute path is: "D: /java/j2sdk1.4.2_04/jre/lib/i386/jvm.cfg".
The document is as follows: # # @ (#) jvm.cfg 1.7 03/01/23 # # Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. # Sun proPrietary / confidential. Uses Subject to license terms. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # List of jvms That Can Be Used as an option to java, javac, etc. # Order is important - first in this list is The default jvm. # Note That this Both this file and it wers format area unsupported and # WILL Go Away in . a future release # # You may also select a JVM in an arbitrary location with the # "-XXaltjvm =
There are two ways to specify the JVM type, one specified according to the JVM name in the jvm.cfg file, the second method is to specify directly, the methods they perform are "Java -j
So these three situations are called JVM dynamic connection library "D: /java/j2sdk1.4.2_04/jre/bin/client/jvm.dll" to process Test classes. Let's further verify: Open the CMD Console: Set Java Load Debug E: / Work / Java_RESEARCH> SET _JAVA_LAUNCHER_DEBUG = 1 A situation E: / WORK / JAVA_RESEARCH> Java -j-Client Test.scandirectory ----_ java_launcher_debug - - JRE PATH IS D: /JAVA/J2SDK1.4.2_04/JRE JVM.CFG [0] = -> - Client <- jvm.cfg [1] = -> - server <- jvm.cfg [2] = > -Hotspot <- jvm.cfg [3] = -> - Classic <- jvm.cfg [4] = -> - native <- jvm.cfg [5] = -> - Green <- 299 Micro Seconds to Parse JVM .cfg JVM path is D: /java/j2sdk1.4.2_04/jre/bin/client/jvm.dll 2897 micro seconds to LoadJavaVM JavaVM args: version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2 option [0] = '-Djava .class.path =. 'option [1] =' -Dsun.java.command = test.ScanDirectory '50001 micro seconds to InitializeJVM main-class is' test.ScanDirectory 'Apps' argc is 0 10208 micro seconds to load main class ---- Java_Launcher_Debug ---- Usage: Java Test.scandirectory Dir [Output File] Situation E: / WORK / JAVA_RESEA RCH> java -xxaltjvm = d: /java/j2sdk1.4.2_04/jre/bin/client test.scandirectory ---- Java_Launcher_Debug ---- JRE PATH IS D: /JAVA/J2SDK1.4.2_04/jre jvm.cfg [0] = -> - Client <- jvm.cfg [1] = -> - Server <- jvm.cfg [2] = -> - Hotspot <- jvm.cfg [3] = -> - Classic <- JVM .cfg [4] = -> - native <- jvm.cfg [5] = -> - Green <
- 386 micro seconds to parse jvm.cfg JVM path is D: /java/j2sdk1.4.2_04/jre/bin/client/jvm.dll 2795 micro seconds to LoadJavaVM JavaVM args: version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2 option [0] = '-djava.class.path =.' Option [1] = '-dsun.java.command = Test.scandirectory' 49978 Micro Seconds To Initializejvm main-class is' Test.scandirectory 'Apps' ARGC IS 0 9598 micro seconds to load main class ----_ JAVA_LAUNCHER_DEBUG ---- usage: java test.ScanDirectory DIR [output file] case of a three E: / work / java_research> java test.ScanDirectory ----_ JAVA_LAUNCHER_DEBUG ---- JRE Path is d: /java/j2sdk1.4.2_04/jre jvm.cfg [0] = -> - Client <- jvm.cfg [1] = -> - server <- jvm.cfg [2] = -> - Hotspot <- jvm.cfg [3] = -> - Classic <- jvm.cfg [4] = -> - native <- jvm.cfg [5] = -> - Green <- 381 micro seconds to parse jvm.cfg jvm Path is D: /java/j2sdk1.4.2_04/jre/bin/client/jvm.dll 3038 Micro Seconds to Loadjav aVM JavaVM args: version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2 option [0] = option [1] = '-Dsun.java.command = test.ScanDirectory' 50080 micro seconds to '-Djava.class.path =.' InitializeJVM main-class is' test.ScanDirectory 'Apps' argc is 0 10215 micro seconds to load main class ----_ JAVA_LAUNCHER_DEBUG ---- usage: java test.ScanDirectory DIR [output file] JVM three paths are: JVM path is d: /java/j2sdk1.4.2_04/jre/bin/client/jvm.dll Other cases E: / WORK / JAVA_RESECH>
Java -j-server test.scandirectory ----_ java_launcher_debug ---- JRE PATH IS D: /JAVA/J2SDK1.4.2_04/jre jvm.cfg [0] = -> - Client <- jvm.cfg [1] = -> - Server <- jvm.cfg [2] = -> - Hotspot <- jvm.cfg [3] = -> - Classic <- jvm.cfg [4] = -> - native <- jvm.cfg [ 5] = -> - Green <- 377 Micro Seconds to Parse Jvm.cfg JVM Path IS D: /JAVA/J2SDK1.4.2_04/jre/bin/server/jvm.dll 2985 Micro Seconds to LoadJavaVM JavaVM Args: Version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2 option [0] = '-Djava.class.path =.' option [1] = '-Dsun.java.command = test.ScanDirectory' 62382 micro seconds to InitializeJVM Main-Class is' test .ScanDirectory 'Apps' argc is 0 12413 micro seconds to load main class ----_ JAVA_LAUNCHER_DEBUG ---- usage: java test.ScanDirectory DIR [output file] E: / work / java_research> java -XXaltjvm = D: / java /J2SDK1.4.2_04/jre/bin/server test.scandirectory ----_ java_launcher_debug ---- JRE PATH IS D: / JAVA / J2SDK1.4.2_04 / jre jvm.cfg [0] = -> - Client <- jvm.cfg [1] = -> - server <- jvm.cfg [2] = -> - Hotspot <- jvm.cfg [3 ] = -> - Classic <- jvm.cfg [4] = -> - native <- jvm.cfg [5] = -> - Green <- 376 micro seconds to parse jvm.cfg JVM PATH IS D: / JAVA / j2sdk1.4.2_04 / jre / bin / server / jvm.dll 2937 micro seconds to LoadJavaVM JavaVM args: version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2 option [0] = '-Djava.class.path =.' option [1 ] = '-Dsun.java.command = Test.scandirectory'
62725 micro seconds to InitializeJVM Main-Class is' test.ScanDirectory 'Apps' argc is 0 8942 micro seconds to load main class ----_ JAVA_LAUNCHER_DEBUG ---- usage: java test.ScanDirectory DIR [output file] can be seen from the above Out, if we installed multiple JDK or JRE versions, use "java-xxaltjvm =" to specify the absolute path to other versions of JVM.dll, as for the operation, ready to be tested. Let's go back to the main function of java.c to see how the jvm.dll found on it loads the hook execution. This operation is roughly divided into three steps: a, load the JVM.dll dynamic connection library. B. Initialize JVM.DLL and hook to the JNIENV (JNI Call Interface) instance. C, call the JNIENV instance to load and process the Class class. Implementation: a, loading the JVM.dll dynamic connection library is implemented by the main function to call Java_MD.c. First, the main function of a local variable InvocationFunctions constructed structure, function pointer two InvocationFunctions structure: typedef struct {CreateJavaVM_t CreateJavaVM; GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;} InvocationFunctions; LoadJavaVM function first calls the windows API functions: LoadLibrary jvm.dll loaded dynamic link library, Then, the export function JNI_CREATEJAVAVM and JNI_GETDEFAULTJAVAVMINITARGS in JVM.dll are then connected to the CreateJavAVM and getDefaultjavavMinitargs function pointer variables of the InvocationFaultJavaVMinitargs function pointer variable. JVM.DLL load work declares completed. B, initialize JVM.dll and hook to the JNIENV (JNI Call Interface) instance is through Java.c: InitializeJVM is done. The MAIN method first defines a JNIENV structure, which defines a number of function pointer variables related to loading Class class files, lookup class methods, and call class methods in the JNIENV structure. InitializeJVM will call the CreateJavaVM method for the InvocationFunctions structure variable of JNI_CREATEJAVAVM above JVM.dll, that is, call JVM.dll, which returns an instance of the JNIENV structure to the Pointer of the JNienv structure in Main. After the Jnienv pointer in Main, you can start processing the Class files after the JNIENV instance is acquired. C, call the JNIENV instance to load and process the Class class. A) If it is a JAR package.
If it is executed, the main function calls the function in java.c: getMAINCLASSNAME, this function uses the JNIENV instance and calls Java class: java.util.jar.jarfile method getManifest () and from return from Manifest Take the value of GetAttributes ("main-class"), namely the file in the JAR package: MAIN-INF / MANIFEST.MF Specifies the main class of Main-Class as the main class of the run. Then the main function will call the LoadClass method in java.c to load the main class (FindClass using the JNIENV instance). B) If it is a Class method. The main function is directly called Java.c loadClass method to load the class. The main function calls the jnienv instance's getStaticMethodID method to find the "public static void main (string [] args) method in the loaded Class primary class, and determine if the method is a public method, then call the JAVA class. MAIN method. Summary can be seen from the above code analysis. A, why JDK and JRE do not necessarily copy to the hard disk directly to the hard drive, set the PATH environment variable. Because the preferred method of Java runs JRE path is directly determined by obtaining the Java.exe absolute path, you can also find the JRE path if the PATH environment variable is set by modifying the registry option.
The modification method is as follows: First we copied java.exe to any directory, I will copy it to E: / TEMP, run in CMD: Clear Path Environment Variables E: / Temp> SET PATH = E: / Temp> Java Error opening registry key 'Software / JavaSoft / Java Runtime Environment' Error: could not find java.dll Error:. could not find Java 2 Runtime Environment to import the following registry file (java.reg) Windows registry Editor Version 5.00 [HKEY_LOCAL_MACHINE / SOFTWARE / JavaSoft] [HKEY_LOCAL_MACHINE / SOFTWARE / JavaSoft / Java Runtime Environment] "CurrentVersion" = "1.4" [HKEY_LOCAL_MACHINE / SOFTWARE / JavaSoft / Java Runtime Environment / 1.4] "JavaHome" = "D: //java//j2sdk1.4.2_04/ / jre "Re-execution display is normal, as follows: E: / TEMP> Java usage: java [-Options] class [args ...] or java [-Options] -jar jarfile [args .. ............................... .. he default VM is client -cp