ClassLoader
java 程序的启动
1 | ## 调试模式启动 JAVA |
查找 JRE
查找当前启动的启动器所在的路径
openjdk\jdk\src\windows\bin\java_md.c
使用 WIN32 API GetModuleFileName 文件查找当前运行模块的路径。
如果 PATH 环境变量中配置了 %JAVA_HOME%/bin。其中 JAVA_HOME 为 JDK 安装的目录。
截取掉文件名和bin目录,则此时找到的 path 为 %JAVA_HOME%
查找 java.dll
在上一个步骤中,以上面的 path 为基路径,查找
因为上面的 path 是 JAVA_HOME, 其 bin 目录下是 JDK 提供的各种工具程序,并不存在 java.dll,所以最终定位到 %JAVA_HOME%/jre 这个目录下。此时找到的 JRE 就是 %JAVA_HOME%/jre 这个目录。
查找公共的 JRE
如果通过查找 java.dll 并没有找到 JRE,则这个启动器,可能在类似 c:\windows\system32\java.exe 这种形式的。自然定位不到 JRE 。
此时就开始查找公共的 JRE。
在 windows 平台上公共 JRE 的查找是通过注册表来实现的。
查找 HKEY_LOCAL_MACHINE 的 “Software\JavaSoft\Java Runtime Environment” 这个子键下面的信息。这个子键下面有
“CurrentVersion\JavaHome” 这个子键。这个子键的值就是公共的 JRE 的路径。
至此 JRE 找到了,当然如果没有找到进程直接就退出了。
查找 JVM
读取已有的 JVM
读取 %JRE_HOME%/lib/
这个文件中列出了多种可选的 JVM。最终构造好一个 JVM 列表。
1 | ## - 后面也可以直接跟 JVM 所在的路径。如果是路径,则一定要以 |
检测当前要使用的JVM
1 | /* |
获得 JVM 类型。
查找 JVM
直接查找 %JRE_HOME%\
如果 jvmtype 是全路径,则查找
如果存在则 JVM 就找到了。就是 %JRE_HOME%\
LoadJavaVM
参考openjdk\jdk\src\share\bin\java.c
通过 LoadLibrary 或者 dlopen 方法载入上面查找到的 jvm.dll.
并通过 GetProcAddress 或者 dlsym 方法查找到 jvm.dll 中实现的 “JNI_CreateJavaVM” 和 “JNI_GetDefaultJavaVMInitArgs” 方法。
初始化好一个 InvocationFunctions 结构。
AddApplicationOptions
添加三个 optionis
-Denv.class.path
env.class.path is the user’s setting of CLASSPATH
从环境变量中获得 “CLASSPATH”
-Dapplication.home
application.home is the directory where the application is installed.
获得当前执行的 java 所在的路径,通常就是 “JAVA_HOME”
-Djava.class.path
java.class.path is the classpath to where our apps’ classfiles are.
默认是 { “/lib/tools.jar”, “/classes” }, 此时会将 classpath 展开,形成 %JAVA_HOME%/lib/tools.jar 和 %JAVA_HOME%/classes 并将其添加到 java.class.path 属性中。
默认的 classpath 的设置。首先获得环境变量 CLASSPATH,如果不存在,则默认为当前上当 “.”, 将其设置到 -Djava.class.path 中。
初始化 JVM
创建一个新的线程。在新的线程调用 JavaMain 方法。
JavaMain 中调用 InitializeJVM 这个方法将通过 InvocationFunctions 的 JNI_CreateJavaVM 创建 JVM, 将初始化 JNIEnv 变量 env.
JNI_CreateJavaVM 将调用 JVM 实现,初始化好整个 JVM 环境。
通过 env 就可以使用 JNI 接口的方法,调用 JVM 方法。执行 Java 类。
调用主类的方法
由于 JVM 已经初始化了,就可以通过 env 调用 JVM 的功能了,可以执行 java 类的方法了。
执行 Main 类
1 | // java.c LoadMainClass 方法 |
ClassPath
指定 classpath 时有两种类型:
class 文件打包在 jar 或者 zip 文件中
这种类型的 classpath 直接指定文件的全路径,以 zip 或者 jar 文件名称结束。
class 文件直接存放在文件夹(目录)当中
则 classpath 是,包含 “root” package 的 文件夹,为其 classpath
运行时类的加载
默认的加载位置
如何修改
1 | -Xbootclasspath:bootclasspath |
扩展类加载
java.ext.dirs
应用类加载
java.class.path