专栏首页琦小虾的BinaryJVM技术总结之三——类加载机制

JVM技术总结之三——类加载机制

接上篇《JVM技术总结之二——GC机制》

三. 类加载机制

参考地址: 《类加载机制-深入理解jvm》 《Java Class文件格式、常量池项目的类型、表的结构》

3.1 类的加载过程

Java 类的加载过程主要分为五步:加载验证准备解析初始化。其中验证、准备、解析可以合称为连接。此外,这五步的顺序并不是完全固定的,比如为了支持动态绑定,解析的过程可以放在初始化之后。类的加载过程如下图所示:

3.1.1 加载

加载过程主要做三件事情:

  1. 根据全类名获取 *.class 文件的路径,通过二进制流读入 JVM 的方法区;
  2. 在方法区中将该字节流转为方法区的运行时数据结构;
  3. 在堆中生成代表该类的 java.lang.Class 对象,Class 对象的实例作为访问方法区中运行时数据结构的访问入口

3.1.2 校验

校验阶段主要确保 Class 文件字节流中的内容不会违反当前 JVM 的规范,不会危害到 JVM 运行时的安全。主要验证的有文件格式、元数据、字节码、符号引用

3.1.3 准备

准备阶段主要是将为类变量分配内存,并初始化为默认值。以下面的片段为例:

public static int value = 111;

需要注意的是,在准备阶段对于 int 类型,初始默认值为 0 而不是 111。同样的,其他基本类型的初始默认值都是该基本类型的默认值(如 double 的 0.0)。将 value 赋值为 111 的操作在初始化的步骤(即 clinit 方法)中进行。

3.1.4 解析

解析是将符号引用转换为直接引用的过程。

  • 符号引用:一组用于标识类型的符号,符合 Java 虚拟机规范的常量表,例如其中一项常量池项目类型如下图所示;
  • 直接引用:在内存中能够唯一标识对象的引用。可以是内存指针、偏移量、或者是能间接定位到目标的句柄等。

3.1.5 初始化

执行类构建方法 clinit 的过程。clinit 方法由所有类变量的赋值动作静态语句块 static{} 合并而来,这其中也包含了父类的 clinit 方法(类变量赋值动作与父类的静态语句块),同时在执行一个类的 clinit 方法时,也会通过递归方式保证其父类的 clinit 方法先被调用

此外对于初始化阶段,只有几种情况才会要求类立刻执行 clinit 方法:

  1. new:new 关键字某个未被初始化的类;
  2. 父类:初始化某子类时,父类未被初始化,则先初始化父类;
  3. 反射:通过反射调用某个未初始化的类;
  4. main 方法所在类

3.2 类加载器

ClassLoader 中有一个 ClassLoader parent,记录其父类加载器。根类加载器 bootstrap ClassLoader 是最顶层的 ClassLoader,没有父类加载器。类加载器的加载范围不同,如果子类加载器想要加载父类加载器已经加载的类,可以通过双亲委派机制,直接访问父类加载器已经加载的类。 但是有的时候父类加载器也需要加载子类加载器的 Class,这时候就需要打破双亲委派机制,主要方式是使用 Thread 类里的线程上下文类加载器的方法 setContextClassLoader。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaSE 基础学习之一 —— Java 的简介

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/...

    剑影啸清寒
  • Kafka技术知识总结之五——Kafka的高可用性

    Kafka 实现高可用性的方式是进行 replication。对于 kafka,如果没有提供高可用性机制,一旦一个或多个 Broker 宕机,则宕机期间其上所有...

    剑影啸清寒
  • 设计模式总结之一——代理模式

    代理模式广泛的用于多种框架,如 Mybatis, Spring 等。有静态代理、动态代理两种。

    剑影啸清寒
  • 深度分析:Java类加载机制和类加载器

    所谓类加载机制就是JVM虚拟机把Class文件加载到内存,并对数据进行校验,转换解析和初始化,形成虚拟机可以直接使用的Jav类型,即Java.lang.Clas...

    会呼吸的Coder
  • java.lang.NoClassDefFoundError原因

    java开发中经常遇到java.lang.ClassNotfoundException异常,ClassNotfoundException异常一般就是编译时找不到...

    SmileNicky
  • 实现一个分布式调用链路追踪Java探针你可能会遇到的问题

    Java探针可以在Java应用运行时毫无感知的切入应用代码,是一种用于监听代码行为或改变代码行为的工具。

    wujiuye
  • 深入探究JVM之类加载与双亲委派机制

    前面学习了虚拟机的内存结构、对象的分配和创建,但对象所对应的类是怎么加载到虚拟机中来的呢?加载过程中需要做些什么?什么是双亲委派机制以及为什么要打破双亲委派机制...

    夜勿语
  • 性能优化总结(四):预加载的设计

        本节说一下数据的预加载。这节的内容与SQL没什么关系。主要说的是在 GIX4项目 中,我们是如何设计符合需求的预加载类库的。内容如下: 什么是预加载,为...

    用户1172223
  • Java类加载机制详解

    Java类加载器负责加载所有的类,系统会为所有被载入内存的类生成一个java.lang.Class实例。对于同一个类,一旦被加载如内存中,就不会被再次加载。JV...

    张申傲
  • 深入理解类加载机制:拨开迷雾见真章

    我们平常写的Java代码是存储在.java文件中,这是一个文本文件,是不能直接执行的,但是这个文本文件可以被编译成为一个字节码文件(后缀为.class),这个字...

    itlemon

扫码关注云+社区

领取腾讯云代金券