备注:本文篇幅比较长,但内容简单,大家不要恐慌,安静地耐心翻阅就是
Class文件的认识
我们都知道在Java中程序是运行在虚拟机中,我们平常用文本编辑器或者是IDE编写的程序都是.java格式的文件,这是最基础的源码,但这类文件是不能直接运行的。如我们编写一个简单的程序HelloWorld.java
public class HelloWorld{ public static void main(String[] args){ System.out.println("Hello world!"); }}
如图:
然后,我们需要在命令行中进行java文件的编译
javac HelloWorld.java
可以看到目录下生成了.class文件
我们再从命令行中执行命令:
java HelloWorld
上面是基本代码示例,是所有入门JAVA语言时都学过的东西,这里重新拿出来是想让大家将焦点回到class文件上,class文件是字节码格式文件,java虚拟机并不能直接识别我们平常编写的.java源文件,所以需要javac这个命令转换成.class文件。另外,如果用C或者Python编写的程序正确转换成.class文件后,java虚拟机也是可以识别运行的。更多信息大家可以参考这篇。
了解了.class文件后,我们再来思考下,我们平常在Eclipse中编写的java程序是如何运行的,也就是我们自己编写的各种类是如何被加载到jvm(java虚拟机)中去的。
你还记得java环境变量吗?
初学java的时候,最害怕的就是下载JDK后要配置环境变量了,关键是当时不理解,所以战战兢兢地照着书籍上或者是网络上的介绍进行操作。然后下次再弄的时候,又忘记了而且是必忘。当时,心里的想法很气愤的,想着是–这东西一点也不人性化,为什么非要自己配置环境变量呢?太不照顾菜鸟和新手了,很多菜鸟就是因为卡在环境变量的配置上,遭受了太多的挫败感。
因为我是在Windows下编程的,所以只讲Window平台上的环境变量,主要有3个:JAVA_HOME、PATH、CLASSPATH。
JAVA_HOME
指的是你JDK安装的位置,一般默认安装在C盘,如
C:Program FilesJavajdk1.8.0_91
PATH
将程序路径包含在PATH当中后,在命令行窗口就可以直接键入它的名字了,而不再需要键入它的全路径,比如上面代码中我用的到javac和java两个命令。
一般的
PATH=%JAVA_HOME%bin;%JAVA_HOME%jrebin;%PATH%;
也就是在原来的PATH路径上添加JDK目录下的bin目录和jre目录的bin.
CLASSPATH
CLASSPATH=.;%JAVA_HOME%lib;%JAVA_HOME%libools.jar
一看就是指向jar包路径。
需要注意的是前面的.;,.代表当前目录。
环境变量的设置与查看
设置可以右击我的电脑,然后点击属性,再点击高级,然后点击环境变量,具体不明白的自行查阅文档。
查看的话可以打开命令行窗口
echo %JAVA_HOME%echo %PATH%echo %CLASSPATH%
好了,扯远了,知道了环境变量,特别是CLASSPATH时,我们进入今天的主题Classloader.
JAVA类加载流程
Java语言系统自带有三个类加载器:
- Bootstrap ClassLoader 最顶层的加载类,主要加载核心类库,%JRE_HOME%lib下的rt.jar、resources.jar、charsets.jar和class等。另外需要注意的是可以通过启动jvm时指定-Xbootclasspath和路径来改变Bootstrap ClassLoader的加载目录。比如java -Xbootclasspath/a:path被指定的文件追加到默认的bootstrap路径中。我们可以打开我的电脑,在上面的目录下查看,看看这些jar包是不是存在于这个目录。
- Extention ClassLoader 扩展的类加载器,加载目录%JRE_HOME%libext目录下的jar包和class文件。还可以加载-D java.ext.dirs选项指定的目录。
- Appclass Loader也称为SystemAppClass 加载当前应用的classpath的所有类。
我们上面简单介绍了3个ClassLoader。说明了它们加载的路径。并且还提到了-Xbootclasspath和-D java.ext.dirs这两个虚拟机参数选项。
加载顺序?
我们看到了系统的3个类加载器,但我们可能不知道具体哪个先行呢?
我可以先告诉你答案
1. Bootstrap CLassloder
2. Extention ClassLoader
3. AppClassLoader
为了更好的理解,我们可以查看源码。
看sun.misc.Launcher,它是一个java虚拟机的入口应用。
public class Launcher { private static Launcher launcher = new Launcher(); private static String bootClassPath = System.getProperty("sun.boot.class.path"); public static Launcher getLauncher() { return launcher; } private ClassLoader loader; public Launcher() { // Create the extension class loader ClassLoader extcl; try { extcl = ExtClassLoader.getExtClassLoader(); } catch (IOException e) { throw new InternalError( "Could not create extension class loader