ClassPath是Java中一个重要的环境变量,弄懂他对于Java运行环境的理解有重大的帮助
ClassPath是什么
CLASSPATH直译过来是类路径,是Java环境配置中要设置的一个环境变量,就是.class文件的路径,表示JVM从哪里去寻找要运行的class文件,CLASSPATH = D:\java
表示执行java命令时去D:\java
目录中去找需要被执行的class文件并运行。
体验package
先来体验一个正常的Java项目,目录结构如下
|
|
Student.java
内容如下
|
|
MainTest.java
内容如下
|
|
运行MainTest.java
中的main()
,可以得到
正常调用
可以看到,两个Java类处于不同的目录,也能正常调用,前提是MainTest.java
识别到了Student.java
的包路径,准确import
了com.study.school.Student
,这个包路径是package
定义的!
体验ClassPath
首先我们整个目录结构如下
|
|
我们先关注MainTest.java
,看看他的内容
|
|
很简单,只是一句输出,那么我们先执行javac
命令,将他编译为字节码文件,再使用java
命令去执行他
|
|
目前为止所有的输出都符合预期。
但同时我们也理解,一个大型的,或者可拓展性强的Java项目,是按照模块化思维来进行开发的,所以不同的功能会交给不同的包来执行,Java提供了package
关键字来做到这点。正如上面的案例一样
为了模拟项目环境,我们需要修改目录结构以及.java
的内容
|
|
那我们稍微修改一下MainTest.java
,让他处于包环境内,变成MainTestClassPath.java
,只添加了package
关键字以及包路径
MainTestClassPath.java
内容如下
|
|
此时我们再执行javac
命令,将他编译为字节码文件,再使用java
命令去执行他
|
|
报错了,为什么?原因很清楚的告知了我们,没有找到或者无法加载主类,但是我们运行的类很简单,不应该出现类层面的问题,唯一出现的问题,就是添加了package
关键字。
没有找到类,是因为ClassLoader
查找失败了
这些问题是怎么形成的,暂时按下不表,至于如何修复,或者说如何正确调用呢?
解决
步骤应该如下
目录结构没有变化
|
|
MainTestClassPath.java
内容也不变
|
|
执行如下命令
|
|
成功执行了,为什么,不同的点在于使用了 -d
参数,-d
指定了生成目录,在bin
目录下生成。
这个时候javac
自动创建了多级目录,按照package
的.
号作为目录划分符,将创建好的MainTestClassPath.class
放在了目录最深处
然后使用java
命令,指定classpath
为bin
目录,执行com.study.java.MainTestClassPath
类时,ClassLoader
会在bin
目录下寻找com.study.java.MainTestClassPath
类,并且将.
作为目录分隔符,进入目录查找类,此时就找到了
如果运行java
命令时,不指定ClassPath
参数,需要先进入bin
目录,再执行java.exe com.study.java.MainTestClassPath
,这样java
除了默认查找路径外(这些默认路径和项目文件无关),也会查找当前目录下有没有com.study.java.MainTestClassPath
类,同样将.
作为目录分隔符,进入目录查找类,此时也能找到
可以尝试将MainTestClassPath.class
拿出目录时,不管怎么执行都同样会得到错误: 找不到或无法加载主类
的情况,所以默认的ClassLoader
的查找是和路径强相关的。
ClassPath
所以ClassPath是什么?
ClassPath是一个环境变量,表示JVM从哪里去寻找要运行的class文件,ClassPath会包含默认路径与执行命令的当前目录
根据javac
的生成可以得知,package
关键字会将包路径中的.
号作为目录分隔符。这样就解释了为什么IDEA中,源码路径也需要保持和package
声明保持一致的原因,为了尽量和生成路径一致
IDEA报错
IDEA正常
总结
在这篇文章中提到的类加载器的加载阶段,应用程序类加载器 - Application Class Loader
是会根据ClassPath
来加载类(Bootstrap Class Loader
和 Extension Class Loader
不会),所以做此补充,并且ClassPath可以做为参数传递给JVM,使其包含除默认目录外的其他目录
所以如果你到类找不到了,好好配置一下ClassPath吧
Tips
我们强烈不推荐在系统环境变量中设置
classpath
,那样会污染整个系统环境。在启动JVM时设置classpath
才是推荐的做法。实际上就是给java
命令传入-classpath
参数:
1
java -classpath .;C:\work\project1\bin;C:\shared abc.xyz.Hello
或者使用
-cp
的简写:
1
java -cp .;C:\work\project1\bin;C:\shared abc.xyz.Hello
参考
https://liaoxuefeng.com/books/java/oop/basic/package/
https://liaoxuefeng.com/books/java/oop/basic/classpath-jar/index.html