Java 通过引入字节码和 JVM 机制,提供了强大的跨平台能力,理解 Java 的类加载机制是深入 Java 开发的必要条件。

一、Java代码执行流程

Java程序运行时,必须经过编译运行两个步骤。首先将后缀名为.java的源文件进行编译,最终生成后缀名为.class的字节码文件。然后JVM虚拟机启动时,会初始化好类加载器(ClassLoader)。通过ClassLoader,JVM将编译好的字节码文件加载到内存(类加载)。最后由JVM对加载到内存的java类进行解释执行,显示结果。

以我们常见的Test.java为例,具体流程如下图所示:

二、类加载过程

类加载过程主要分为三个步骤:加载链接初始化,而其中链接过程又分为三个步骤:验证准备解析,加上卸载使用两个步骤统称为为类的生命周期

加载

简单来说,加载指的是把class字节码文件从各个来源通过类加载器装载入内存中。

1、字节码来源

由于没有具体指明需要在哪里获取class文件,导致字节码来源途径非常丰富:

  • 从压缩包中读取,如jar、war

  • 从网络中获取,如Web Applet

  • 动态生成,如动态代理、CGLIB

  • 由其他文件生成,如JSP

  • 从数据库读取

  • 从加密文件中读取

2、内存储存

  • 静态储存解析成运行时数据,存放在方法区

  • 堆区生成该类的Class对象,作为方法区这个类的各种数据的访问入口

链接

验证

验证阶段主要是为了为了确保Class文件的字节流中包含的信息符合虚拟机要求,并且不会危害虚拟机。

而验证主要分为以下四类:

  • 文件格式验证

  • 元数据验证

  • 字节码验证

  • 符号引用验证

准备

准备阶段会为类的静态变量分配内存、赋初值

数据类型 零值
int 0
long 0L
short (short)0
char ‘\u0000’
byte (byte)0
boolean false
float 0.0f
double 0.0d
reference null

需要注意的有以下几点:

  • 实例变量是在创建对象的时候完成赋值的,没有赋初值一说
  • final修饰的常量在编译的时候会给属性添加ConstantValue属性,准备阶段直接完成赋值,即没有赋初值这一步

解析

解析阶段会将符号引用替换为直接引用,该过程也被称为静态链接

1、符号引用

以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可

2、直接引用

可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。而直接引用必须引用的目标已经在内存中存在

3、动态链接

即符号引用替换为直接引用的阶段,该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针或句柄等(直接引用)。

初始化

初始化阶段是执行类构造器 <clinit>() 方法的过程。这一步主要的目的是:根据程序员程序编码制定的主观计划去初始化类变量和其他资源。

1、执行类构造器<clinit>()方法的过程

  • 对类的静态变量初始化为指定的值,执行静态代码块
  • 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
  • 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步
  • 当范围一个Java类的静态域时,只有真正声名这个域的类才会被初始化

2、初始化的时机

需要在主动引用时,才会执行初始化

  • new、getstatic、putstatic、invokestatic
  • 对内进行反射调用时
  • 初始化一个类的子类会去加载其父类
  • 启动程序所使用的main方法所在类
  • 当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果

除了主动引用外,还有以下三种情况被称为被动引用,不会触发初始化

  • 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
  • 定义对象数组和集合,不会触发该类的初始化
  • 类A引用类B的static final常量不会导致类B初始化(注意静态常量必须是字面值常量,否则还是会触发B的初始化)

三、触发类加载过程的时机

触发类加载过程的时机主要分为隐式加载显示加载两种情况

隐式加载

  • 创建类对象
  • 使用类的静态域
  • 创建子类对象
  • 使用子类的静态域
  • 在JVM启动时,BootStrapLoader会加载一些JVM自身运行所需的class
  • 在JVM启动时,ExtClassLoader会加载指定目录下一些特殊的class
  • 在JVM启动时,AppClassLoader会加载classpath路径下的class,以及main函数所在的类的class文件

显示加载

  • ClassLoader.loadClass(className):只加载和连接、不会进行初始化
  • Class.forName(String name, boolean initialize,ClassLoader loader):使用ClassLoader进行加载和连接,根据参数initialize决定是否初始化。

四、类加载完成后在内存中储存

类加载完成后主要包括类信息以及类Class对象,其中类信息保存在方法区中,类Class对象保存在堆区

类信息主要包含运行时常量池、类型信息、字段信息、方法信息、类加载器的引用、对应class实例的引用等信息。

类加载器的引用:这个类到类加载器实例的引用

对应class实例的引用:类加载器在加载类信息放到方法区中后,会创建一个对应的Class 类型的对象实例放到堆(Heap)中, 作为开发人员访问方法区中类定义的入口和切入点

JVM系列(一):JVM类加载过程详解相关推荐

  1. Java类加载过程详解

    类的生命周期 类的加载 类加载过程 加载 链接 验证 准备 解析 初始化 总结 首先我们先简单了解一下整个JVM的体系结构是怎样的,如下图所示(图1): 再详细具体一点(图2): 上面的图片有些地方看 ...

  2. 最通俗易懂的JAVA虚拟机类加载过程详解,看完还不懂你考虑转行吧!

    前言 当程序使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.链接.初始化三个步骤对该类进行类加载. Java Class文件 class文件是一组以8位字节为基础的二进制流,各个数据项目 ...

  3. SAP License:SAP ECC6安装系列四:安装过程详解

    续接上篇,我们终于按下了 "Next"按钮,正式开始安装 SAP 了,下面一步步的简单进行说明,因为实在是很傻瓜的软件安装过程,唯一与众不同的,就是所需要的时间真的很长,一般来说8 ...

  4. JVM之类加载阶段详解

    JVM之类加载阶段详解 类加载阶段总览 加载 获取二进制流 将字节流转换为运行时数据结构 堆中生成Class对象 特殊 连接 验证 准备 解析 名词解释 何时进行 解析哪些类型 初始化 类 接口 使用 ...

  5. 类加载顺序及加载过程详解

    转自: 类加载顺序及加载过程详解 下文笔者讲述类的加载顺序及加载过程的详解说明,如下所示 java创建对象的方式分为以下四种 new 反射克隆反序列化 class对象获取的方式分享 //没有完成初始化 ...

  6. JVM垃圾回收算法与原理详解

    垃圾回收 参考文档 GC参考手册-Java版 理解Java的强引用.软引用.弱引用和虚引用 JVM系列(五) - JVM垃圾回收算法 如何判断对象可以回收 引用计数法 参考文章 Java JVM的引用 ...

  7. jvm与Tomcat调优【详解】——有这一篇就够了

    jvm与Tomcat调优 一.JVM性能调优 1.1 什么是JVM? 1.2 JVM调优工具 1.3 JVM调优经验 1.4常用JVM参数参考: 1.5 Java文件编译的过程 1.6 为什么说jav ...

  8. 内存分配策略(一):JVM栈桢及方法调用详解

    JVM 线程堆栈分析过程详解 在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因.在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术.在线程堆栈中 ...

  9. 深入理解Java虚拟机之Java类加载机制,Java类实例化过程详解。

    目录 Java类加载机制 类加载过程 加载(Loading) 连接(Linking) 初始化(Initialzation) 使用(Useing) 卸载(Unloading) 引言 什么情况下开始类加载 ...

最新文章

  1. 【Python】函数默认参数怎么改变?
  2. php 变量源码,PHP源码中变量存储方式
  3. 实战Makefile
  4. PHP关于函数的参数问题
  5. jdk1.8下载安装教程
  6. SpringBoot整合jersey
  7. Windows 下安装 TensorFlow 2.2 GPU 版 教程:坑多,整理出来方便大家
  8. 可编译易用的模块化nf-HiPAC移植成功
  9. 【计算机组成原理】微命令 微指令 微操作 微程序
  10. 发一个mir2的内挂代码
  11. 【外文翻译】外国友人写得很不错的Java Lambda表达式入门教程,我终于翻译好给大家啦!!!...
  12. 无驱、代码自动植入:新一代软件保护锁——圣天诺LDK-HL
  13. Pytorch分布式训练/多卡训练(二) —— Data Parallel并行(DDP)(2.2)(代码示例)(BN同步主卡保存梯度累加多卡测试inference随机种子seed)
  14. 内是不是半包围结构_半包围结构是什么意思 半包围结构字的书写规则
  15. 20年的星际争霸,再回首
  16. Non-parametric Classifiers
  17. P1497 木牛流马 题解
  18. Android 开发之 ContentProvider 内容提供者
  19. leaflet离线地图(开发总结)
  20. 01-Docker基本管理

热门文章

  1. 【数据压缩3】AVI文件格式分析及问题回答+WAV文件格式分析
  2. 使用批处理实现完整备份Outlook 2010和恢复
  3. 如何用200元打造自己的4G数传模块
  4. nginx静态代理图片
  5. 电池管理系统 (BMS)
  6. 年轻人的生活方式:玩命工作
  7. php手机省电,手机耗电量越来越多,这个开关一定要关掉!用电量才不会愈来愈高...
  8. web前段开发(第五周)
  9. 操作系统I/O控制方式详解
  10. Cocos2dx 物体按指定轨迹匀速运动 (坐标均距)