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

JVM结构-类加载

文章目录

  • JVM结构-类加载
    • 1.类加载子系统的作用
    • 2.类加载ClassLoader的角色
    • 3.类加载过程
      • 3.1加载
      • 3.2链接
      • 3.3初始化
        • 类什么时候初始化
        • 类的初始化顺序
    • 4.类加载器的分类
      • 4.1引导类加载器(启动类加载器BootStrap ClassLoader)
      • 4.2扩展类加载器(Extension ClassLoader)
      • 4.3应用程序类加载器(系统类加载器Application ClassLoader)
    • 5.双亲委派机制
        • 工作原理:
        • 双亲委派优点:
    • 6.沙箱安全机制
        • 作用:防止恶意代码污染java源代码
        • 面试题
          • 在jvm中如何判断两个对象是属于同一个类
    • 7.类的主动使用/被动使用
      • 主动使用:
      • 被动使用:

1.类加载子系统的作用

小白学习JVM(二)--类加载和双亲委派机制_第1张图片

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

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

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

2.类加载ClassLoader的角色

小白学习JVM(二)--类加载和双亲委派机制_第2张图片

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

3.类加载过程

小白学习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 –> 父类构造方法- -> 子类构造方法
小白学习JVM(二)--类加载和双亲委派机制_第4张图片

结论:

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

4.类加载器的分类

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

常见的类加载器有三个:

小白学习JVM(二)--类加载和双亲委派机制_第5张图片

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文件,采用双亲委派模式,将请求交给父类处理

小白学习JVM(二)--类加载和双亲委派机制_第6张图片

工作原理:

收到类加载请求,不会先加载,会将委托一层一层向上委托,直到没有父类加载器,若父类加载器完成任务就成功返回,若父类没有完成,又会返回给子类,若全部加载失败,抛出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(一)–概述和模型
  • 小白学习JVM(二)–类加载和双亲委派机制

你可能感兴趣的:(JVM,JAVA,jvm,java,新星计划)