当前位置:网站首页>JVM类加载子系统
JVM类加载子系统
2022-07-06 09:30:00 【机智的爆爆哥】
1. 类加载器与类加载的过程
我们先来看张图,字节码文件经过类加载系统的过程,首先我们要明确,类加载器的作用是什么?
主要是起了一个传输的作用,相当于快递员,后面的过程可以看成是流水线,会对相应的文件进行验证,判断是否合法。
类的加载过程
加载
这里的加载只是整个加载的一个最初流程,这点需要注意,加载主要分为三步。
1.通过类的全限定类名获取对应类的二进制字节流。
2.将字节流代表的静态结构转化为方法区的运行时结构。
3.在内存中生成对应的java.lang.Class对象。
链接
链接细分为三步,这三步都很重要。
验证
可能有人恶意更改class文件,实现某种攻击,所以要先做验证。
准备
- 为类变量赋值为零值
- 加final的变量在编译期就被定义了,所以不会赋值
- 这个时候还没有创建对象呢,所以实例变量也不会进行赋值
解析
将符号引用转化为直接引用,具体的细节字节码篇再讲。
初始化
首先要明白 clint方法和init方法,前者是由所有类变量的赋值,静态语句合并在一起的方法,后者是有几个构造器,就会有几个对应的init方法。
clint方法说白了就是用static修饰的语句,就会被加入到里面,如果一个类有父类,那么会先执行父类的clinit方法。
init方法里面包含了构造器,显式初始化,如直接赋值,代码块,实例化都算在里面。
而整个初始化阶段就是执行clinit方法的,并且在执行clinit方法会加锁,保证数据的安全性。
2. 类加载器分类
类加载器主要分为两类,一类是C语言编写的,被称为引导类加载器,其他都可算作自定义加载器,具体如下所示。
其中最上层是最特殊的,其他的都是由Java语言实现的。
可以运行如下代码,尝试获取下类加载器。
public class Test {
public static void main(String[] args) {
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);//sun.misc.Launcher$ [email protected]
//获取扩展类加载器
ClassLoader extClassLoafer = systemClassLoader.getParent();
System.out.println(extClassLoafer);//sun.misc.Launcher$ [email protected]
//用户自定义类加载器
ClassLoader classLoader = Test.class.getClassLoader();
System.out.println(classLoader);//sun.misc.Launcher$ [email protected]
//尝试获取引导类加载器
ClassLoader bootstrapClassloader = extClassLoafer.getParent();
System.out.println(bootstrapClassloader);//null
}
}
可以看到,我们发现,自定义类的加载器是系统类加载器,系统类加载器的上级是引导类加载器,引导类加载器的上级为null,因为是C语言写的,咱们获取不到。
3. ClassLoader的使用说明
Bootstrap classLoader
引导类加载器,也被称为启动类加载器,最上级的角色,用C语言编写,用来加载一些核心的类,如JAVA_HOME/jre/lib/rt.jar、resource.jar,提供JVM自身所需要的类。
Extension classLoader
扩展类加载器,派生于ClassLoader类,由Java语言编写,加载核心包以外的内容,如用户建的Jar包放在jre/lib/ext目录下,也会被扩展类加载器所加载。
AppClassLoader
系统类加载器,一般来讲我们定义的类都是由它来加载的,也是程序中的默认加载器。
在某些情况下,我们确实需要自定义加载器,如隔离加载类,修改鳄梨加载方式,防止源码泄漏等,详细内容将放在后面讲。
4. 谈谈双亲委派机制
这个我就被面试官问到过,其实我觉得这个翻译并不准确,应该叫父级代理,双亲指的并不是父母,而是指这个加载器的更高级。
流程图如下所示。
具体流程分为三步。
1.当一个类收到了加载请求,并不会直接去加载,而是由他的父类加载器去执行
2.父类加载器如果还有上级,就在向上委托,知道最上级为止
3.如果顶层的加载器能够完成加载当然最好,如果不能,再交由子类加载器去处理。
大家可以想象成上了一顿好吃的,小孩子虽然想吃,但是先推给爸爸吃,爸爸想,爷爷还没动筷呢,等爷爷吃了再吃,爷爷说,这东西太硌牙了,你们吃吧,爸爸就先吃了......
我们可以举个例子,定义一个java.lang包下的Hello类
但运行直接报错了,安全异常,被禁止的包名java.lang
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
因为这个包下的类都是由引导类加载器管的,如果可以这么定义,那么你如果写个死循环,或者延迟的程序,可能导致加载器运行异常,这也是一种保护的措施。
5. 其他
面试题:如果判断两个class对象是否为同一个类?
首先是两个类的完整包名要都一致,且他们的加载器也要一致,第二点才答出才能够区分出你与别人的水平。
类的主动使用与被动使用
主动引用会导致类的初始化,可以回忆下第一节讲的,也就是是否会执行clinit方法。
有以下七种
- 创建类的实例
- 访问某个类/接口的静态变量,或为该静态变量赋值
- 调用类的静态方法
- 反射获取类
- JVM启动时被表明启动的类(这个先记住吧 我也没碰到过)
- JDK 7 开始提供的动态语言支持:
java.lang.invoke.MethodHandle 实例的解析结果
REF_getStatic、REF_putStatic、REF_invokeStatic 句柄对应的类没有初始化则初始化 (了解即可)
最后两种碰到的很少,了解即可。
每日分享
有的人浅薄,有的人金玉其表败絮其中。有一天你会遇到一个彩虹般绚烂的人,当你遇到这个人后,会觉得其他人都只是浮云而已。
边栏推荐
- IDEA断点调试技巧,多张动图包教包会。
- ByteDance 2022 school recruitment R & D advance approval publicity meeting, students' top 10 issues
- 字节跳动海外技术团队再夺冠:高清视频编码已获17项第一
- Train 100 pictures for 1 hour, and the style of the photos changes at will. There is a demo at the end of the article | siggraph 2021
- Activit fragmented deadly pit
- Mongodb learning notes
- ~83 form introduction
- Full record of ByteDance technology newcomer training: a guide to the new growth of school recruitment
- QT system learning series: 1.2 style sheet sub control lookup
- 7-12 inventory code base
猜你喜欢
Log4j2 major vulnerabilities and Solutions
算数运算指令
我走過最迷的路,是字節跳動程序員的腦回路
Alibaba cloud server builds SVN version Library
High performance mysql (Third Edition) notes
The "advertising maniacs" in this group of programmers turned Tiktok advertisements into ar games
Shell_ 06_ Judgment and circulation
Mongodb learning notes
Activit零零碎碎要人命的坑
逻辑运算指令
随机推荐
Many papers on ByteDance have been selected into CVPR 2021, and the selected dry goods are here
Ce n'est qu'en apprenant que c est à la hauteur des attentes Top5 s1e8 | s1e9: caractères et chaînes & opérateurs arithmétiques
~77 linear gradient
yum install xxx报错
After idea installs the plug-in, restart the plug-in and disappear
7-7 ring the stupid bell
~76 sprite map
冯诺依曼体系结构
原型链继承
~81 long table
Activiti目录(五)驳回、重新发起、取消流程
J'ai traversé le chemin le plus fou, le circuit cérébral d'un programmeur de saut d'octets
Activiti目录(四)查询代办/已办、审核
Ruoyi-Cloud 踩坑的BUG
Record the error reason: terminate called after throwing an instance
Jedis
Eureka high availability
Solr standalone installation
Shell_ 01_ data processing
登陆验证koa-passport中间件的简单使用