常量池:
即class文件常量池,是class文件的一部分,用于保存编译时确定的数据。
保存的内容如下图:
package lime;
/**
* @Author liangmy
* @Date 2019/1/22
*/
/**
* 常量池:
* <p>
* 即class文件常量池,是class文件的一部分,用于保存编译时确定的数据。
* 常量池项:
* 1* 字面量
* 1.1* 文本字符串
* 1.2* 被声明为final的常量值
* 1.3* 基本数据类型的值
* 1.4* 其他(其他是个什么玩意)
* 2* 符号引用
* 2.1* 类的完全限定名
* 2.2* 字段名称和描述符
* 2.3* 方法名称和描述符
*/
public class Main {
private int fieldInt;
public void showTime() {
System.out.println("show time");
}
public static void main(String[] args) {
String string = "lime";
final byte finalByte = 1;
final short finalShort = 2;
final int finalInt = 4;
final long finalLong = 8;
final Object finalObject = new Object();
byte b = 1;
short s = 2;
int i = 4;
long l = 8;
}
}
javac Main.java
javap -verbose Main
警告: 二进制文件Main包含lime.Main
Compiled from "Main.java"
public class lime.Main {
public lime.Main();
public void showTime();
public static void main(java.lang.String[]);
}
localhost:lime liangmy$ javap -verbose Main
警告: 二进制文件Main包含lime.Main
Classfile /Users/liangmy/ideaProjects/lime/src/main/java/lime/Main.class
Last modified 2019-12-27; size 558 bytes
MD5 checksum 9d231ec6e27ca000980573bfb6338e05
Compiled from "Main.java"
public class lime.Main
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#21 // java/lang/Object."<init>":()V
#2 = Fieldref #22.#23 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #24 // show time
#4 = Methodref #25.#26 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = String #27 // lime
#6 = Class #28 // java/lang/Object
#7 = Long 8l
#9 = Class #29 // lime/Main
#10 = Utf8 fieldInt
#11 = Utf8 I
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 showTime
#17 = Utf8 main
#18 = Utf8 ([Ljava/lang/String;)V
#19 = Utf8 SourceFile
#20 = Utf8 Main.java
#21 = NameAndType #12:#13 // "<init>":()V
#22 = Class #30 // java/lang/System
#23 = NameAndType #31:#32 // out:Ljava/io/PrintStream;
#24 = Utf8 show time
#25 = Class #33 // java/io/PrintStream
#26 = NameAndType #34:#35 // println:(Ljava/lang/String;)V
#27 = Utf8 lime
#28 = Utf8 java/lang/Object
#29 = Utf8 lime/Main
#30 = Utf8 java/lang/System
#31 = Utf8 out
#32 = Utf8 Ljava/io/PrintStream;
#33 = Utf8 java/io/PrintStream
#34 = Utf8 println
#35 = Utf8 (Ljava/lang/String;)V
{
public lime.Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 23: 0
public void showTime();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String show time
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 27: 0
line 28: 8
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=13, args_size=1
0: ldc #5 // String lime
2: astore_1
3: new #6 // class java/lang/Object
6: dup
7: invokespecial #1 // Method java/lang/Object."<init>":()V
10: astore 7
12: iconst_1
13: istore 8
15: iconst_2
16: istore 9
18: iconst_4
19: istore 10
21: ldc2_w #7 // long 8l
24: lstore 11
26: return
LineNumberTable:
line 31: 0
line 36: 3
line 37: 12
line 38: 15
line 39: 18
line 40: 21
line 41: 26
}
SourceFile: "Main.java"
运行时常量池:
Java语言并不要求常量一定只能在编译期产生,运行期间也可能产生新的常量,这些常量被放在运行时常量池中。
类加载后,常量池中的数据会在运行时常量池中存放!
这里所说的常量包括:基本类型包装类(包装类不管理浮点型,整形只会管理-128到127)和String(也可以通过String.intern()方法可以强制将String放入常量池)
字符串常量池:
HotSpot VM里,记录interned string的一个全局表叫做StringTable,它本质上就是个HashSet<String>。注意它只存储对java.lang.String实例的引用,而不存储String对象的内容
jdk 1.7后,移除了方法区间,运行时常量池和字符串常量池都在堆中。