JVM中的几种常量池

点击查看原文中具体案例与解释

目录

一、class文件常量池

字面量

1、文本字符串:

2、被final修饰的变量。

符号引用

1、类和接口和全限定名:

2、字段的名称和描述符:

3、方法的名称和描述符。

二、运行时常量池

三、字符串常量池

四、java基本类型封装类的常量池

补充:t.intern()的用法


一、class文件常量池

在Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用。

这里简单解释下字面量和符号引用

字面量

字面量类似与我们平常说的常量,主要包括:

1、文本字符串:

就是我们在代码中能够看到的字符串,例如String a = “aa”。其中”aa”就是字面量。

2、被final修饰的变量。

符号引用

主要包括以下常量:

1、类和接口和全限定名:

例如对于String这个类,它的全限定名就是java/lang/String。

2、字段的名称和描述符:

所谓字段就是类或者接口中声明的变量,包括类级别变量(static)和实例级的变量。

3、方法的名称和描述符。

所谓描述符就相当于方法的参数类型+返回值类型

二、运行时常量池

我们上面说的class文件中的常量池,它会在类加载后进入方法区中的运行时常量池。并且需要的注意的是,运行时常量池是全局共享的,多个类共用一个运行时常量池。并且class文件中常量池多个相同的字符串在运行时常量池只会存在一份。

注意运行时常量池存在于方法区中。

三、字符串常量池

看名字我们就可以知道字符串常量池会用来存放字符串,也就是说常量池中的文本字符串会在类加载时进入字符串常量池。

那字符串常量池和运行时常量池是什么关系呢?上面我们说常量池中的字面量会在类加载后进入运行时常量池,其中字面量中有包括文本字符串,显然从这段文字我们可以知道字符串常量池存在于运行时常量池中。也就存在于方法区中。

不过在周志明那本深入java虚拟机中有说到,到了JDK1.7时,字符串常量池就被移出了方法区,转移到了里了。

那么我们可以推断,到了JDK1.7以及之后的版本中,运行时常量池并没有包含字符串常量池,运行时常量池存在于方法区中,而字符串常量池存在于中。

四、java基本类型封装类的常量池

1. 内存中有一个java基本类型封装类的常量池。这些类包括
Byte, Short, Integer, Long, Character, Boolean。需要注意的是,Float和Double这两个类并没有对应的常量池。

2.上面5种整型的包装类也只是在对象数值在-128~127才可以使用这些常量池。

3. 在周志明的那本虚拟机中有这样一句话:包装类的
“\==”运行符在不遇到算术运算的情况下不会自动拆箱,以及他们的equals()方法不处理数据类型的关系,可以推断出如果遇到“==”两边有算术运算是话就会自动拆箱和进行数据类型转换处理。

4.Long的equals方法会先判断是否是Long类型。

5.无论是Integer还是Long,他们的equals方法比较的是数值。

补充:t.intern()的用法

String t = "tt";

例如我们调用了t.intern()

在JDK1.6的时候,调用了这个方法之后,虚拟机会在字符串常量池在查找是否有内容与”tt”相等的对象,如果有,则返回这个对象,如果没有,则会在字符串常量池中添加这个对象。注意,是把这个对象添加到字符串常量池。

到了JDK1.7之后,如果调用了intern这个方法,虚拟机会在字符串常量池在查找是否有内容与”tt”相等的对象,如果有,则返回这个对象,如果没有。则会在堆中把这个对象的引用复制添加到字符串常量池中。注意,这个时候添加的是对象在堆中的引用。

发布了129 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41808387/article/details/104538306