类的加载过程

一、类的加载阶段

  类的加载阶段,其实就是将class字节码文件中的二进制数据读取到内存之中,然后将文件所代表的静态存储结构,转换为方法区中运行时的数据结构,并且在堆内存中生成一个该类的java.lang.Class对象,作为访问方法区数据结构的入口。

而在同一个类加载器下,无论一个类被加载多少次,堆内存里面的Class对象都只有唯一 的一个。

  而加载的方式也不仅仅是字节码文件或者说字节流的形式,还有我们都知道的动态代理,可以运行时动态生成字节码的字节流,从jar包中获取字节流等等,加载阶段不局限一种形式。

 

二、类的连接阶段

1、验证

  验证字节流的信息是否符合JVM的规范,保证不会出现危害JVM的代码。一般就是验证这个文件的格式,也就是头部信息是不是class文件,还有版本号,用高版本编译的文件是不能被低版本的兼容的;验证元数据的继承等进行语义分析是否合法;验证代码的控制流程等;还有就是符号引用的验证。

2、准备

  经过了验证之后,就会开始对该类对象的变量分配内存,并且设置初始值,而类变量的内存是分配在方法区中的,不同于实例变量。

3、解析

  这个阶段,其实就是把部分符号引用替换成直接引用。比如说

1 public class Tes1{
2     static Simple simple;
3 
4     public static void main(String[] args) {
5         System.out.println(simple);
6     }
7 }

在方法中引用了simple,那么在解析阶段就会在常量池找simple的符号引用,然后对simple加载,然后符号引用就会转换成直接引用,也就是simple的内存地址。

三、类的初始化阶段

  在这个阶段中,主要就是执行<clinit>()方法,在方法中,所有的类变量都会被赋予正确的值,以及执行静态语句块。

  <clinit>()这个方法是在编译阶段,由编译器自动生成在class文件中的,方法里面的执行顺序与源代码中的书写顺序是一致的!!!也就是说这个方法里面是可以保证执行顺序的!!!!而且JVM会保证父类的<clinit>()先执行。除此之外,这个方法在多线程环境下,JVM会保证它的同步语义,有且仅有一个线程执行<clinit>(),并且只会执行一次。

posted @   huang1993  阅读(143)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示