0
点赞
收藏
分享

微信扫一扫

Java虚拟机(JVM)寻找Class的顺序

天际孤狼 2022-01-27 阅读 65
java

前言

  • jdk 1.8
    期望在java -jar命令执行java程序时,能够指定classpath

java 加载类的路径

java 类加载器有三个:

  • Bootstrap CLassLoader
  • ExtClassLoader
  • AppClassLoader

java 类加载器对应的路径:

  • bootclasspath:对应 Bootstrap CLassLoader。java虚拟机系统参数sun.boot.class.path。
  • Extensions JAR files:对应 Extention ClassLoader 。java虚拟机系统参数java.ext.dirs。
  • classpath:对应 AppClassLoader。java虚拟机系统参数java.class.path。

jar 中 MANIFEST.MF 文件里的 Class-Path 路径

  • 使用-jar选项(形如:java -jar xxx.jar )来运行ar时,-jar会覆-cp的值。
  • 将 MANIFEST.MF 文件里的 Class-Path 路径视作 -cp (classpath)路径。

Java虚拟机(JVM)寻找Class的顺序

Java虚拟机(JVM)按照下面的顺序依次寻找Class:

  • bootclasspath
  • Extensions JAR files
  • classpath

Java虚拟机(JVM)优先加载第一个找到的Class。

测试环境

D:/test2
├──LoadClassApp.jar
└─lib
   ├─────LoadClassModule1-1.0.jar
   └─────LoadClassModule2-1.0.jar

LoadClassApp.jar

import java.io.File;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		printPath("sun.boot.class.path");
		printPath("java.ext.dirs");
		printPath("java.class.path");

		Runnable job = (Runnable)Class.forName("test.RunService").newInstance();
		job.run();
	}
	
	public static void printPath(String name) {
		System.out.println(name + ":");
		String[] paths = System.getProperty(name).split(File.pathSeparator);
		for(String path : paths) {
			System.out.println("- " + path);
		}
	}
}

LoadClassModule1.jar

public class RunService implements Runnable{

	@Override
	public void run() {
		System.out.println("Module:LoadClassModule1");
		System.out.println("Class in  : " + this.getClass().getProtectionDomain().getCodeSource().getLocation().toString());
	}
	
}

LoadClassModule2.jar

public class RunService implements Runnable{

	@Override
	public void run() {
		System.out.println("Module:LoadClassModule2");
		System.out.println("Class in  : " + this.getClass().getProtectionDomain().getCodeSource().getLocation().toString());
	}
	
}

LoadClassApp.jar 中的MANIFEST.MF文件
在这里插入图片描述

测试1:java -jar 启动

cmd> java -jar LoadClassApp.jar
sun.boot.class.path:
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\sunrsasign.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\classes
java.ext.dirs:
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
java.class.path:
- LoadClassApp.jar
Module:LoadClassModule1
Class in  : file:/D:/test2/lib/LoadClassModule1-1.0.jar
  • LoadClassApp.jar 中的MANIFEST.MF文件起作用。
  • 在MANIFEST.MF文件的Class-Path中,LoadClassModule1-1.0.jar在LoadClassModule2-1.0.jar前面。

测试2:修改Extensions JAR files

cmd> java -Djava.ext.dirs="%JAVA_HOME%jre\lib\ext;ext-lib" -jar LoadClassApp.jar
sun.boot.class.path:
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\sunrsasign.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\classes
java.ext.dirs:
- C:\Program Files\Java\jdk1.8.0_144jre\lib\ext
- ext-lib
java.class.path:
- LoadClassApp.jar
Module:LoadClassModule2
Class in  : file:/D:/test2/ext-lib/01LoadClassModule2-1.0.jar
  • -Djava.ext.dirs=参数起作用。
  • 在ext-lib目录中,01LoadClassModule2-1.0.jar在01LoadClassModule1-1.0.jar前面。
    在这里插入图片描述

测试3:修改bootclasspath

cmd> java -Xbootclasspath/a:boot-lib\LoadClassModule2-1.0.jar;boot-lib\LoadClassModule1-1.0.jar -Djava.ext.dirs="%JAVA_HOME%jre\lib\ext;ext-lib" -jar LoadClassApp.jar
sun.boot.class.path:
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\sunrsasign.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar
- C:\Program Files\Java\jdk1.8.0_144\jre\classes
- boot-lib\LoadClassModule2-1.0.jar
- boot-lib\LoadClassModule1-1.0.jar
java.ext.dirs:
- C:\Program Files\Java\jdk1.8.0_144jre\lib\ext
- ext-lib
java.class.path:
- LoadClassApp.jar
Module:LoadClassModule2
Exception in thread "main" java.lang.NullPointerException
        at test.RunService.run(RunService.java:8)
        at test.Test.main(Test.java:12)
  • -Xbootclasspath/a:参数起作用
  • boot-lib\LoadClassModule2-1.0.jar在boot-lib\LoadClassModule1-1.0.jar前面
  • -Xbootclasspath加载的jar无法打印jar的路径,因此报错。
举报

相关推荐

0 条评论