jvm类加载器模块图解
类加载器类型一共两种,引导类加载器bootstarpClassLoader和自定义加载器
userDefinedClassLoader(系统加载器和appSource加载器也归于自定义加载器)
1.启动类加载器 (引导类加载器Bootstrap ClassLoader)
- 使用C/C++编写,嵌套在jvm内部
- 加载核心类库(rt.jar、resources.jar),提供JVM自身需要的类
- 不继承ClassLoader,没有父记载器
- 加载扩展类和应用程序类加载器,并作为他们的父类
- 出于安全考虑,只加载包为java、javax、sun等开头的包
2.扩展类加载器(Extension ClassLoader)
- java语言编写
- 派生于ClassLoader
- 父类记载器为启动类加载器、
- 从java.ext.dirs指定目录类库或者Jdk的lib/ext目录下类库,如果用户创建的Jar包放此目录下,也会用扩展类加载器加载
3.应用程序加载器(AppClassLoader)
- java语言编写
- 派生于ClassLoader
- 父类记载器为启动类加载器
- 加载环境变量classpath指定的类库
- 程序默认的加载器,java应用的类都是由它来完成
4.自定义加载器
- 隔离加载类
- 修改加载类方式
- 扩展加载源
- 防止源码泄露
双亲委派机制
- 加载器收到类加载请求时,不会自己去加载,而是把请求委托给父类加载器加载,如果父类还存在父类,在继续委托,知道达到顶层的启动类加载器(BootStrap ClassLoader)
- 如果父类加载器完成类加载任务,则返回,如果父类加载器无法完成加载,则由子加载器自己尝试加载。
package com.pingan.com;
public class ClassLoaderTest {
public static void main(String[] args) {
//类加载请求过来,
//1.先找到AppClassLoader的父类加载器Extension ClassLoader,
//2.Extension ClassLoader父类Bootstrap ClassLoader加载 因为Bootstrap ClassLoader只加载java、javax、sun等开头的包所以加载不成功
//3.往下找Extension ClassLoader 此时 从java.ext.dirs指定目录类库或者Jdk的lib/ext目录下类库所以也不加载
//4.AppClassLoader 就自己加载了
ClassLoaderTest classLoaderTest = new ClassLoaderTest();
System.out.println(classLoaderTest.getClass().getClassLoader());
}
}
sun.misc.Launcher$AppClassLoader@73d16e93
此时打印的就是AppClassLoader加载器去加载
案列:如果你自己定义个和java的String一样的方法,它会被BootStrap ClassLoader加载,此时就是加载java自带的String,而不是加载你自定义的String,因为Java自带的String没有Main方法,所以报错
机制叫沙箱安全机制
package java.lang;
public class String {
// 在类 java.lang.String 中找不到 main 方法
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("双亲委派机制");
}
}
当你创建一个Java.lang自定义的类时,BootStrap ClassLoader会阻止你创建
package java.lang;
public class TestA {
//Exception in thread “main” java.lang.SecurityException: Prohibited package name: java.lang
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(“aa”);
}
}
双亲委派机制优势
- 避免重复加载
- 防止核心API被串改,保护程序