哪里有 class 告诉我?

说明

本文探讨的 JVM 参数和代码示例均适用于 JDK 8 版本。

用户类的位置

用户类是指由开发者或第三方定义的类,它们通过应用程序类加载器进行加载。

在 Java 程序中,可以通过设置 CLASSPATH 环境变量或 JVM 启动参数 -cp-classpath 来指定类加载路径。这些配置的优先级从低到高,后设置的配置会覆盖先前的配置,默认路径为当前目录。

image

接下来,我们将验证默认值和优先级。

验证默认路径为当前路径

考虑一个名为 Temp.java 的类,它不位于任何包路径中:

public class Temp {  
    public static void main(String[] args) {  
        System.out.println("Executed!");  
    }  
}

在没有设置 CLASSPATH 环境变量的情况下,将编译后的 Temp.class 文件放置在 E 盘,然后执行 java Temp 命令,程序能够正常运行。这说明类加载器是根据默认的类路径值找到该 Class 文件的,而这个默认值就是当前路径。

image

根据官方文档,Java 程序启动时会将 class path 的值放入 java.class.path 系统属性中。

image

修改代码,在程序运行时打印实际的 class path:

public class Temp {  
    public static void main(String[] args) {  
        System.out.println("Executed!");  
        System.out.println("The actual class path is :" + System.getProperty("java.class.path"));  
    }  
}

执行结果表明,打印的结果是当前路径。

验证 CLASSPATH 环境变量的作用

在 Windows 系统中设置 CLASSPATH 环境变量,因为 Temp.class 文件位于 E 盘,所以环境变量也设置为 E 盘。

再次运行程序,结果表明通过配置的路径,类加载器能够找到 Temp.class 文件,并且打印的 class path 也是 E:。

验证 -cp-classpath 参数的作用

移除 CLASSPATH 环境变量,通过执行 java 命令时指定 -cp 参数来设置 class path 路径。

程序执行的效果与通过 CLASSPATH 环境变量设置相同。

验证 -cp-classpath 参数的优先级高于 CLASSPATH 环境变量

设置 CLASSPATH 环境变量为 D:,如果不带 -cp 参数执行,会提示找不到类,因为 D: 路径下没有 Temp.class 文件。

带上 -cp 参数后能够正常执行,说明 -cp 参数的配置生效了,其优先级高于 CLASSPATH 环境变量。

引导类的位置

sun.boot.class.path 系统属性的值

引导类包括构成 Java 平台的类,如 rt.jar 中的类,由引导类加载器(Bootstrap ClassLoader)加载。

如果直接在 Temp.class 文件所在的路径下执行 java Temp 命令,能够正常执行。那么 Temp 类的父类 Object 类位于 jre/lib 目录下的 rt.jar 包中,引导类加载器是如何找到并加载 Object 类的呢?

根据官方文档,引导类加载器加载的 class path 可以通过 sun.boot.class.path 系统属性获取。

public class Temp {  
    public static void main(String[] args) {  
        System.out.println("Executed!");  
        System.out.println("The actual class path is :" + System.getProperty("sun.boot.class.path"));  
    }  
}

执行结果表明输出结果中包含 rt.jar 包的绝对路径。

sun.boot.class.path 系统属性赋值源码分析

以 Windows 平台为例,分析 HotSpot 虚拟机的源码实现,涉及三个文件:

hotspot\src\share\vm\runtime\arguments.cpp
hotspot\src\share\vm\runtime\os.cpp
hotspot\src\os\windows\vm\os_windows.cpp

源代码的调用链路如下:

arguments.jpg

arguments.cpp 负责处理 JVM 启动参数,初始化 _java_home_sun_boot_class_path 系统属性。

然后调用 os_windows.cppinit_system_properties_values() 方法,在该方法中会调用 os_windows.cpp 中的 jvm_path() 方法,尝试获取 jvm.dll 的绝对路径。

然后返回到 os_windows.cppinit_system_properties_values() 方法,去除路径中的 jvm.dllserver/client

版权声明:程序员胖胖胖虎阿 发表于 2024年12月27日 下午7:11。
转载请注明:哪里有 class 告诉我? | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...