jvm常量池,运行时常量池,字符串常量池

    jvm中的常量池分为三种

    1.类文件常量池(Class Constant Pool) 也称静态常量池

    2.运行时常量池(Runtime Constant Pool)

    3.字符串常量池(String Constant Pool)

1.类文件常量池

         我们写的每一个Java类被编译后,就会形成一份class文件(每个class文件都有一个class常量池)。 class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。

        字面量包括:1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;

       符号引用包括:1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

2. 运行时常量池
        运行时常量池(Runtime Constant Pool)是方法区的一部分。jdk1.8以前存在于永久代,jdk1.8之后存在于元空间。静态常量池中的内容,在类加载后会被存放到方法区的运行时常量池中。运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是说,并非预置入Class文件中静态常量池的内容才能进入方法区运行时常量池,运行期间也可以将新的常量放入池中。

3.字符串常量池

        字符串常量池存在运行时常量池之中(在JDK7之前存在运行时常量池之中,在JDK7已经将其转移到堆中)。字符串常量池的存在使JVM提高了性能和减少了内存开销。

        字符串常量池可以理解为是分担了部分运行时常量池的工作。和其他的对象分配一样,字符串耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能,为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化,为字符串开辟一个字符串常量池,类似于缓存区。实现该优化的基础是因为字符串是不可变的,可以不用担心数据冲突进行共享。运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用。

        加载时,对于class文件的静态常量池,字符串字面量会进入到当前类的运行时常量池,但不会立即进入全局的字符串常量池(即在字符串常量池中并没有相应的引用,在堆中也没有对应的对象产生),字符串常量池是lazy resolve的,在第一次引用该项的ldc指令被第一次执行到的时候才会resolve,但这个过程我们可以不关注。可以认为当类加载完成后,运行代码String str1="abc"或String str2=new String(“abc”)时,字面量“abc”已经存在于字符串常量池。jdk7字符串常量池以后存在于堆中。

说明:

        HotSpot虚拟机在jdk8以前是用永久代(Permanent Generation)实现方法区,永久代和方法区这两者不是等价的,对于其他虚拟机实现,譬如BEA JRockit、IBM J9等来说,是不存在永久代的概念的。因为仅仅是当时的HotSpot虚拟机设计团队选择把收集器的分代设计扩展至方法区,或者说使用永久代来实现方法区而已,这样使得HotSpot的垃圾收集器能够像管理Java堆一样管理这部分内存,省去专门为方法区编写内存管理代码的工作。

        在JDK1.7之前 运行时常量池逻辑包含字符串常量池存放在方法区, 此时hotspot虚拟机对方法区的实现为永久代。静态常量池在Class文件中。

        在JDK1.7 字符串常量池被从方法区拿到了堆(方法区是堆的一个逻辑分区)中, 这里没有提到运行时常量池,也就是说字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代。静态常量池在Class文件中。

        在JDK1.8及之后 hotspot移除了永久代用元空间(Metaspace)取而代之, 这时候字符串常量池还在堆, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间(Metaspace)。静态常量池在Class文件中。

        如下图Java堆内存结构,注意,在Java虚拟机规范将永久代(方法区)中描述为Java堆的一个逻辑部分。

 

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值