• 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对象的数据又是从 方法区的字节码文件的运行时结构获取的。

      好了,就说这么多啦!!

  • 相关阅读:
    spring boot 启动后执行初始化方法
    Linux CentOS 7 下 JDK 安装与配置
    Linux rpm 命令参数使用详解[介绍和应用]
    异常处理: 重载Throwable.fillInStackTrace方法已提高Java性能
    dubbo 配置属性
    centos7 操作防火墙
    springBoot 打包 dubbo jar包
    直播中聊天场景的用例分享
    解决在安装Fiddler4.6版本后,在手机上安装证书出现的问题解决方法
    系统调优方案思路分享
  • 原文地址:https://www.cnblogs.com/ibcdwx/p/14494997.html
Copyright © 2020-2023  润新知