美文网首页
JVM 各种常量池傻傻分不清?

JVM 各种常量池傻傻分不清?

作者: M_lear | 来源:发表于2020-07-17 21:25 被阅读0次

总体上有如下四种常量池:
class 文件中的常量池、运行时常量池、字符串常量池、符号常量池。

class 文件中的常量池:一个类对应一个 class 文件,每个 class 文件中都有一个常量池。这个常量池是一个静态的常量池,存在于文件中,而不是内存中。记录了类中的字面量和符号引用。

运行时常量池:与 class 文件中静态的常量池相对的是 JVM 进程中的运行时常量池,运行时常量池是 JVM 加载 class 文件(类加载)后,class 文件中的常量池在内存中的表现形式,存储在 JVM 的方法区。显然,运行时常量池和类也是一一对应的。

字符串常量池:管理字符串常量(String)的常量池。是全局共享的,整个 JVM 进程中只有一个。

符号常量池:管理符号常量(Symbol)的常量池。是全局共享的,整个 JVM 进程中只有一个。

总是说常量池常量池,这个池子(pool)究竟是什么样的呢?所有常量池的池子都是一样的吗?
当然不一样,池(pool)只是用来表达存放数据的含义,具体这个数据怎么存,跟 pool 这个词无关。对于 class 文件中的常量池来说,就是外存中文件里的一段二进制数据。对于运行时常量池来说就是内存中的一个数组。而对于字符串常量池和符号常量池来说就是内存中的一个哈希表。

JDK1.7 中各个常量池的内存分布:

java7

绿字表示和类对应,一个 JVM 进程里有多个。红字表示和 JVM 进程对应,一个 JVM 进程里只有一个。

JDK1.8 中各个常量池的内存分布:

java8

class 文件中的常量池

CONSTANT_Utf8 描述类中的所有字符串,真正存储字符串的常量,所有需要字符串的常量都通过引用这个类型的常量存储字符串。使用改进后的 utf-8 编码。

CONSTANT_Integer、CONSTANT_Long、CONSTANT_Float、CONSTANT_Double 描述类中的基本类型常量。(比较小的话不会放到常量池,直接嵌到字节码的操作数)
CONSTANT_String 描述类中的 String 常量,引用了 CONSTANT_Utf8 常量,自身并没有存储字符串。

CONSTANT_Class 描述当前类所依赖类的全限定名,用于加载所依赖的类
CONSTANT_Fieldref、CONSTANT_Methodref 和 CONSTANT_InterfaceMethodref 描述了当前类依赖的其它类的字段、方法和其它接口的方法。这三种常量又引用了 CONSTANT_Class、CONSTANT_NameAndType 共同构成了字段和方法的全限定名和描述符,用于寻找依赖字段和方法

关于 class 文件中常量池的描述,具体的可以参考 Java 虚拟机规范。

字符串常量池、符号常量池

字符串常量池和符号常量池持有的都是引用。String 常量在堆里,Symbol 常量(对应 CONSTANT_Utf8,是 C++ 对象,所有 CONSTANT_Utf8 常量在类加载时构造成 Symbol 对象,并放入全局的 SymbolTable,统一管理)在直接内存里。

字符串常量不会在类加载时就进入字符串常量池。
代码示例:

public class Test {

    static String test(){
        String a = "hehe";
        String b = "haha";
        return a+b;
    }
    
    public static void main(String[]args){
        String s1 = new StringBuilder().append("he").append("he").toString();
        System.out.println(s1 == s1.intern());
        Test.test();
        String s2 = new StringBuilder().append("ha").append("ha").toString();
        System.out.println(s2 == s2.intern());
    }

}

输出:
true
false

相关文章

  • JVM 各种常量池傻傻分不清?

    总体上有如下四种常量池:class 文件中的常量池、运行时常量池、字符串常量池、符号常量池。 class 文件中的...

  • 常量池、运行时常量池、字符串常量池

    常量池、运行时常量池、字符串常量池 Java里包含各种常量池,经常傻傻分不清楚,下面就简单梳理下Java中的池们。...

  • JVM-常量池

    JVM-常量池 JVM常量池分为 Class文件常量池 运行时常量池 全局字符串常量池 基本类型包装类对象常量池 ...

  • java基础类型、String类理解、版本对比、1.8新特性

    1、java基本数据类型及长度 2、jvm的常量池: JVM常量池浅析Java常量池理解与总结 Java中的常量池...

  • 彻底弄懂java中的常量池

    JVM有几种常量池 主要分为: Class文件常量池、运行时常量池,全局字符串常量池,以及基本类型包装类对象常量池...

  • JVM常量池

    1 Class常量池 .java文件通过编译器编译后会生成.class(字节码)文件。class文件中除了包含类的...

  • 深入浅出JVM常量池

    常量池在JVM中分为三种:字符串常量池,运行时常量池,Class常量池讨论范围 JDK 1.7版本及以后 字符串常...

  • JVM(六)JVM常量池

    1.常量池类型 Java中的常量池分为三种: 类文件常量池(静态常量池)(The Constant Pool)运行...

  • JVM-常量池

    1,(全局)字符串常量池(String Constant Pool) 1)使用sun.jvm.hotspot.me...

  • JVM常量池浅析

      需要说明的一点是,这篇文章是以《深入理解Java虚拟机》第二版这本书为基础的,这里假设大家已经了解了JVM的运...

网友评论

      本文标题:JVM 各种常量池傻傻分不清?

      本文链接:https://www.haomeiwen.com/subject/koppihtx.html