java -jar 启动程序 / 设置 classpath
前言
- 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。
java 设置路径的方法
设置 bootclasspath
参考这里
设置 Extensions JAR files
参考这里
设置 classpath
参考这里
测试程序
创建 maven 项目 PrintPath,代码如下:
import java.io.File;
public class Test {
public static void main(String[] args) {
printPath("java.home");
printPath("sun.boot.class.path");
printPath("java.ext.dirs");
printPath("java.class.path");
}
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);
}
}
}
运行结果
cmd> java -jar target\PrintPath.jar
java.home:
- C:\Program Files\Java\jre1.8.0_144
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
java.ext.dirs:
- C:\Program Files\Java\jre1.8.0_144\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
java.class.path:
- target\PrintPath.jar
java -jar 启动时,-cp 参数无效
使用 -jar 选项(形如:java -jar xxx.jar )来运行一个可执行的 jar 包时,-jar 会覆 -cp 的值。
cmd> java -cp D:\java_ext\sunec.jar -jar target\PrintPath.jar
java.home:
- C:\Program Files\Java\jre1.8.0_144
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
java.ext.dirs:
- C:\Program Files\Java\jre1.8.0_144\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
java.class.path:
- target\PrintPath.jar
-cp参数无效
jar 文件的 Class-Path
在 jar 中存在一个名为 META-INF\MANIFEST.MF 的文件,该文件中有个名为 Class-Path 的属性。Class-Path 的属性中的 jar 会被加载。
java -jar 启动程序时,设置 classpath 的方法
方法 1:修改 bootclasspath
此种方法可以添加少量的 jar 文件。当 jar 文件很多时,应该也可以。
cmd> java -Xbootclasspath/a:.\lib2\xx1.jar;.\lib2\xx2.jar;. -jar target\PrintPath.jar
java.home:
- C:\Program Files\Java\jre1.8.0_144
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
- .\lib2\xx1.jar
- .\lib2\xx2.jar
- .
java.ext.dirs:
- C:\Program Files\Java\jre1.8.0_144\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
java.class.path:
- target\PrintPath.jar
- 添加 jar 文件
- 添加配置文件目录
- 添加 class 文件目录
方法 2:修改 Extensions JAR files
此种方法可以添加 jar 所在的目录。当 jar 文件很多时,比较友好。但是,需要注意:尽量将java自带的lib\ext目录带上。
cmd> java -Djava.ext.dirs="%JAVA_HOME%jre\lib\ext;.\lib" -jar target\PrintPath.jar
java.home:
- C:\Program Files\Java\jre1.8.0_144
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
java.ext.dirs:
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext
- .\lib2
java.class.path:
- target\PrintPath.jar
方法 3:修改 classpath
java -jar 方式启动程序时,-cp 参数是无效的,则不能通过 - cp 参数设置 classpath。其替代方法是,在 JAR 中的 META-INF\MANIFEST.MF 文件里设置 Class-Path。
推荐此法:在 JAR 中的 META-INF\MANIFEST.MF 文件里设置 Class-Path。
springboot 项目怎么做?
springboot 项目时不需要处理。确实需要处理时,参考这里。
PS:确保 springboot 项目的 POM.xml 中包含了 spring-boot-maven-plugin 插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
maven 项目打包时,由 maven 生成 META-INF\MANIFEST.MF 文件且设置 Class-Path
修改 POM.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 生成manifest,假定依赖的jar都在与本程序同目录的lib目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib</classpathPrefix>
<mainClass>test.Test</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- 将依赖的jar拷贝到target/lib目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
无法重新打包时,修改 META-INF\MANIFEST.MF 文件且设置 Class-Path
尝试手动编辑 MANIFEST.MF:
尽量选择个靠谱的压缩包操作软件,比如 winrar。
扩展知识(转)
自 JDK 1.2 以后,JVM 采用了委托 (delegate) 模式来载入 class.采用这种设计的原因可以参考 http://java.sun.com/docs/books/tutorial/ext/basics/load.html
Java 虚拟机 (JVM) 寻找 Class 的顺序:
1. Bootstrap classes
属于 Java 平台核心的 class, 比如 java.lang.String 等。及 rt.jar 等重要的核心级别的 class. 这是由 JVM Bootstrap class loader 来载入的。一般是放置在 {java_home}\jre\lib 目录下
2. Extension classes
基于 Java 扩展机制,用来扩展 Java 核心功能模块。比如 Java 串口通讯模块 comm.jar. 一般放置在 {Java_home}\jre\lib\ext 目录下
3. User classes
开发人员或其他第三方开发的 Java 程序包。通过命令行的 - classpath 或 - cp, 或者通过设置 CLASSPATH 环境变量来引用.JVM 通过放置在 {java_home}\lib\tools.jar 来寻找和调用用户级的 class. 常用的 javac 也是通过调用 tools.jar 来寻找用户指定的路径来编译 Java 源程序。这样就引出了 User class 路径搜索的顺序或优先级别的问题.
- 3.1 缺省值:调用 Java 或 javawa 的当前路径 (.), 是开发的 class 所存在的当前目录
- 3.2 CLASSPATH 环境变量设置的路径。如果设置了 CLASSPATH, 则 CLASSPATH 的值会覆盖缺省值
- 3.3 执行 Java 的命令行 - classpath 或 - cp 的值,如果制定了这两个命令行参数之一,它的值会覆盖环境变量 CLASSPATH 的值
- 3.4 -jar 选项:如果通过 java -jar 来运行一个可执行的 jar 包,这当前 jar 包会覆盖上面所有的值。换句话说,-jar 后面所跟的 jar 包的优先级别最高,如果指定了 - jar 选项,所有环境变量和命令行制定的搜索路径都将被忽略.JVM APPClassloader 将只会以 jar 包为搜索范围.
有关可执行 jar 有许多相关的安全方面的描述,可以参考 http://java.sun.com/docs/books/tutorial/jar/ 来全面了解.
这也是为什么应用程序打包成可执行的 jar 包后,不管你怎么设置 classpath 都不能引用到第三方 jar 包的东西了.
java -jar 启动程序 / 设置 classpath_java -jar classpath-CSDN 博客
java bootclasspath_xbootclasspath-CSDN 博客
前言
- jdk1.8
查看 bootclasspath
创建项目 BootstrapClassPath,代码如下:
import java.io.File;
public class Test {
public static void main(String[] args) {
printPath("sun.boot.class.path");
}
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);
}
}
}
执行结果:
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
修改 bootclasspath
- -Xbootclasspath: 完全取代基本核心的 Java class 搜索路径。不常用(慎用), 否则要重新写所有 Java 核心 class
- -Xbootclasspath/a: 后缀。在 bootclasspath 后面添加。常用!!
- -Xbootclasspath/p: 前缀。在 bootclasspath 前面添加。不常用,避免引起不必要的冲突。
-Xbootclasspath/a 示例
cmd> java -Xbootclasspath/a:.\lib\xxx.jar;BootstrapClassPath.jar test.Test
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
- ./lib/xxx.jar
- BootstrapClassPath.jar
- .
/lib/xxx.jar;BootstrapClassPath.jar被添加到了sun.boot.class.path后面 - 前面的源码打包到了
BootstrapClassPath.jar中
-Xbootclasspath/p 示例
cmd> java -Xbootclasspath/p:.\lib\xxx.jar;BootstrapClassPath.jar test.Test
sun.boot.class.path:
- ./lib/xxx.jar
- BootstrapClassPath.jar
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
- .
/lib/xxx.jar;BootstrapClassPath.jar被添加到了sun.boot.class.path前面 - 前面的源码打包到了
BootstrapClassPath.jar中
(可以)添加.class 文件目录
cmd> java -Xbootclasspath/a:.\target\classes test.Test
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
- .\target\classes
(可以)添加.yml、.xml、.properties(或其它配置文件)文件目录
cmd> java -Xbootclasspath/a:.\target\conf test.Test
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
- .\target\conf
(可以)添加.jar 文件
cmd> java -Xbootclasspath/a:.\target\BootstrapClassPath.jar test.Test
sun.boot.class.path:
- C:\Program Files\Java\jre1.8.0_144\lib\resources.jar
- C:\Program Files\Java\jre1.8.0_144\lib\rt.jar
- C:\Program Files\Java\jre1.8.0_144\lib\sunrsasign.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jsse.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jce.jar
- C:\Program Files\Java\jre1.8.0_144\lib\charsets.jar
- C:\Program Files\Java\jre1.8.0_144\lib\jfr.jar
- C:\Program Files\Java\jre1.8.0_144\classes
- .\target\BootstrapClassPath.jar
(不可以)添加.jar 文件所在目录
cmd> java -Xbootclasspath/a:.\target test.Test
错误: 找不到或无法加载主类 test.Test
扩展知识
自 JDK 1.2 以后,JVM 采用了委托 (delegate) 模式来载入 class.
采用这种设计的原因可以参考: http://java.sun.com/docs/books/tutorial/ext/basics/load.html
java extensions JAR files_extension jar-CSDN 博客
前言
- jdk1.8
java.ext.dirs

查看 java.ext.dirs
创建 maven 项目 ExtDirs,代码如下:
import java.io.File;
public class Test {
public static void main(String[] args) {
printPath("java.home");
printPath("java.ext.dirs");
}
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);
}
}
}
执行结果:
java.home:
- C:\Program Files\Java\jdk1.8.0_144\jre
java.ext.dirs:
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
- 注意这里出现的都是目录,且目录下为
.jar文件 - C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext

C:\WINDOWS\Sun\Java\lib\ext我的电脑上没有这个目录
上面的结果是在 eclipse 中运行出来的。在命令行里运行出来的结果有些不一样,如下:
cmd> java -cp target\classes test.Test
java.home:
- C:\Program Files\Java\jre1.8.0_144
java.ext.dirs:
- C:\Program Files\Java\jre1.8.0_144\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
- 在
eclipse中的运行结果与在命令行里的运行结果的差别为 jre 目录的不同。 - 在
eclipse中,设置了 jdk,使用的是 jdk 中的 jre - 在命令行里,使用的是 jre(不是 jdk 中的 jre)(安装 jdk 时,既安装了 jdk,又安装了 jre。如果不安装 jre,会不会就一样了?)
- 尽管 jre 的路径不一样,但目录下的
.jar文件是一样的
修改 java.ext.dirs
java -Djava.ext.dirs=...
(不可以)添加.class 文件目录
cmd> java -Djava.ext.dirs=.\target\ExtDirs.jar test.Test
错误: 找不到或无法加载主类 test.Test
cmd> java -cp ./target/ExtDirs.jar test.Test
java.home:
- C:\Program Files\Java\jre1.8.0_144
java.ext.dirs:
- C:\Program Files\Java\jre1.8.0_144\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
- 不能加载
.class文件
(不可以)添加.jar 文件
cmd> java -Djava.ext.dirs=.\target\classes test.Test
错误: 找不到或无法加载主类 test.Test
cmd> java -cp .\target\classes test.Test
java.home:
- C:\Program Files\Java\jre1.8.0_144
java.ext.dirs:
- C:\Program Files\Java\jre1.8.0_144\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
- 不能加载
.jar文件
(可以)添加.jar 文件所在目录
cmd> java -Djava.ext.dirs=.\target test.Test
java.home:
- C:\Program Files\Java\jre1.8.0_144
java.ext.dirs:
- ./target
cmd> java -cp .\target\* test.Test
java.home:
- C:\Program Files\Java\jre1.8.0_144
java.ext.dirs:
- C:\Program Files\Java\jre1.8.0_144\lib\ext
- C:\WINDOWS\Sun\Java\lib\ext
- 在
./target目录下包含ExtDirs.jar。ExtDirs.jar中的入口程序为test.Test。
尽量将 java 自带的 lib\ext 目录带上
cmd> java -Djava.ext.dirs="%JAVA_HOME%jre\lib\ext;.\target" -cp target\classes test.Test
java.home:
- C:\Program Files\Java\jre1.8.0_144
java.ext.dirs:
- C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext
- .\target
-Djava.ext.dirs="%JAVA_HOME%jre\lib\ext;D:\java_ext"加引号是因为%JAVA_HOME%包含空格。- 尽量将 java 自带的
lib\ext目录带上。否则,在用其下.jar时,会发生错误。如果确定不需要其下.jar时,则不用加上 java 自带的lib\ext目录。 - 缺少 java 自带的
lib\ext目录时,java.security包不能使用(NoSuchAlgorithmException)。
扩展知识
自 JDK 1.2 以后,JVM 采用了委托 (delegate) 模式来载入 class.
采用这种设计的原因可以参考: http://java.sun.com/docs/books/tutorial/ext/basics/load.html
参考
https://blog.csdn.net/scugxl/article/details/43240991
https://docs.oracle.com/javase/tutorial/ext/basics/install.html
查看 classpath
创建 maven 项目 ClassPath,代码如下:
import java.io.File;
public class Test {
public static void main(String[] args) {
printPath("java.class.path");
}
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);
}
}
}
执行结果:
java.class.path:
- D:\sde\git-workspace\JavaSamples\java-samples-ClassPath\ClassPath\target\classes
D:\sde\git-workspace\JavaSamples\java-samples-ClassPath\ClassPath是项目目录- 项目为 maven 项目
修改 classpath
java -classpath ...java -cp ...是java -classpath ...的简写
(可以)添加.class 文件目录
cmd> java -cp target\classes test.Test
java.class.path:
- target\classes
(可以)添加.jar 文件
cmd> java -cp target\ClassPath.jar test.Test
java.class.path:
- target\ClassPath.jar
(不可以)添加.jar 文件所在目录
cmd> java -cp target test.Test
错误: 找不到或无法加载主类 test.Test
cmd> java -cp target\ test.Test
错误: 找不到或无法加载主类 test.Test
cmd> java -cp target\*.jar test.Test
错误: 找不到或无法加载主类 test.Test
java -cp无法自动查找target目录下的.jar文件,并加载。
(可以)通配符 *
cmd> java -cp target\* test.Test
java.class.path:
- target\ClassPath.jar
cmd> java -cp target\classes\* test.Test
错误: 找不到或无法加载主类 test.Test
target\*是个特例,可以让 java 自动搜索其下的.jar文件,并加载。
【springboot】启动时指定 lib 目录_-dloader.path=.,lib-CSDN 博客
java -jar -Dloader.path=lib xxxApp.jar
java -jar -Dloader.path=lib,templates,static xxxApp.jar

浙公网安备 33010602011771号