JVM类加载器初探

JVM类加载器初探

1、klass模型类的继承结构

你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

2、类加载的过程

2.1、加载

通过类的全限定名获取存储该类的class文件(没有指明必须从哪获取),解析成运行时数据,即instanceKlass实例,存放在方法区,在堆区生成该类的Class对象,即instanceMirrorKlass实例。

2.1.1、何时加载?主动使用时

1、new、getstatic、putstatic、invokestatic
2、反射
3、初始化一个类的子类会去加载其父类
4、启动类(main函数所在类)
5、当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化

2.1.2、预加载:包装类、String、Thread

因为没有指明必须从哪获取class文件,脑洞大开的工程师们开发了以下功能:
1、从压缩包中读取,如jar、war
2、从网络中获取,如Web Applet
3、动态生成,如动态代理、CGLIB
4、由其他文件生成,如JSP
5、从数据库读取
6、从加密文件中读取

2.2、验证

1、文件格式验证
2、元数据验证
3、字节码验证
4、符号引用验证

2.3、准备

为静态变量分配内存、赋初值,实例变量是在创建对象的时候完成赋值的,没有赋初值一说
注意:
如果被final修饰,在编译的时候会给属性添加ConstantValue属性,准备阶段直接完成赋值,即没有赋初值这一步

2.4、解析

思路:
1、加载阶段解析常量池时
2、用的时候
openjdk是第二种思路,在执行特定的字节码指令之前进行解析:
anewarray、checkcast、getfield、getstatic、instanceof、invokedynamic、invokeinterface、invokespecial、invokestatic、invokevirtual、ldc、ldc_w、ldc2_w、multianewarray、new、putfield。

2.5、初始化

1、执行静态代码块,完成静态变量的赋值
2、静态字段、静态代码段,字节码层面会生成clinit方法
3、方法中语句的先后顺序与代码的编写顺序相关

3、类加载器子系统与SPI

3.1、类加载器

JVM中有两种类型的类加载器,由C++编写的及由Java编写的。除了启动类加载器(Bootstrap Class Loader)是由C++编写的,其他都是由Java编写的。由Java编写的类加载器都继承自类java.lang.ClassLoader。JVM还支持自定义类加载器。后面会将。各种类加载器之间存在着逻辑上的父子关系,但不是真正意义上的父子关系,因为它们直接没有从属关系。

1.启动类加载器:bootstrapClassLoader
2.扩展类加载器:extensionClassLoader 可以通过java.ext.dirs指定
3.应用类加载器:applicationClassLoader默认加载用户程序的类加载器
4.自定义类加载器:UserClassLoader继承类java.lang.ClassLoade

4、双亲委派

什么是双亲委派机制. 当某个类加载器需要加载某个 .class 文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
优势:效率、安全、提供了扩展性
劣势:无法做到不委派、无法做到向下委派

4.1、打破双亲委派

因为在某些情况下父类加载器需要委托子类加载器去加载class文件。受到加载范围的限制,父类加载器无法加载到需要的文件,以Driver接口为例,由于Driver接口定义在jdk当中的,而其实现由各个数据库的服务商来提供,比如mysql的就写了MySQL Connector,那么问题就来了,DriverManager(也由jdk提供)要加载各个实现了Driver接口的实现类,然后进行管理,但是DriverManager由启动类加载器加载,只能记载JAVA_HOME的lib下文件,而其实现是由服务商提供的,由系统类加载器加载,这个时候就需要启动类加载器来委托子类来加载Driver实现,从而破坏了双亲委派。类似这样的情况就需要打破双亲委派。打破双亲委派的意思其实就是不委派、向下委派

4.2、SPI机制

是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。

4.3、沙箱安全(防止双亲委派被破坏)

比如定义了一个类名为String所在包为java.lang,因为这个类本来是属于jdk的,如果没有沙箱安全机制的话,这个类将会污染到我所有的String,但是由于沙箱安全机制,所以就委托顶层的bootstrap加载器查找这个类,如果没有的话就委托extsion,extsion没有就到aapclassloader,但是由于String就是jdk的源代码,所以在bootstrap那里就加载到了,先找到先使用,所以就使用bootstrap里面的String,后面的一概不能使用,这就保证了不被恶意代码污染。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值