Class Loading作为java程序执行的第一步,虚拟机对这部分并没有严格的说明,因此这个阶段对于程序员而言就有着非常大的灵活性,这点对于java的技术的发展也有非常大的作用,比如说动态代理,OSGI,JSP等。
从JVM的角度出发类加载器主要分两类
一:启动类加载器
主要负责把<JAVA_HOME>/jre/lib目录下(或者是-Xbootclasspath指定的路径)的能被虚拟机识别的jar加载到虚拟机内存中。
不可扩展,不可以被程序员引用
二:除了第一种的所有加载器
这些加载器都继承自java.lang.ClassLoader类
从用户的角度看的话除了启动类加载器外还可以分为
一:扩展类加载器
这个加载器由sun.misc.Launcher$ExtClassLoader实现,主要负责加载<JAVA_HOME>/jre/lib/ext目录下的jar到内存中,还可以加载系统变量java.ext.dirs定义目录下的jar包
开发者可以直接使用这个加载器
二:应用程序加载器
这个加载器由sun.misc.Launcher$AppClassLoader来实现,主要负责加CLASSPATH定义的jar,开发者也可以直接使用这个加载器,如果没有定义自己的类加载器,那么它将是系统的默认加载器
前面描述了类加载器的大致分类以及特点,接下来说明一下什么叫Parents Delegation Model,以及这种模型有什么优点以及为什么要弄这个模型?
(1)什么叫Parents Delegation Model?
所谓的Parents Delegation Model其实就是一种类加载器之间的层次关系,具体的说就是它规定最顶层的类加载器必须为启动类加载器,其余的类加载器必须有自己的父类加载器,且上下层关系的加载器一般是用组合而不是继承来实现的,下图为大概的层次机构关系
(2)这种模型的作用何在?
在说作用之前首先讲一下这种模型的工作原理,其原理可以用一句话概括:尽量让父类加载器去加载请求加载的类.只有当父类加载器加载不到对应的类时,才会用子类加载器去加载
例如当要加载java.lang.Object的时候,由于这种模型会尽量让父类加载器去加载,由于java.lang.Object 属于<JAVA_HOME>/jre/lib/rt.jar,所以当用启动类加载器去加载的时候,可以加载到需要的类,又由于类的唯一性是由加载器+类本生 来确定的,所以双亲委派模型保证了java程序的稳定运行.
要注意的是虽然这种模型对于java程序的稳定运行起到了很重要的作用,但是它并不是虚拟机规范强制要求的