Java-反射类加载到内存分析

  相信大家知道,类加载大概的意思是:当我们要运行编译后的class文件时,会有类加载器 把 class文件加载到内存中;实际上这个比较抽象,说具体点的话,应该是如下:

 

   嗯,好!相信大家看了之后还不懂啊,起初我也是一脸懵逼啊,现在逐个给大家解释。

  所谓类加载,细分应该是:类加载,类链接,类初始化。

    1. 类加载:由类加载器 class文件加载到内存中(说具体点就是方法去),并在 堆内存创建对应的class对象;

    2. 类链接:类链接细分的话也是分为3个步骤:

      》验证:校验 类结构是否符合JVM规范

      》准备:这个很重要,该阶段是为 类中 的 静态变量,注意是静态变量,为静态变量分配内存空间,并进去默认值的初始化。再提一句,静态变量的赋值和静态代码库的加载是在 类初始化中的,别搞混了

      》解析:讲符合引用替换为地址引用(这个不用深究)

    3. 类初始化:指的是 为 该类的变量(包括静态和非静态)进行赋值操作 以及 执行一些 预加载代码;下面讲详细点:

      》当类初始化的时候,首先会初始化他的父类

      》初始化类的时候,会执行类构造器<clinit>方法,这个方法里合并了 该类的类变量和静态代码块,比如代码如下:

public class ClassLoadDemo {

    static {
        System.out.println("静态代码块执行了");
        str = "20";
    }

    public static String str= "10";
}

      那 <clinit>方法大概就是这样:

    <clinit>(){
        System.out.println("静态代码块执行了");
        str = "20";
        str = "10";
    }

      需要大家注意一点:静态变量和静态代码块谁先加载,取决于他们在代码中的顺序,比如上面的静态代码块 放在 静态变量的前面,那静态代码块就先加载。

  还是给一段代码,然后详细说下大概的类加载过程是怎样的吧,如下:

 

     1. 该java文件,经过编译后会生成两个class文件,分别是Test05.class和 A.class

  2. 当使用 java.exe 执行Test05.class时,Test05.class会先加载到方法区中,接着A.class也同样加载到方法区,此时他们的数据结构会发送改变,变成运行时数据结构

  3. 在堆内存中生成 对应的两个class对象

  4. 在方法区中,为 静态变量m 分配内存,并赋予默认值 0

  5. 接着初始化Test05类,执行 <clinit>方法,即 执行 static代码块 和 m=100,则此时m=0

  6. main方法进栈,执行 A a = new A()时,会先初始化A类,执行其<clinit>,接着在堆内存创建 A 对象,执行构造A的构造方法

  7. 然后打印A.m,打印结构是m=100

大概的过程就是这样上面的步骤,然后需要细道的是:在堆内存中的 实例对象 中的 数据 是从class对象获取的,而class对象的数据又是从 方法区的字节码文件的运行时结构获取的。

  好了,就说这么多啦!!

posted @ 2021-03-07 15:59  爱编程DE文兄  阅读(255)  评论(0编辑  收藏  举报