Java面试点 — 常量池(按版本区分)

本文详细介绍了JDK中常量池的演变历程,从JDK6到JDK8,常量池的位置从方法区(永久代)迁移至堆中,再到元空间。探讨了字符串常量池、class常量池和运行时常量池的概念、作用及存储内容,以及它们在不同JDK版本中的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


参考文章:
JDK8的JVM内存结构,元空间替代永久代成为方法区及常量池的变化
静态常量池与运行时常量池

一、JDK版本变化

  • Java6和6之前,常量池是存放在方法区(永久代)中的。
  • Java7,将常量池是存放到了堆中。
  • Java8之后,取消了整个永久代区域,取而代之的是元空间。运行时常量池和静态常量池存放在元空间中,而字符串常量池依然存放在堆中。

二、常量池类型

在Java的内存分配中,总共3种常量池:

> 字符串常量池(String Constant Pool)

1. 字符串常量池在Java内存区域的哪个位置?

在JDK6.0及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中;
在JDK7.0版本,字符串常量池被移到了堆中了。至于为什么移到堆内,大概是由于方法区的内存空间太小了。

在永久代移除后,字符串常量池也不再放在永久代了,但是也没有放到新的方法区——元空间里,而是留在了堆里。运行时常量池当然是随着搬家到了元空间里,毕竟它是装类的重要等信息的,有它的地方才称得上是方法区。
在这里插入图片描述

2. 字符串常量池是什么?

在HotSpot VM里实现的String Pool功能的是一个StringTable类,它是一个Hash表,默认值大小长度是1009;这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享。字符串常量由一个一个字符组成,放在了StringTable上。
在JDK6.0中,StringTable的长度是固定的,长度就是1009,因此如果放入String Pool中的String非常多,就会造成hash冲突,导致链表过长,当调用String#intern()时会需要到链表上一个一个找,从而导致性能大幅度下降;
在JDK7.0中,StringTable的长度可以通过参数指定:
-XX:StringTableSize=66666

3. 字符串常量池里放的是什么?

在JDK6.0及之前版本中,String Pool里放的都是字符串常量;
在JDK7.0中,由于String#intern()发生了改变,因此String Pool中也可以存放放于堆内的字符串对象的引用。
需要说明的是:字符串常量池中的字符串只存在一份!
如:
String s1 = “hello,world!”;
String s2 = “hello,world!”;
即执行完第一行代码后,常量池中已存在 “hello,world!”,那么 s2不会在常量池中申请新的空间,而是直接把已存在的字符串内存地址返回给s2。

字符串常量池使用示例
在这里插入图片描述
在这里插入图片描述

> class常量池(Class Constant Pool)

1. class常量池简介

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

2. 什么是字面量和符号引用

字面量包括:1. 文本字符串 2. 八种基本类型的值 3. 被声明为final的常量等;
符号引用包括:1. 类和方法的全限定名 2. 字段的名称和描述符 3. 方法的名称和描述符。

> 运行时常量池(Runtime Constant Pool)

运行时常量池存在于内存中,也就是class常量池被加载到内存之后的版本,不同之处是:它的字面量可以动态的添加(String#intern()),符号引用可以被解析为直接引用;
JVM在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。
而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。
在解析阶段,会把符号引用替换为直接引用,解析的过程会去查询字符串常量池,也就是我们上面所说的StringTable,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值