机制背景:
Java虚拟机对Class文件采用的是按需加载的方式,只有在需要使用该类时,才会将它的class文件加载到内存中生成lcass对象。
描述:
加载某个类的class文件时,虚拟机采用的是双亲委派模式。即把请求交由父类处理,它是一种任务委派模式。
优势:
1、避免类的重复加载
2、保护程序的安全,放置核心API被随意篡改
工作原理:
1、如果一个类收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给其父类的加载器来执行
2、如果其父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器
3、如果父类加载器可以完成类的加载任务,就成功返回;如果无法完成类的加载任务,子加载器才回尝试自己去进行加载。
案例:
自定义一个java.lang文件包,并创建一个String类。
程序内使用String类时,类的加载任务会被委派到顶层的引导类加载器。则始终加载的是核心类库rt.jar中的String类。自定义的String类,永远不会被加载到。(也是基于系统类加载安全的考虑)
双亲委派的反向委托:
当父类加载器无法加载到需要的类库时,则会反向委托到其下一级的类加载器进行加载。
沙箱安全机制:
自定义重复的核心类库的时候,比如String类。引导类加载器在加载的时候,仍然会加载核心类库的String类。自定义的类并不会被加载到。
而且,在核心类包下,自定义非重复的类,引导类加载器在进行加载的时候,出于安全机制,会报安全错误。
其他
JVM必须知道一个类型是由启动加载器加载的,还是由用户类加载器加载的。如果一个类型是由用户类加载加载的,那么JVM会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中。当解析一个类型到另一个类型的引用的时候,JVM需要保证这两个类型的类加载器是相同的。
类的主动使用和被动使用
区别:类会不会被初始化。会初始化的时候是类的主动使用
主动使用分为七种情况:
创建类的实例
访问类或接口的静态方法,或则好对该静态变量赋值
调用类的静态方法
反射(比如:Class.forName(""))
初始化一个类的子类
Java虚拟机启动的时候别表明为启动类的类
JDK7开始提供的动态语言支持:
java.lang.invoke.MethodHandle示例的解析结果
REF_GetStatic、REF_putStatic、REF_invokeStatic句柄对应的类没有初始化,则初始化
其他使用Java类的方式都被看作是对类的被动使用,都不会导致类的初始化。