Classloader机制

1.概述?缓存

类加载器:负责.class文件加载到内存中,并为之生成对应的Class对象,也就是字节码对象。这样就可使用这个类中的成员变量和方法了。而被加载到内存中的class文件就会变成class对象。spa

常见的类加载器有三种,每一个加载器负责加载不一样的位置的类:code

  (1)Bootstrap:根类加载器对象

  (2)ExtClassLoader:扩展类加载器blog

  (3)AppClassLoader:系统、应用类加载器内存

关于上述加载器的区别:get

说明:一、Bootstrap是最顶级的加载器。加载类文件不是咱们本身书写的,是JRE/lib/rt.jar包下的。只有将这个包下面的全部类加载到内存中,才可使用这个包下的全部类。class

            2.ExtClassLoader扩展类加载器,是用来加载JRE/lib/ext/*.jar这个包下的全部类,在这个jar包中,都是jdk内部本身使用的。变量

    3.AppClassLoader系统/应用类加载器。是用来加载ClassPath指定全部的jar或目录,classPath表示存放类路径。扩展

2.委托机制

全盘负责委托机制:

ClassLoader(类加载器)加载类用的是全盘负责委托机制。

1)全盘负责:当一个ClassLoader(类加载器)加载一个类的时候,那么在这个类中所引用的全部其它的类一般也都由这个类加载器来加载。

举例:好比上述代码中咱们在 ClassLoaderDemo1 类中书写以下代码:

public class ClassLoaderDemo1 {

public static void main(String[] args) {

// 获取当前类的加载器

ClassLoader loader = ClassLoaderDemo1.class.getClassLoader();

//输出当前类的类加载器

System.out.println(loader);//sun.misc.Launcher$AppClassLoader@b0014f0

//获取AppClassLoader类加载器的父类

ClassLoader parent = loader.getParent();

//输出AppClassLoader类加载器的父类加载器

System.out.println(parent);//sun.misc.Launcher$ExtClassLoader@325e9e34

}

} 

说明:因为咱们在ClassLoaderDemo1 类中使用了System类,那么System类也应该由ClassLoaderDemo1的类加载器加载到内存中。

换句话说,若是在A类中使用了B类,那么A类的加载器就会将B类也会加载到内存中,就是一个类的加载器同时把多个类都加载了。

2)委托机制:先让Parent(父)类加载器寻找,只有在Parent找不到的时候,才从本身的范围中寻找。

可是呢,全盘负责要和委托机制一块儿使用,一个类加载器在加载一个类的时候不是上来就先加载类,而是先咨询这个类加载器的父亲,先看他的父类加载器有没有要加载的类,若是已经存在要加载的类了,那么子类加载器就不会加载,由于在加载就会重复,产生冲突了,只有在父类加载器中找不到的时候,才从本身的范围中寻找。

举例:仍是上述的代码,因为ClassLoaderDemo1 类是被 AppClassLoader 类加载器加载内存中的,那么根据全盘负责机制,AppClassLoader 类加载器也会将System类加载到内存中,可是在加载的时候,根据委托机制AppClassLoader 类加载器会先去咨询他的父亲ExtClassLoader 类加载器,而这个类加载器中也没有System类,那么又会去咨询ExtClassLoader 类加载器的父类Bootstrap类加载器,而在这个类加载器中是能够加载System类的,因此做为子类加载器AppClassLoader 就不会加载了,这样才能保证一个类只会被加载一次,任何一个类同时只会被加载一次。

若是一个类在父类加载器中找到了,那么就会把这个类加载以后保存到cache(缓存)中。

3)类加载器的cache(缓存)机制:若是cache中保存了这个类就直接返回它,若是没有才加载这个类,而后存入cache中,下一次若是有其余类在使用的时候就不会在加载了,直接去cache缓存拿便可。这就是为何每一个类只加载一次,内存只有一份的缘由。

举例:仍是上述代码中,当第一次使用System类的时候,那么System类就会被加载了,那么System类就会存储到内存中了,当下面代码中咱们再一次使用System类的时候,因为内存中已经有了,那么就不会在去加载了,这时会直接拿过来用便可。

所以方法区中每个类的字节码文件只有一份的缘由由全盘负责、委托机制和类加载器的cache(缓存)机制共同决定。

相关文章
相关标签/搜索