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

常量池:

  即class文件常量池,是class文件的一部分,用于保存编译时确定的数据。

保存的内容如下图:

  

 1 D:\java\test\out\production\test>javap -verbose mainTest
 2 Classfile /D:/java/test/out/production/test/mainTest.class
 3   Last modified 2019年4月22日; size 507 bytes
 4   MD5 checksum 08699c6d713bc8967a8daea381ce23c1
 5   Compiled from "mainTest.java"
 6 public class mainTest
 7   minor version: 0
 8   major version: 55
 9   flags: (0x0021) ACC_PUBLIC, ACC_SUPER
10   this_class: #4                          // mainTest
11   super_class: #5                         // java/lang/Object
12   interfaces: 0, fields: 1, methods: 2, attributes: 1
13 Constant pool:
14    #1 = Methodref          #5.#25         // java/lang/Object."<init>":()V
15    #2 = Fieldref           #4.#26         // mainTest.age2:I
16    #3 = String             #27            // sss
17    #4 = Class              #28            // mainTest
18    #5 = Class              #29            // java/lang/Object
19    #6 = Utf8               age2
20    #7 = Utf8               I
21    #8 = Utf8               <init>
22    #9 = Utf8               ()V
23   #10 = Utf8               Code
24   #11 = Utf8               LineNumberTable
25   #12 = Utf8               LocalVariableTable
26   #13 = Utf8               this
27   #14 = Utf8               LmainTest;
28   #15 = Utf8               main
29   #16 = Utf8               ([Ljava/lang/String;)V
30   #17 = Utf8               args
31   #18 = Utf8               [Ljava/lang/String;
32   #19 = Utf8               name
33   #20 = Utf8               Ljava/lang/String;
34   #21 = Utf8               nick
35   #22 = Utf8               age
36   #23 = Utf8               SourceFile
37   #24 = Utf8               mainTest.java
38   #25 = NameAndType        #8:#9          // "<init>":()V
39   #26 = NameAndType        #6:#7          // age2:I
40   #27 = Utf8               sss
41   #28 = Utf8               mainTest
42   #29 = Utf8               java/lang/Object
43 {
44   public mainTest();
45     descriptor: ()V
46     flags: (0x0001) ACC_PUBLIC
47     Code:
48       stack=2, locals=1, args_size=1
49          0: aload_0
50          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
51          4: aload_0
52          5: bipush        22
53          7: putfield      #2                  // Field age2:I
54         10: return
55       LineNumberTable:
56         line 1: 0
57         line 2: 4
58       LocalVariableTable:
59         Start  Length  Slot  Name   Signature
60             0      11     0  this   LmainTest;
61
62   public static void main(java.lang.String[]);
63     descriptor: ([Ljava/lang/String;)V
64     flags: (0x0009) ACC_PUBLIC, ACC_STATIC
65     Code:
66       stack=1, locals=4, args_size=1
67          0: ldc           #3                  // String sss
68          2: astore_1
69          3: ldc           #3                  // String sss
70          5: astore_2
71          6: bipush        25
72          8: istore_3
73          9: return
74       LineNumberTable:
75         line 4: 0
76         line 5: 3
77         line 6: 6
78         line 7: 9
79       LocalVariableTable:
80         Start  Length  Slot  Name   Signature
81             0      10     0  args   [Ljava/lang/String;
82             3       7     1  name   Ljava/lang/String;
83             6       4     2  nick   Ljava/lang/String;
84             9       1     3   age   I
85 }
86 SourceFile: "mainTest.java"

运行时常量池:

  Java语言并不要求常量一定只能在编译期产生,运行期间也可能产生新的常量,这些常量被放在运行时常量池中。

  类加载后,常量池中的数据会在运行时常量池中存放

  这里所说的常量包括:基本类型包装类(包装类不管理浮点型,整形只会管理-128到127)和String(也可以通过String.intern()方法可以强制将String放入常量池)

字符串常量池:

  HotSpot VM里,记录interned string的一个全局表叫做StringTable,它本质上就是个HashSet<String>。注意它只存储对java.lang.String实例的引用,而不存储String对象的内容

jdk 1.7后,移除了方法区间,运行时常量池和字符串常量池都在堆中。

原文地址:https://www.cnblogs.com/natian-ws/p/10749164.html

时间: 2024-11-29 08:13:30

JVM 常量池、运行时常量池、字符串常量池的相关文章

JVM内存结构——运行时数据区

在Java虚拟机规范中将Java运行时数据划分为6种,分别为: PC寄存器(程序计数器) Java栈 堆 方法区 运行时常量池 本地方法栈 一.PC寄存器(程序计数器) PC寄存器(Program Counter Register)严格来说是一个数据结构,它用于保存当前正常执行的程序的内存地址. 线程私有. 每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器.PC寄存器里保存有当前正在执行的JVM指令的地址. 每个线程都需要一个独立的程序计数器,各条线程之间

JVM内存结构(运行时数据区)

前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些内存区域被统一叫做运行时数据区.Java运行时数据区大致可以划分为5个部分.在这里要特别指出,我们现在说的JVM内存划分是概念模型.如下图所示: JVM运行时数据区分为5种: 程序计数器 虚拟机栈(java栈) 堆 方法区 本地方法栈 程序计数器 程序计数器是一块较小的内存空间,它可

java中的编译时常量与运行时常量

常量是程序运行期间恒定不变的量,许多程序设计语言都有某种方式,向编译器告知一块数据是恒定不变的,例如C++中的const和Java中的final. 根据编译器的不同行为,常量又分为编译时常量和运行时常量,其实编译时常量肯定就是运行时常量,只是编译时常量在编译的时候就被执行计算,并带入到程序中一切可能用到它的计算式中. 以Java为例,static final int a = 1将是一个编译时常量,编译后的符号表中将找不到a,所有对a的引用都被替换成了1. 而static final int b

Jvm基础-Java运行时数据区

最近在看<深入理解Java虚拟机>,里面讲到了Java运行时数据区,这是Jvm基本知识,把读书笔记记录在此.这些知识属于常识,都能查到的,如果我有理解不对的地方,还请指出. 首先把图贴上来,图来自JVM Runtime Data Areas(运行时数据区),感谢. 由上图可知,Java运行时数据区域包括程序计数器.Java虚拟机栈.本地方法栈.Java堆.方法区. 1. 程序计数器 程序计数器用来记录下一条字节码指令,因为CPU是要轮转的,在切换回来之后,Java能够找到下一条要执行的指令.如

jvm内存模型(运行时数据区)

运行时数据区(runtime data area) jvm定义了几个运行时数据区,这些运行时数据区存储的数据,供开发者的应用或者jvm本身使用.按线程共享与否可以分为线程间共享和线程间独立. 线程间独立的运行时数据区 线程间独立的区域随线程的创建而创建,随线程销毁而销毁.线程独立的区域内存储的数据只有该线程能够访问,对其他线程是不可见的. 程序计数器寄存器(pc Register) 每个线程都有自己的pc(程序计数器)register(寄存器).在任意时点上,jvm中的线程只能执行一个类的一个方

JVM知识总结-运行时区域划分

区域简介 JVM运行时区域有些随着虚拟机进程的启动而存在,有些依赖于用户线程的启动和结束而建立和销毁,大致分为以下几类:方法区,虚拟机栈,本地方法栈,堆,程序计数器,概念图如下(源于<深入理解JAVA虚拟机-JVM高级特性>): 程序计数器 当前线程所执行的字节码的行号指示器,是一块各个线程私有的内存,每个线程都有一个独立的程序计数器: 如果线程执行的是一个JAVA方法,计数器记录的是虚拟机字节码指令的地址,如果执行的是一个Native方法,计数器值为空(Undefined): 唯一一个在JV

JVM三部曲之运行时数据区 (第一部)

在接下来的几天想总结下,JVM相关的一些内容,比如下面的这三个内容算是比较核心知识点了 1.运行时数据区域: 在运行时数据区里存储类Class文件元数据(方法区),对象和数组(堆),方法参数局部变量(栈)等. 2.垃圾回收机制: java 语言的优势之一就是它的自动内存管理,主要回收运行时数据区域的堆内存里的数据 3.类加载机制: 虚拟机首先需要把编译完成的字节码文件通过类加载器来加载到运行时数据区域 一个段Java代码的生命周期都会少不了上图这几个步骤,也就是Java代码首先会被编译成字节码文

EF6 Create Different DataContext on runtime(运行时改变连接字符串)

引言   在使用EF时,有时我们需要在程序运行过程中动态更改EF的连接字符串,但不幸的时EF是否对 ConfigurationManager.RefreshSection("xxx") 这行代码的影响不大,我没去深究,还请大侠指点.(本人猜测,EF内部实现没有订阅RefreshSection的事件去做相应的更换连接字符串的处理),如果确实想用该方法通过修改配置文件来实现动态更换连接字符串,那最保守的做法再加上个重启应用程序的方法.(确保EF能重新读到新的配置信息.)   这个时候就需要

运行时动态将字符串编译为C#可执行代码

private void button1_Click(object sender, EventArgs e) { CSharpCodeProvider CSharp = new CSharpCodeProvider(); String[] dll = { "System.dll", "System.Windows.Forms.dll" }; CompilerParameters 编译参数 = new CompilerParameters(dll); 编译参数.Gen

ART运行时垃圾收集(GC)过程分析

ART运行时与Dalvik虚拟机一样,都使用了Mark-Sweep算法进行垃圾回收,因此它们的垃圾回收流程在总体上是一致的.但是ART运行时对堆的划分更加细致,因而在此基础上实现了更多样的回收策略.不同的策略有不同的回收力度,力度越大的回收策略,每次回收的内存就越多,并且它们都有各自的使用情景.这样就可以使得每次执行GC时,可以最大限度地减少应用程序停顿.本文就详细分析ART运行时的垃圾收集过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! ART运行