小白学习JVM--类加载和双亲委派机制

Posted 肖帆咪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小白学习JVM--类加载和双亲委派机制相关的知识,希望对你有一定的参考价值。

JVM结构-类加载

1.类加载子系统的作用

在这里插入图片描述

类加载器子系统负责从文件系统加载.class文件,class文件有特定的文件标识(CA FE BA BE 开头)

ClassLoader负责class文件的加载,能否运行有执行引擎觉得.

加载的类信息放在方法区中,还可以存放运行时常量池信息,还可以包含字符串字面量和数字常量

2.类加载ClassLoader的角色

在这里插入图片描述

  1. class file存在硬盘上,是一个模板在执行时加载到JVM中,然后根据模板实例化一个实例
  2. class file加载到jvm中,称为DNA元数据模板,放在方法区中
  3. .class–>JVM–>元数据模板,类加载器充当运输工具

3.类加载过程

在这里插入图片描述

3.1加载

  1. 通过地址获取类的二进制字节流
  2. 将字节流代表的静态存储结构转换为方法区的运行时结构
  3. 内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据的访问入口

3.2链接

  1. 验证:检验被加载的类的内部结构是否正确,并调整和其他类协调一致
  2. 准备:准备阶段为类的静态属性分配内存,设置默认初始值;不包含用final修饰的static实例变量,在编译时进行初始化,不会为实例变量初始化
  3. 解析:将类的二进制数据中的符号引用替换成直接引用

3.3初始化

类什么时候初始化

  1. 创建实例对象时候
  2. 访问类或接口的静态变量或对静态变量赋值
  3. 调用类的静态方法
  4. 反射(Class.forName(""))
  5. 初始化一个类的子类(首先初始化子类的父类)

类的初始化顺序

父类 static –> 子类 static –> 父类构造方法- -> 子类构造方法
在这里插入图片描述

结论:

子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了;
静态变量、静态初始化块顺序取决于它们在类中出现的先后顺序
变量、初始化块初始化顺序取决于它们在类中出现的先后顺序

4.类加载器的分类

JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器

常见的类加载器有三个:

在这里插入图片描述

4.1引导类加载器(启动类加载器BootStrap ClassLoader)

  1. 使用C/C++语言实现,嵌套在JVM内部,加载java核心类库
  2. 不集成于java.lang.ClassLoader没有父加载器
  3. 负责加载扩展类加载器和应用类加载器,并为他们制定父类加载器
  4. 出于安全,只加载java,javax,sun等开头的类

4.2扩展类加载器(Extension ClassLoader)

  1. java语言编写,由sun.misc.Launcher$ExtClassLoader实现
  2. 派生于ClassLoader类
  3. 上层加载器为引用类加载器
  4. 从java.ext.dirs系统属性所指定 的目录中加载类库,或在JDK系统目录下的jre/lib/ext下加载类库,如果用户创建的jar放在此目录下.䧥自动由扩展类加载器加载

4.3应用程序类加载器(系统类加载器Application ClassLoader)

  1. java语言编写,由sun.misc.Launcher$AppClassLoader实现
  2. 派生于ClassLoader类
  3. 上层加载器为扩展加载器
  4. 加载用户定义的类
  5. 通过类名.classgetClassLoader(),ClassLoader.getSystemClassLoader()来获得
  6. ClassLoader类,是一个抽象类,其后所有的类加载器都继承自CLassLoader(不包括启动类加载器)

5.双亲委派机制

JVM对class文件采用的是按需加载的方式,即需要改类时才会将class文件加载到内存中生成class对象,加载某个类的class文件,采用双亲委派模式,将请求交给父类处理

在这里插入图片描述

工作原理:

收到类加载请求,不会先加载,会将委托一层一层向上委托,直到没有父类加载器,若父类加载器完成任务就成功返回,若父类没有完成,又会返回给子类,若全部加载失败,抛出ClassNotFoundException异常

双亲委派优点:

  1. 安全,避免用户编写的类替换java的核心类,如java.lang.String
  2. 避免权限定命名的类重复加载(通过findLoadClass()判断当前类是否已加载)

6.沙箱安全机制

作用:防止恶意代码污染java源代码

例如:我们定义类为String的包也命名为java.lang,因为这个类属于jdk,若没有沙箱安全机制,该类就会污染系统中的String.

因为沙箱安全机制,就委托顶层的类加载器查找这个类,没有就委托扩展类加载器,还没有就委托系统类加载器.由于STring就是jdk源代码,所以引导加载器就加载到了,找到后使用,后面的一概不使用,保证了恶意代码污染

面试题

在jvm中如何判断两个对象是属于同一个类
  1. 类的全类名完全一致
  2. 类的加载器相同

7.类的主动使用/被动使用

主动使用:

  1. 初始化类的new方式,导致类的加载并初始化
  2. 访问类的静态变量,包括读取和更新
  3. 访问类的静态方法
  4. 对类进行反射操作,导致类的初始化
  5. 初始化子类会导致父类的初始化

被动使用:

  1. 引用类的静态常量,不会导致初始化,常量指已经知道字面量的常亮,需要经过计算得到的常量还会导致初始化

  2. 构造某个类的数组时不会导致类的初始化

    Student[] student = new Student[10];

    主动使用和被动使用的区别在于类是否会被初始化

以上是关于小白学习JVM--类加载和双亲委派机制的主要内容,如果未能解决你的问题,请参考以下文章

打破双亲委派JVM:类加载机制深度剖析 - 第8篇

JVM笔记二双亲委派机制

jvm 双亲委派模式

Tomcat打破双亲委派机制执行顺序底层代码原理JVM04_Tomcat JDBC破坏双亲委派机制带来的面试

JVM17_Tomcat打破双亲委派机制执行顺序底层代码原理Tomcat|JDBC破坏双亲委派机制带来的面试题

JVM 专题四:类加载子系统双亲委派机制