Java 类加载篇(二)Classpath 类路径总结
各个类加载器的类路径(Classpath)
Java Launcher(即 java
命令)启动 Java 虚拟机时,各个类加载器按以下顺序及类路径加载类:
三个类加载器使用的类路径,从以下系统属性中获取,可以通过 System.getProperty(...)
获取查看:
1 | // Bootstrap ClassLoader |
下面详细介绍各个类加载器:
Bootstrap ClassLoader
负责加载构成 Java 平台的基础类(Bootstrap classes),位于 $JAVA_HOME/jre/lib
目录,包括 rt.jar
和其它几个重要 jar 文件中的类。这些基础类包括 Java 类库(Java Class Library (JCL))的公共类,以及此库可用的私有类。
几乎所有的 Java 类库(JCL) 都存储在一个名为“rt.jar
”的 Java archive (jar) 归档文件中,该文件随 JRE 和 JDK 发行版一起提供。Java 类库(rt.jar
)位于默认的 bootstrap classpath($JAVA_HOME/jre/lib
)下,不必出现在为应用程序声明的 classpath 中。JRE 会使用引导类加载器(bootstrap class loader)找到 JCL。
Java 9 的模块系统目前已将这个单块的 rt.jar
jar 包拆分并模块化。
Extension ClassLoader
负责加载扩展 Java 平台的扩展类(Extension classes)。位于 $JAVA_HOME/jre/lib/ext
扩展目录的每个 .jar
文件都被假定为扩展文件,并使用 Java Extension Framework 扩展机制加载。
sun.misc.Launcher$ExtClassLoader
执行过程中,URLClassPath
的值如下:
例如,可以将 MySQL 厂商驱动程序 mysql-connector-java
放到该扩展目录中。
Application ClassLoader
负责加载由开发人员和第三方定义的未利用 Java 扩展机制的用户类(User classes)。
https://en.wikipedia.org/wiki/Classpath
Classpath is a parameter in the Java Virtual Machine or the Java compiler that specifies the location of user-defined classes and packages. The parameter may be set either on the command-line, or through an environment variable.
为了查找 User classes,Java Launcher(即 java
命令)将引用 User Classpath —— 一个包含了用户定义的类文件的目录、jar 包和 zip 包列表。Java Launcher(即 java
命令)将这个 User Classpath 字符串放到 java.class.path
系统属性中。该值的来源及优先级如下:
默认值“
.
”,表示当前工作目录下的所有类文件(如果在 jar 包中,则位于其下)。CLASSPATH
环境变量,覆盖默认值。1
2
3
4
5# 查看 CLASSPATH 环境变量
echo $CLASSPATH
# 设置 CLASSPATH 环境变量
set CLASSPATH=-cp
或-classpath
命令行选项,覆盖默认值以及CLASSPATH
环境变量。A semicolon (
;
) separated list of directories, JAR archives, and ZIP archives to search for class files.Specifying
classpath
overrides any setting of theCLASSPATH
environment variable. If theclasspath
option isn’t used andCLASSPATH
isn’t set, then the user class path consists of the current directory (.
).由
-jar
选项指定的 jar 包,它覆盖上述所有值。如果使用此选项,则所有用户类必须来自指定的 jar 包。Executes a program encapsulated in a JAR file. The
jarfile
argument is the name of a JAR file with a manifest that contains a line in the formMain-Class:classname
that defines the class with thepublic static void main(String[] args)
method that serves as your application’s starting point.When you use
-jar
, the specified JAR file is the source of all user classes, and other class path settings are ignored.If you’re using JAR files, then see jar.
参考:Setting the Class Path on Windows or Unix
⭐️ 注意点 1:User Classpath 使用字符串格式指定,路径不要含有空格,否则转义为 %20
之后会报错,例如:
1 | java.lang.RuntimeException: Cannot resolve classpath entry: java.lang.RuntimeException: Cannot resolve classpath entry: D:\myprogram\mybatis%20tool\mybatis-generator-gui-0.8.4\target\classes\lib\mysql-connector-java-5.1.38.jar |
⭐️ 注意点 2:每个路径使用以下方式进行分隔:
- 在类 Unix 系统中,以冒号(
:
)分隔 - 在 Windows 系统中,以分号(
;
)分隔
⭐️ 注意点 3:类文件具有反映“类的完全限定名称(class’s fully-qualified name)”的子路径名。例如 com.mypackage.MyClass
:
- 如果类存储在
/myclasses
目录,则/myclasses
必须在 User Classpath 中,并且类文件的完整路径必须为/myclasses/com/mypackage/MyClass.class
。 - 如果类存储在
myclasses.jar
中,则myclasses.jar
必须在 User Classpath 中,并且类文件必须存储myclasses.jar/com/mypackage/MyClass.class
。
下面来看几个例子,总结如下:
Unpacked Classes
假设我们有一个名为主类:HelloWorld,存储在 D:\myprogram 目录下:
1 | D:\myprogram\ |
查看 Windows 下 CLASSPATH
环境变量:
1 | $ echo $CLASSPATH |
由于 CLASSPATH
环境变量默认包含当前目录(.
),这意味着当我们的工作目录为 D:\myprogram\
时,我们不需要显式指定 CLASSPATH
:
1 | $ cd /D/myprogram |
否则,需要使用 -classpath
参数显式指定如下:
1 | $ java -classpath D:\myprogram org.mypackage.HelloWorld |
总结,设置 Classpath 的两种方式:
- 使用
CLASSPATH
环境变量 - 使用
-cp
或-classpath
命令行选项
JAR files
- 单个 jar 包:使用绝对路径指定具体某个 jar 包
- 多个 jar 包:使用绝对路径加上通配符
*
META-INF/MANIFEST.MF
如果程序已经打成 jar 包,需要使用清单文件指定入口类及 CLASSPATH
,并使用 java -jar
命令启动。例如 Tomcat 的 bootstrap.jar
引导包:
1 | ...... |
例子
Spring Boot 配置文件
Spring Boot will automatically find and load
application.properties
andapplication.yaml
files from the following locations when your application starts:
- The classpath root
- The classpath
/config
packageThe list is ordered by precedence (with values from lower items overriding earlier ones).
参考:External Application Properties
IDEA 如何查找类?
首先,为 IDEA 平台配置上你所拥有的 JDK 及路径:
然后,为你的项目指定一个默认 SDK:
搞掂之后,IDEA 会为项目载入指定版本的 SDK,将基础目录 jre/lib/
的 Bootstrap classes 和扩展目录 jre/lib/ext/
的 Extension classes 加入 classpath:
参考
https://docs.oracle.com/en/java/javase/11/tools/java.html
https://docs.oracle.com/en/java/javase/11/tools/jar.html
1 | # Lists the table of contents for the archive. |
Setting the Class Path on Windows or Unix
http://cr.openjdk.java.net/~mr/jigsaw/ea/module-summary.html
Wikipedia