前言
- 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的路径,因此报错。