Java类加载器的底层原理
作者:龚生
出处:
类加载器的关系
文章插图
类加载器的分类
- JVM支持两种类加载器 , 一种为 引导类加载器 (Bootstrap ClassLoader),另外一种是 自定义类加载器 (User Defined ClassLoader)
- 引导类加载器是由C/C++编写的无法访问到
- Java虚拟机规定:所有派生于抽象类ClassLoader的类加载器都划分为自定义加载器
- 最常见的类加载器只有三个(如上图所示)
public class ClassLoaderTest {public static void main(String[] args) {//获取系统类加载器ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2//获取其上层:扩展类加载器ClassLoader extClassLoader = systemClassLoader.getParent();System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@1540e19d//获取其上层:获取不到引导类加载器ClassLoader bootstrapClassLoader = extClassLoader.getParent();System.out.println(bootstrapClassLoader);//null//对于用户自定义类来说:默认使用系统类加载器进行加载ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2//String类使用引导类加载器进行加载的 。 ---> Java的核心类库都是使用引导类加载器进行加载的 。ClassLoader classLoader1 = String.class.getClassLoader();System.out.println(classLoader1);//null}}
系统自带的类加载器介绍- 启动类加载器(引导类加载器、Bootstrap ClassLoader)由c/c++语言实现的 , 嵌套在jvm内部用来加载java核心库并不继承java.lang.ClassLoader , 没有父加载器为扩展类加载器和系统类加载器的父加载器只能加载java、javax、sun开头的类
- 扩展类加载器(Extension ClassLoader)java语言编写 , sun.misc.Launche包下 。 派生于ClassLoader类 , 父类加载器为Bootstrap ClassLoader从java.ext.dirs系统属性指定的目录中加载类库或者加载jre/lib/ext子目录下的类库(用户可以在该目录下编写JAR , 也会由此加载器所加载)
- 系统类加载器(System ClassLoaderAppClassLoader)派生于ClassLoader , 父类加载器为Extension ClassLoader负责加载classpath或者系统属性java.class.path指定路径下的类库java语言编写 , sun.misc.Launche包下 。 负责加载程序中默认的类 , 可以通过getSystemClassLoader()方法获取该类的加载器 。
- 用户自定义类加载器(后面详细介绍)隔离加载类修改类加载的方式扩展加载源防止源码泄漏(可以对字节码文件加密)继承ClassLoader类方式实现自定义类加载器
- ClassLoader是一个抽象类 , 其后的所有类加载器都继承此类
文章插图
注:这些方法都不是抽象方法 。 获取ClassLoader的路径
public class ClassLoaderTest2 {public static void main(String[] args) {try {//1.ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();System.out.println(classLoader);//2.ClassLoader classLoader1 = Thread.currentThread().getContextClassLoader();System.out.println(classLoader1);//3.ClassLoader classLoader2 = ClassLoader.getSystemClassLoader().getParent();System.out.println(classLoader2);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
双亲委派机制(面试)- Java虚拟机对class文件采用的是 按需加载 的方式 , 当需要使用到这个类的时候才会对它的class文件加载到内存生成class对象 , 加载的过程中使用的 双亲委派模式, 即把请求交给父类处理 。
- 如果一个类加载器收到了类加载的请求 , 它不会自己加载 , 而是先把这个请求给自己的父类加载器去执行
- 如果这个父类加载器还有父类加载器 , 则会再将请求给自己的父类加载器 , 依次递归到顶层的启动类加载器
- 依次进行判断是否能完成委派(加载此类) , 若能完成委派则该类就由此加载器加载 , 若无法完成委派 , 则将委托给子类加载器进行判断是否能完成委派 , 依次递归到底层加载器 , 若期间被加载则完成加载阶段不会再递归(注) 。
文章插图
注:类只能被一个加载器所加载 。
- 双亲委派的优势
- 避免类的重复加载
- 保护程序的安全 , 防止核心API被篡改
- 例如:创建一个java.lang.String类 , 因为有双亲委派的机制 , 所以会将String类交给引导类加载器来判断是否能被加载 。 引导加载器判断可以加载此类(是核心类中的String) , 完成加载 , 则"恶意"写的String类无法生效 , 防止String类被恶意篡改 。 这里也称沙箱安全机制(保护java核心源代码)
- 人民币|天猫国际新增“服务大类”,知舟集团提醒入驻这些类目的要注意
- 互联网|强制收集个人信息?国家网信办拟为38类App戴紧箍
- 现状|程序员现状揭秘:平均年薪20.36万,Java人才需求量最大
- 介绍|5分钟介绍各种类型的人工智能技术
- 实体店|这3类手机建议“网购”,实体店太坑了!网友:咋不早说?
- 人类|距离人类“玩坏”自己的电脑桌面,还需要多久?
- 同比|今年前10个月,上海商品类网络购物交易额5520.2亿元,同比增长12.9%!
- 产品|墨案Inkpad X超级阅读器:10英寸大屏,同品类号称无敌
- 发现|我们调研了数万个用户,发现最不可信的是人类
- 产品|秦朔谈物联网中央空调:并非是产品,而是新品类