JVM -- 类加载(七)

2023-10-27

一、加载

将类的字节码载入方法区中,内部采用 C++ 的 instanceKlass 描述 java 类,它的重要 field 有

_java_mirror 即 java 的类镜像,如对 String 来说,就是 String.class,作用是把 klass 暴 露给 java 使用

_super 即父类

_fields 即成员变量

_methods 即方法

_constants 即常量池

_class_loader 即类加载器

_vtable 虚方法表

_itable 接口方法表

如果这个类还有父类没有加载,先加载父类

加载和链接可能是交替运行的

注:

instanceKlass 这样的【元数据】是存储在方法区(1.8 后的元空间内),但 _java_mirror 是存储在堆中 可以通过 HSDB 工具查看

二、链接

static 变量分配空间,设置默认值

1、static 变量在 JDK 7 之前存储于 instanceKlass 末尾,从 JDK 7 开始,存储于 _java_mirror 末尾

2、static 变量分配空间和赋值是两个步骤,分配空间在准备阶段完成,赋值在初始化阶段完成

3、如果 static 变量是 final 的基本类型,以及字符串常量,那么编译阶段值就确定了,赋值在准备阶 段完成

4、如果 static 变量是 final 的,但属于引用类型,那么赋值也会在初始化阶段完成

public class Load1 {
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        ClassLoader classloader = Load1.class.getClassLoader();
        Class<?> c = classloader.loadClass("com.mycompany.load.C");

        //new C();
        System.in.read();
    }
}

class C {
    D d = new D();
}

class D {

}

loadClass() 方法

public static void main(java.lang.String[]) throws java.lang.ClassNotFoundException, java.io.IOException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: ldc           #2                  // class com/mycompany/load/Load1
         2: invokevirtual #3                  // Method java/lang/Class.getClassLoader:()Ljava/lang/ClassLoader;
         5: astore_1
         6: aload_1
         7: ldc           #4                  // String com.mycompany.load.C
         9: invokevirtual #5                  // Method java/lang/ClassLoader.loadClass:(Ljava/lang/String;)Ljava/lang/Class;
        12: astore_2
        13: getstatic     #6                  // Field java/lang/System.in:Ljava/io/InputStream;
        16: invokevirtual #7                  // Method java/io/InputStream.read:()I
        19: pop
        20: return
      LineNumberTable:
        line 7: 0
        line 8: 6
        line 11: 13
        line 12: 20
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      21     0  args   [Ljava/lang/String;
            6      15     1 classloader   Ljava/lang/ClassLoader;
           13       8     2     c   Ljava/lang/Class;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
           13       8     2     c   Ljava/lang/Class<*>;
    Exceptions:
      throws java.lang.ClassNotFoundException, java.io.IOException

new C();

public static void main(java.lang.String[]) throws java.lang.ClassNotFoundException, java.io.IOException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: new           #2                  // class com/mycompany/load/C
         3: dup
         4: invokespecial #3                  // Method com/mycompany/load/C."<init>":()V
         7: pop
         8: getstatic     #4                  // Field java/lang/System.in:Ljava/io/InputStream;
        11: invokevirtual #5                  // Method java/io/InputStream.read:()I
        14: pop
        15: return
      LineNumberTable:
        line 10: 0
        line 11: 8
        line 12: 15
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     0  args   [Ljava/lang/String;
    Exceptions:
      throws java.lang.ClassNotFoundException, java.io.IOException

三、初始化

<cinit>()V 方法

初始化即调用<cinit>()V ,虚拟机会保证这个类的『构造方法』的线程安全

调用时机

1、类初始化是【懒惰的】

1、main 方法所在的类,总会被首先初始化

2、首次访问这个类的静态变量或静态方法时

3、子类初始化,如果父类还没初始化,会引发

4、子类访问父类的静态变量,只会触发父类的初始化

5、Class.forName

6、new 会导致初始化

2、不会导致类初始化的情况

1、访问类的 static final 静态常量(基本类型和字符串)不会触发初始化

2、类对象.class 不会触发初始化

3、创建该类的数组不会触发初始化

4、类加载器的 loadClass 方法

5、Class.forName 的参数 2 为 false 时

public class Load2 {
    static {
        System.out.println("main init");
    }

    public static void main(String[] args) throws ClassNotFoundException, IOException {
        //System.out.println("========不会导致类初始化的情况========");
        // 1. 静态常量不会触发初始化
        //System.out.println(B.b);
        //main init
        //5.0

        // 2. 类对象.class 不会触发初始化
        //System.out.println(B.class);
        //main init
        //class com.mycompany.load.B

        // 3. 创建该类的数组不会触发初始化
        //System.out.println(new B[0]);
        //main init
        //[Lcom.mycompany.load.B;@511d50c0

        // 4. 不会初始化类 B,但会加载 B、A
//        ClassLoader cl = Thread.currentThread().getContextClassLoader();
//        cl.loadClass("com.mycompany.load.B");
        //main init

        // 5. 不会初始化类 B,但会加载 B、A
//        ClassLoader c2 = Thread.currentThread().getContextClassLoader();
//        Class.forName("com.mycompany.load.B", false, c2);
        //main init

        System.out.println("========类初始化========");

        // 1. 首次访问这个类的静态变量或静态方法时
        //System.out.println(A.a);
        //main init
        //a init
        //0

        // 2. 子类初始化,如果父类还没初始化,会引发
        //System.out.println(B.c);
        //main init
        //a init
        //b init
        //false

        // 3. 子类访问父类静态变量,只触发父类初始化
        //System.out.println(B.a);
        //main init
        //a init
        //0

        // 4. 会初始化类 B,并先初始化类 A
        Class.forName("com.mycompany.load.B");
        //main init
        //a init
        //b init
    }
}

class A {
    static int a = 0;
    static {
        System.out.println("a init");
    }
}

class B extends A {
    final static double b = 5.0;
    static boolean c = false;
    static {
        System.out.println("b init");
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM -- 类加载(七) 的相关文章

  • Java 接口合成方法生成,同时缩小返回类型

    我有 2 个接口和 2 个返回类型 interface interfaceA Publisher
  • Intellij Idea 使用什么 JVM 来启动?

    我是 Eclipse 用户 最近决定尝试 Intellij Idea 我的操作系统是 Ubuntu 12 使用 Eclipse 时 可以通过在 eclipse ini 中指定来轻松选择用于启动 Eclipse 的 JVM http wiki
  • jvm 如何以及何时何地更改 Linux 的最大打开文件值?

    在linux中 每个登录用户的每个进程的最大打开文件数有限制 如下所示 ulimit n 1024 当我学习java nio时 我想检查这个值 因为channel在Linux中也是一个文件 所以我编写了一个客户端代码来不断创建socketC
  • 监控 Java 应用程序上的锁争用

    我正在尝试创建一个小基准 在 Groovy 中 以显示几个同步方法上的高线程争用 当监控自愿上下文切换时 应该会出现高争用 在 Linux 中 这可以通过 pidstat 来实现 程序如下 class Res private int n s
  • 如何使用 Java 引用释放 Java Unsafe 内存?

    Java Unsafe 类允许您按如下方式为对象分配内存 但是使用此方法在完成后如何释放分配的内存 因为它不提供内存地址 Field f Unsafe class getDeclaredField theUnsafe Internal re
  • UseCompressedOops JVM 标志有什么作用以及何时应该使用它?

    HotSpot JVM 标志是什么 XX UseCompressedOops我应该做什么以及什么时候使用它 在 64 位 Java 实例上使用它 与不使用它 时 我会看到什么样的性能和内存使用差异 去年大多数 HotSpot JVM 都默认
  • 容器中的 JVM 计算处理器错误?

    最近我又做了一些研究 偶然发现了这一点 在向 OpenJDK 团队抱怨之前 我想看看是否有其他人观察到这一点 或者不同意我的结论 因此 众所周知 JVM 长期以来忽略了应用于 cgroup 的内存限制 众所周知 现在从 Java 8 更新某
  • 测量 tomcat 的排队请求数

    因此 使用tomcat 您可以设置acceptCount值 默认为100 这意味着当所有工作线程都忙时 新连接被放置在队列中 直到队列满 之后它们被拒绝 我想要的是监视此队列中项目的大小 但无法确定是否有办法通过 JMX 获取此值 即不是队
  • 无法为对象堆保留足够的空间

    每次尝试运行该程序时 我都会重复出现以下异常 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机 我尝试增加虚拟内存 页面大小 和 RAM 大小 但无济于事 我怎样才能消除这个错误 运行 JVM XX MaxHeap
  • 调整 Java 类以提高 CPU 缓存友好性

    在设计java类时 对于实现CPU缓存友好性有哪些建议 到目前为止我学到的是应该尽可能多地使用 POD 即 int 而不是整数 这样 在分配包含对象时 数据将被连续分配 例如 class Local private int data0 pr
  • 使用 libjvm.so 时出现 Sigsegv Java 致命错误

    我正在做重启测试Sles12sp2 using STAF v3 4 24一段时间后我收到此错误 A fatal error has been detected by the Java Runtime Environment SIGSEGV
  • Android java.exe 以非零退出值 1 结束 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我尝试过查看类似的解决方案 但没有解决方案有效 我以前运行应用程序没有问题 但我的新应用程序突然开始给我带来问题 当我尝试运行它时总是
  • 使用 Coldfusion 11 的 CFdirectory,文件名中存在非 ASCII 字符问题

    我有一个类似的问题 ColdFusion CFDirectory 和法语 https stackoverflow com questions 1715632 coldfusion cfdirectory and the french从而没有
  • 将 Kotlin .kt 类打包到 JAR 中

    我如何构建HelloWorld kt as a JAR以便它运行 thufir dur kotlin thufir dur kotlin kotlinc HelloWorld kt include runtime d HelloWorld
  • JVM锯齿状空闲进程

    我目前正在进行一项涉及 JVM 及其内存使用工作原理的研究 我不明白的是 JVM在空闲时用什么填充它的内存 只是为了在堆几乎达到时释放它 为什么使用的内存不只有一条平线 顺便说一句 这个 java 应用程序托管在 glassfish 上 但
  • 如何制作.Net或JVM语言?

    我看到了 NET 和 JVM 的所有这些新语言 一个人如何开始制作一个 我找不到关于 JVM 或 MSIL 规范的任何好的文档 Edit 我已经知道如何解析 我更感兴趣的是如何有这么多人基于这些平台创建新语言 你有点幸运 为 NET 开发的
  • Java:为什么.class文件中的方法类型包含返回类型,而不仅仅是签名?

    class 文件的常量池中有一个 NameAndType 结构 它用于动态绑定 该类可以 导出 的所有方法都被描述为 签名 返回类型 喜欢 getVector Ljava util Vector 当某些 jar 中方法的返回类型发生更改时
  • Dart/Flutter 如何编译到 Android?

    我找不到任何具体的资源 Dart 是否被编译到 JVM 或者 Google 的团队是否编译了 Dart VM 以在 JVM 上运行 然后在 JVM 内的 Dart VM 中运行 Dart 前者更有意义 并且符合 无桥 的口号 但后者似乎更符
  • 限制 Java 进程的总内存消耗(在 Cloud Foundry 中)

    与这两个问题相关 如何设置JVM的最大内存使用量 https stackoverflow com questions 1493913 how to set the maximum memory usage for jvm 什么会导致 jav
  • 哪个更快:instanceof 或 isInstance?

    抛开设计问题不谈 什么在现代 JVM 上执行得更快 foo instanceof Bar or Bar class isInstance foo Why Class isInstance是 JVM 固有的 它被编译为与instanceof完

随机推荐

  • 产生java.lang.NullPointerException报错的原因

    产生java lang NullPointerException报错的原因 java lang NullPointerException 异常产生原因 public class Test public static void main St
  • Vue中created和mounted详解

    目录 一 生命周期概念 二 浏览器渲染过程 三 生命周期中的浏览器渲染 beforeCreate阶段 created阶段 beforeMount阶段 mounted阶段 四 使用场景 五 常见相关问题 一些页面跳转后 一些基础数据接口没有重
  • @Autowired 自动注入的service 对象为null

    问题 在controller层新加一个接口 调用自动注入的service对象操作数据库 发现service对象为null 排查 奇了怪了 同在一个controller里 其他接口怎么都正常 当然网上一顿找 发现有如下几种可能 当使用 Aut
  • 兆易创新2022数字芯片笔试题

    1 如下图assertion 请问图示波型哪个周期可以判定success 如图所示 本条断言的意思大体是 EN信号高电平有效 等到A上升沿的时候 其前一个周期 B 成立 等待0个周期 B C 成立 等待1个周期 D为1的过程中 B C 语句
  • 如何删除linux系统下的非空目录

    标题 如何删除linux系统下的非空目录 删除目录的常用shell命令为 rm rm 是一个用于删除文件和目录的命令行实用程序 与 rmdir命令不同 rm 可以删除空目录和非空目录 rmdir命令是什么的知识点补充在最下边 默认情况下 在
  • CMake中使用get_target_property判断Target是否存在

    使用Cmake的add custom target建立自定义的Target后 必须将这个Target加入all依赖 否则生成的Makefile不会执行这个Target的内容 这样会有个问题 如果需要编译如下目录 目录下有N个目录 这些目录下
  • gRPC那点事

    什么是 gRPC gRPC gRPC Remote Procedure Call 是一种高性能 开源的远程过程调用 RPC 框架 它允许分布在不同计算机上的应用程序能够像调用本地方法一样进行通信 从而实现了在分布式系统中进行高效的通信 传统
  • 手把手教你搭建Scala开发环境 步骤详细

    个人主页 csdn春和 推荐专栏 JavaWeb专栏 从入门到实战超详细 本期文章 搭建Scala开发环境 如果对您有帮助还请三连支持 定会一 一回访 本文目录 一 Scala开发环境搭建 1 1 安装scala 1 2 scala插件安装
  • scala学习-12-scala读取java项目下Src目录下的properties文件

    1 概述 scala读取java项目下Src目录下的properties文件 package scala import java util Properties import java io FileInputStream import s
  • springbootweb请求响应

    web三层架构流程 先是前端传送一个请求给后端 然后controller层接受数据进行处理 传给service层进行逻辑处理再交给dao层 dao层访问数据库 数据库再返回数据给dao层 然后再传给service层处理 最后回到contro
  • ResourceUtils

    ResourceUtils org springframework util ResourceUtils 从资源路径获取文件 判断字符串是否是一个合法的 URL 字符串 static boolean isUrl String resourc
  • Java自动装箱和自动拆箱

    基本类型的包装类 在java中 每一种基本类型都有一个对应的包装类 这些类都在java lang包中 8种基本数据类型所对应的包装类是byte Byte short Short int Integter long Long char Cha
  • 【金融系列】使用Python分析债券,画零息利率曲线,对债券进行精确定价,计算债券的麦考利久期、修正久期和凸度,并进行价格敏感性分析

    目前许多代码和资源在进行债券定价时 大多以债券发行日作为贴现值的时间点 但在实际应用中我们常常需要对早就发行的债券进行定价 这就需要计算准确的现金流 现金流日距离当前贴现时间点的时间距离和不同时间距离的零息利率 这一过程会较多使用插值法 还
  • css中的渐变的属性,CSS3 渐变属性(Gradients)-线性渐变(linearGradient)

    通过使用 CSS3 渐变 gradients 你可以减少下载的事件和宽带的使用 此外 渐变效果的元素在放大时看起来效果更好 因为渐变 gradient 是由浏览器生成的 丛本质上来说 既然 background image 属性中的渐变是浏
  • element框架table多选分页时保留原有选中项(vue2和vue3均适用)

    element中table表格多选 分页 1 表格多选 手动添加一个 el table column 设 type 属性为 selection 即可
  • DLT(Direct Linear Transform)算法

    一 定义 直接线性变换解法是建立像点的 坐标仪坐标 和相应物点的物方空间坐标直接的线性关系的解法 直接线性变换解法的特点 不归心 不定项 不需要内外方位元素的起始值 物方空间需布置一组控制点 特别适合于处理非量测相机所摄影像 本质是一种空间
  • 数据结构常用的算法

    一 排序算法 本质上就是按照某种顺序将一组数排好 分多次重复进行 每次只负责把一个数字放到合适的位置上 两种思路 先确定一个数字 然后根据数据找合适的位置 先确定一个位置 根据位置找合适的数字 1 冒泡排序算法 先确定位置 选最前面或者最后
  • 解决protobuf内存泄漏的3种办法

    1 protobuf对象是如何释放 数组 内存的 毫无疑问是 通过调用析构函数 只要让protobuf定义的对象调用析构函数 无论嵌套了多少层数据 包含了多少个数组都可以释放new出来的内存 2 protobuf对象Clear 接口和STL
  • clickhouse系列第三篇之clickhouse客户端使用教程(1.命令行客户端连接)

    文章目录 一 客户端支持的配置项 1 配置项的配置方式 1 1 从命令行传入 1 2 配置文件 2 配置项列表 二 客户端用法 1 非交互模式 1 1 query 参数指定执行语句 1 2 query 参数和发送到stdin的数据联合使用
  • JVM -- 类加载(七)

    一 加载 将类的字节码载入方法区中 内部采用 C 的 instanceKlass 描述 java 类 它的重要 field 有 java mirror 即 java 的类镜像 如对 String 来说 就是 String class 作用是