第一部分:Java虚拟机启动时,关于类加载方面的一些动作
当使用java ProgramName.class运行程序时,Java找到JRE,接着找到jvm.dll,把该动态库载入内存,这就是JVM。然后加载其它动态库, 并激活JVM。JVM激活之后会进行一些初始化工作,之后生成BootstrapLoader,该Class Loader是由C++写的。BootstrapLoader加载Launcher.java中的ExtClassLoader,并设定其Parent为 null,意思是ExtClassLoader的Parent Class Loader就是BootstrapLoader。然后BootstrapLoader又加载Launcher.java中的 AppClassLoade,并设定其Parent Class Loader是ExtClassLoader。不过如果调用ExtClassLoader的getParent( )方法,则返回的是null。这两个Class Loader都是以静态类的形式存在,并且都是用Java编写的。
这三个Class Loader它们都有自己的类查找路径:
BootstrapLoader: sun.boot.class.path
ExtClassLoader: java.ext.dirs
AppClassLoader: java.class.path
以上三个路径都是Java的系统属性,可以通过System.getProperty(String key)方法来查看其设置:
System.out.println(System.getProperty("java.class.path"));
现在看看每一种属性输出后的值,从而可以发现每种Class Loader分别负责哪些类的装载:
key: sun.boot.class.path
String: %JAVA_HOME%/lib/resources.jar, rt.jar, sunrsasign.jar, jsse.jar, jce.jar, charsets.jar,
%JAVA_HOME%/classes
key: java.ext.dirs
String: %JAVA_HOME%/lib/ext, %Windows%/sun/java/lib/ext
key: java.class.path
String: 程序的入口文件类所在的目录
由此可见,BootstrapLoader负责Java核心类(所有以java.*开头的类)。ExtClassLoader负责加载扩展类(所以以javax.*开头的类以及存在ext目录下的类)。AppClassLoader负责加载应用程序自身的类。
第二部分:Java的类加载机制。Java是如何加载类的,其流程。
类加载按照加载时机,是否自动加载分为两种:预先加载和按需加载。
预先加载的类是在JVM启动之后,应用程序运行之前。至少包含rt.jar中的所有类。
按需加载则是在应用程序运行之后,在程序运行过程中,JVM遇到一个还未被装载的类,这时由Class Loader把该类载入内存。
类加载按照方式来分,也是两种:隐式加载和显式加载。
隐式加载是通过new的方式,在类初始化时由JVM根据相应的Class Loader将类载入。
显式加载则是程序员在代码中显式利用某个Class Loader将类载入。
JVM自动装载类的算法是这样的:如果Class A的实例引用了Class B的实例,则在默认情况下,JVM会先找到Class A的Class Loader,然后用该Class Loader来装载Class B。
Class Loader装载类的一般算法如下:
Background: Class Loader是按照层次关系组织起来的,每一个Class Loader都有一个Parent。如果在创建Class Loader时不显式指定其父Class Loader,JVM会把系统Class Loader指定为该Class Loader的Parent。每一个Class Loader都有自己对应的Loaded Class Cache,换句话说,Loaded Class Cache由两部分组成:ClassLoader,以及由它加载的Class类名。 |
|