Java source code analysis-JVM. dll Loading Process

Source: Internet
Author: User
Tags unsupported
Brief Introduction
Java.exe is the execution program of the Java classfile.
An execution shell that loads JVM. dll (in windows, the following uses Windows as an example,
Linux and Solaris are actually similar, for: libjvm. So), this dynamic Connection Library is Java
The actual operation of the virtual machine. This document describes how the java. exe program finds and loads JVM. dll.
Dynamic library, and call it for class file processing.

Source code
Code analyzed in this article: javatm 2 SDK, Standard Edition, v1.4.2 FCs
Community source release, which can be downloaded from the sun official website. The main source code for analysis is:
J2se/src/share/bin/Java. c
J2se/src/Windows/bin/java_md.c

What is Java. C?
'Java project' source code
'Java program ', which includes the java.exe/javac.exe/javadoc.exe and Java. C sources in JDK.
Use the java_args macro in the code to control the generated code. If the macro is not defined, compile the file
To become java.exe otherwise, compile the file to control the generation of other 'java project '.
For example:
J2se/make/Java/javac/makefile (this is the javac compilation file:
$ (CD).../../Sun/javac; $ (make) $ @ release = $ (release) full_version = $ (full_version)
J2se/make/Sun/javac/makefile (called by the makefile above:
Java_args = "{/"-J-ms8m/",/" com. Sun. Tools. javac. Main /"}"
The javac.exe program generated by the same java.c Code directly calls the Java class method:
Com. Sun. Tools. javac. Main, so that it is executed like an EXE file that runs directly,
The java.exe program of java_argsis not specified, it will call the class method passed in the parameter.

Start with the main entry function of Java. C.
The previous section in the main () function deals with the re-allocation of parameter pointers.
Then call the function createexecutionenvironment, which is mainly used to find
Directory, And the JVM. dll Virtual Machine core dynamic connection library file path. Depending on the operating system,
This function has different implementation versions, but the general processing logic is the same. Let's take a look at the functions in windows.
(J2se/src/Windows/bin/java_md.c ).

The createexecutionenvironment function is mainly divided into three steps:
A. Find the JRE path.
B. Load the Virtual Machine Dynamic Connection Library (JVM. dll) parameter specified in JVM. cfg.
C. Obtain the JVM. dll file path.

Implementation:
A. Find the JRE path through the function: getjrepath in java_md.c.
This function first calls the getapplicationhome function, and the getapplicationhome function calls windows
Api getmodulefilenameobtains the absolute path of the java.exe program. The following uses the JDK installation path as an example,
"D:/Java/j2sdk1.4.2 _ 04/bin/java.exe", and then remove the file name from the absolute path:
"D:/Java/j2sdk1.4.2 _ 04/bin", and the last-level directory will be removed. The absolute path is:
"D:/Java/j2sdk1.4.2 _ 04 ".
Then, the getjrepath function continues to judge the java. dll combined by the obtained path +/bin/Java. dll.
Whether the file exists. If yes, "d:/Java/j2sdk1.4.2 _ 04" is the JRE path. Otherwise, the result is obtained.
"D:/Java/j2sdk1.4.2 _ 04" path +/JRE/bin/Java. dll file?
"D:/Java/j2sdk1.4.2 _ 04/JRE" is the JRE path. If neither of the above conditions exists
Search in the table (see the getpublicjrehome function ).

Function: getpublicjrehome first
HKEY_LOCAL_MACHINE/software/kerberoft/Java Runtime Environment/CurrentVersion
If the key value is "Current JRE version number", determine whether "Current JRE version number" is 1.4 as the version number. If yes
Take HKEY_LOCAL_MACHINE/software/javasoft/Java Runtime Environment/"Current JRE version number"
/Javahome is in the JRE path.

The JRE path returned by my JDK is "D:/Java/j2sdk1.4.2 _ 04/JRE ".

B. The configuration file for loading the dynamic Connection Library of the JVM. cfg virtual machine is implemented through the function readknownvms in Java. C.
.
This function first combines the absolute path of the JVM. cfg file, JRE path +/lib +/arch (CPU architecture) +/JVM. cfg
Arch (CPU architecture) is determined by the getarch function in java_md.c.
There are only two scenarios: 'ia64' for win64 and 'i386' for other scenarios '. I use i386, so JVM. cfg
The absolute path of the file is D:/Java/j2sdk1.4.2 _ 04/JRE/lib/i386/JVM. cfg ". The file content is as follows:
Below:

#
# @(#)jvm.cfg   1.7 03/01/23
#
# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
# SUN PROPRIETARY/CONFIDENTIAL. Use is 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 its format are UNSUPPORTED and
# WILL GO AWAY in a future release.
#
# You may also select a JVM in an arbitrary location with the
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
# and may not be available in a future release.
#
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR

(If you are careful, we will find that in the JDK directory, my options are: "D:/Java/j2sdk1.4.2 _ 04/JRE/bin/client" and "D: /Java/j2sdk1.4.2 _ 04/JRE/bin/Server both directories have JVM. DLL file. Java manages these different versions of JVM. dll through the JVM. cfg configuration file .)

The readknownvms function reads the configuration content in this file into a global variable of the JVM configuration structure. This function skips the annotation (the row starting with '#') first ), then read the JVM parameters specified in the row starting with '-'. Each row contains a JVM information. The first part is the JVM Virtual Machine name, and the second part is the configuration parameters, such as the line:
For "-client known", "-client" is the virtual machine name, "known" is the configuration type parameter, and "known"
Indicates that the JVM. dll of the virtual machine exists, and "aliased_to" indicates the alias of another JVM. dll, "Warn"
Indicates that the JVM. dll of the virtual machine does not exist, but other existing JVM. dll will be used in the runtime to replace the execution, and "error"
It also indicates that the JVM. dll of this type of virtual machine does not exist and will not be replaced by the existing JVM. dll during runtime, and an error is thrown directly.
Information.

When running the Java program, specify the virtual machine used for judgment by Java. function in C: checkjvmtype. This function checks whether JVM parameters are specified in the Java running parameters and then the JVM read from the readknownvms function. the CFG data structure is searched to specify different JVM types. DLL ). There are two ways to specify the JVM type, one is based on JVM. specify the JVM name in the cfg file. The second method is to directly specify the name. The methods they run are "Java-j <JVM. in CFG, the JVM name is> "," Java-xxaltjvm = <JVM type Name> ", or" Java-J-xxaltjvm = <JVM type Name> ". For the first parameter transfer method, the checkjvmtype function takes the JVM name after the '-J' parameter, then, find from the known JVM configuration parameters. If the same name is found, remove the '-' before the JVM name to directly return the value. The second method, the JVM type name after "-xxaltjvm =" or "-J-xxaltjvm =" is directly returned. If no one of the above two methods is specified when running Java, checkjvmtype takes the JVM name in the first configuration in the configuration file, and removes '-' before the name to return this value. The Return Value of the checkjvmtype function is combined with the JRE path in the following function to form the absolute path of JVM. dll.

For example, if "Java-J-client test" is used to run a Java program, readknownvms reads the parameter "-client" and searches for the JVM. whether the JVM name is "-client" is included in the parameters read by CFG. If yes, the "-" before the JVM name is removed and the "client" is directly returned "; if you use the following parameters when running a Java program:
"Java-xxaltjvm = D:/Java/j2sdk1.4.2 _ 04/JRE/bin/client test", readknownvms
"D:/Java/j2sdk1.4.2 _ 04/JRE/bin/client" is returned directly. If the preceding parameters are not included, execute the following command:
"Java test", because the first JVM that exists in the JVM. cfg configuration file is "-client", so the Function
Readknownvms also removes "-" before the JVM name and returns "client ". In fact, these three cases are all used.
The JVM dynamic Connection Library "D:/Java/j2sdk1.4.2 _ 04/JRE/bin/client/JVM. dll" processes the class test. See the getjvmpath function below.

C. The JVM. dll file path is implemented through the function: getjvmpath in java_md.c.
In the preceding two steps, we have obtained the JRE path and JVM type string. The getjvmpath function judges checkjvmtype.
Whether the returned JVM type string contains '/' or '/'. If yes, the JVM type string +/JVM is used. DLL is the full path of JVM. Otherwise, the JRE path +/bin +/JVM string +/JVM is used. DLL is the full path of JVM.

Take a look at the example above. In the first case, the JVM. dll path of "Java-J-client test" is:
JRE path +/bin +/JVM type string +/JVM. dll according to my JDK path, it is:
"D:/Java/j2sdk1.4.2 _ 04/JRE" + "/bin" + "/client" + "/JVM. dll ".
In the second case, the path "Java-xxaltjvm = D:/Java/j2sdk1.4.2 _ 04/JRE/bin/client test" is:
JVM type string +/JVM. dll: "D:/Java/j2sdk1.4.2 _ 04/JRE/bin/client" + "/JVM. dll"
The third case is "Java test": "D:/Java/j2sdk1.4.2 _ 04/JRE" + "/bin" + "/client"
+ "/JVM. dll" is the same as Case 1. Therefore, all three cases are the JVM dynamic connection library called "D:/Java/
J2sdk1.4.2 _ 04/JRE/bin/client/JVM. dll "processes the test class.

Let's further verify:
Open the CMD console:

Set Java load debugging
E:/work/java_research> SET _ java_launcher_debug = 1
Scenario 1
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:
Versions 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]
Case 2
E:/work/java_research> 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:
Versions 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 3
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 loadjavavm
JavaVM ARGs:
Versions 0x00010002, ignoreunrecognized is jni_false, noptions is 2
Option [0] = '-djava. Class. Path = .'
Option [1] = '-dsun. java. Command = test. scandirectory'
50080 micro seconds to 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]
The three JVM paths are:
JVM path is D:/Java/j2sdk1.4.2 _ 04/JRE/bin/client/JVM. dll

Other cases
E:/work/java_research> 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:
Versions 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:
Versions 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]

As shown above, if multiple JDK or JRE versions are installed, use "Java-xxaltjvm ="
You can use the absolute path to specify other versions of JVM. dll. It is still to be tested if it can be run.

Let's go back to the main function of Java. C to see how JVM. dll is loaded and mounted for execution.

This operation is roughly divided into three steps:
A. Load the dynamic Connection Library of JVM. dll.
B. initialize JVM. dll and mount it to the jnienv (JNI call interface) instance.
C. Call the jnienv instance to load and process the class.

Implementation:
A. loading the dynamic Connection Library of JVM. dll is implemented by calling the loadjavavm function in java_md.c by the main function.
The main function first constructs a local variable of the invocationfunctions structure.
The structure has two function pointers:

typedef struct {
    CreateJavaVM_t CreateJavaVM;
    GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
} InvocationFunctions;

The loadjavavm function first calls the Windows API function: loadlibrary loads the dynamic Connection Library of JVM. dll,
Then, export the jni_createjavavm and jni_getdefajavjavavminitargs functions in JVM. dll.
Functions attached to the createjavavm and getdefajavjavavminitargs variables of invocationfunctions
Pointer variable. The installation of JVM. dll is completed.

B. initialize JVM. dll and mount it to the jnienv (JNI call interface) instance through the functions in Java. C:
Initializejvm completed.
The main method first defines a pointer to the jnienv structure. The jnienv structure defines many
Class file, find class methods, call class methods related to function pointer variables. Initializejvm will call the above
To mount the JVM. in DLL, The createjavavm method of the invocationfunctions structure variable of jni_createjavavm calls JVM. in DLL, The jni_createjavavm function returns an instance of the jnienv structure to the pointer of the jnienv structure in main. In this way, after the jnienv pointer in main obtains the jnienv instance, you can start to process the class file.

C. Call the jnienv instance to load and process the class.
A) execute the jar package.
If a jar package is executed, the main function calls Java. function in C: getmainclassname, which is constructed using a jnienv instance and called Java class: Java. util. jar. the getmanifest () method in jarfile and getattributes ("Main-class") value from the returned manifest object, that is, the file in the jar package:
The main Class Name of the main-class specified by META-INF/manifest. MF serves as the main class for running.
The main function then calls the loadclass method in Java. C to load the main class (using findclass of the jnienv instance ).
B) Execute the class method.
The main function directly calls the loadclass method in Java. C to load the class.

Then the main function calls the getstaticmethodid method of the jnienv instance to find the loaded class main class.
The "public static void main (string [] ARGs)" method determines whether the method is a public method, and then calls the callstaticvoidmethod method of the jnienv instance to call the main method of the Java class.

Summary
The code analysis above shows several problems.
A. Why does JDK and JRE not necessarily be installed and copied directly to the hard disk? You can set the PATH environment variable. Because the first option for obtaining jretries for Java Runtime is directly determined by passing the absolute path of java.exe, If you modify the registry option without setting the PATH environment variable, you can find the JRE path. The modification method is as follows:
First, copy java.exe to any directory, copy it to E:/temp, and run the following command in cmd:
Clear Path Environment Variables
E:/temp> set Path =
E:/temp> JAVA
Error opening registry key 'Software/javasoft/Java Runtime Environment'
Error: cocould not find java. dll
Error: cocould not find Java 2 Runtime Environment.

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"

The execution result is as follows:

E:/temp>java
Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)

where options include:
    -client       to select the "client" VM
    -server       to select the "server" VM
    -hotspot      is a synonym for the "client" VM  [deprecated]
                  The default VM is client.

    -cp <class search path of directories and zip/jar files>
    -classpath <class search path of directories and zip/jar files>
                  A ; separated list of directories, JAR archives,
                  and ZIP archives to search for class files.
    -D<name>=<value>
                  set a system property
    -verbose[:class|gc|jni]
                  enable verbose output
    -version      print product version and exit
    -showversion  print product version and continue
    -? -help      print this help message
    -X            print help on non-standard options
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable assertions
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable assertions
    -esa | -enablesystemassertions
                  enable system assertions
    -dsa | -disablesystemassertions
                  disable system assertions

Bw.java.exe loads and executes Java programs through the JVM. cfg file or directly specifying the JVM. dll path.
See the example above.
C. JVM. dll of different implementation versions must have an export function named jni_createjavavm,
Java.exe obtains the jnienv call interface by calling this function to load and execute the class. This
Functions are also the starting point for us to study Java VM implementation skills.
The jni_createjavavm function is located in the hotspot/src/share/Vm/prims/JNI. cpp file.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.