小白学习JVM--类加载和双亲委派机制
Posted 肖帆咪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小白学习JVM--类加载和双亲委派机制相关的知识,希望对你有一定的参考价值。
JVM结构-类加载
文章目录
1.类加载子系统的作用
类加载器子系统负责从文件系统加载.class文件,class文件有特定的文件标识(CA FE BA BE 开头)
ClassLoader负责class文件的加载,能否运行有执行引擎觉得.
加载的类信息放在方法区中,还可以存放运行时常量池信息,还可以包含字符串字面量和数字常量
2.类加载ClassLoader的角色
- class file存在硬盘上,是一个模板在执行时加载到JVM中,然后根据模板实例化一个实例
- class file加载到jvm中,称为DNA元数据模板,放在方法区中
- .class–>JVM–>元数据模板,类加载器充当运输工具
3.类加载过程
3.1加载
- 通过地址获取类的二进制字节流
- 将字节流代表的静态存储结构转换为方法区的运行时结构
- 内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据的访问入口
3.2链接
- 验证:检验被加载的类的内部结构是否正确,并调整和其他类协调一致
- 准备:准备阶段为类的静态属性分配内存,设置默认初始值;不包含用final修饰的static实例变量,在编译时进行初始化,不会为实例变量初始化
- 解析:将类的二进制数据中的符号引用替换成直接引用
3.3初始化
类什么时候初始化
- 创建实例对象时候
- 访问类或接口的静态变量或对静态变量赋值
- 调用类的静态方法
- 反射(Class.forName(""))
- 初始化一个类的子类(首先初始化子类的父类)
类的初始化顺序
父类 static –> 子类 static –> 父类构造方法- -> 子类构造方法
结论:
子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了;
静态变量、静态初始化块顺序取决于它们在类中出现的先后顺序
变量、初始化块初始化顺序取决于它们在类中出现的先后顺序
4.类加载器的分类
JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器
常见的类加载器有三个:
4.1引导类加载器(启动类加载器BootStrap ClassLoader)
- 使用C/C++语言实现,嵌套在JVM内部,加载java核心类库
- 不集成于java.lang.ClassLoader没有父加载器
- 负责加载扩展类加载器和应用类加载器,并为他们制定父类加载器
- 出于安全,只加载java,javax,sun等开头的类
4.2扩展类加载器(Extension ClassLoader)
- java语言编写,由sun.misc.Launcher$ExtClassLoader实现
- 派生于ClassLoader类
- 上层加载器为引用类加载器
- 从java.ext.dirs系统属性所指定 的目录中加载类库,或在JDK系统目录下的jre/lib/ext下加载类库,如果用户创建的jar放在此目录下.䧥自动由扩展类加载器加载
4.3应用程序类加载器(系统类加载器Application ClassLoader)
- java语言编写,由sun.misc.Launcher$AppClassLoader实现
- 派生于ClassLoader类
- 上层加载器为扩展加载器
- 加载用户定义的类
- 通过类名.classgetClassLoader(),ClassLoader.getSystemClassLoader()来获得
- ClassLoader类,是一个抽象类,其后所有的类加载器都继承自CLassLoader(不包括启动类加载器)
5.双亲委派机制
JVM对class文件采用的是按需加载的方式,即需要改类时才会将class文件加载到内存中生成class对象,加载某个类的class文件,采用双亲委派模式,将请求交给父类处理
工作原理:
收到类加载请求,不会先加载,会将委托一层一层向上委托,直到没有父类加载器,若父类加载器完成任务就成功返回,若父类没有完成,又会返回给子类,若全部加载失败,抛出ClassNotFoundException异常
双亲委派优点:
- 安全,避免用户编写的类替换java的核心类,如java.lang.String
- 避免权限定命名的类重复加载(通过findLoadClass()判断当前类是否已加载)
6.沙箱安全机制
作用:防止恶意代码污染java源代码
例如:我们定义类为String的包也命名为java.lang,因为这个类属于jdk,若没有沙箱安全机制,该类就会污染系统中的String.
因为沙箱安全机制,就委托顶层的类加载器查找这个类,没有就委托扩展类加载器,还没有就委托系统类加载器.由于STring就是jdk源代码,所以引导加载器就加载到了,找到后使用,后面的一概不使用,保证了恶意代码污染
面试题
在jvm中如何判断两个对象是属于同一个类
- 类的全类名完全一致
- 类的加载器相同
7.类的主动使用/被动使用
主动使用:
- 初始化类的new方式,导致类的加载并初始化
- 访问类的静态变量,包括读取和更新
- 访问类的静态方法
- 对类进行反射操作,导致类的初始化
- 初始化子类会导致父类的初始化
被动使用:
-
引用类的静态常量,不会导致初始化,常量指已经知道字面量的常亮,需要经过计算得到的常量还会导致初始化
-
构造某个类的数组时不会导致类的初始化
Student[] student = new Student[10];
主动使用和被动使用的区别在于类是否会被初始化
以上是关于小白学习JVM--类加载和双亲委派机制的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat打破双亲委派机制执行顺序底层代码原理JVM04_Tomcat JDBC破坏双亲委派机制带来的面试