Java 常量池详解(二)class文件常量池 和 Java 常量池详解(三)class运行时常量池

article/2025/9/23 22:56:22

Java 常量池详解(一)字符串常量池

2.class文件常量池(class constant pool)

产生时机:当java文件被编译成class文件之后,就会生成class常量池,跟jvm 无关系

常量池主要存放两大类常量:字面量;符号引用

在这里插入图片描述

  • 字面量接近Java语言层面的常量概念,如文本字符串、声明为final的常量值等

(Integer、 Float 、Long、 Double、 String、 UTF-8)

  • 符号引用包含三类引用:
    1、 类和接口的全限定名 org.springframework…Bean
    举例:jvm/Hotspot/ConstantsTest
    在这里插入图片描述
 #7 = Class              #41            // jvm/Hotspot/ConstantsTest#41 = Utf8               jvm/Hotspot/ConstantsTest
  • 2、字段的名称和描述符
    举例: int b
    在这里插入图片描述
 #4 = Fieldref           #7.#37         // jvm/Hotspot/ConstantsTest.b:I#7 = Class              #41            // jvm/Hotspot/ConstantsTest#37 = NameAndType        #17:#18        // b:I#41 = Utf8               jvm/Hotspot/ConstantsTest#17 = Utf8               b#18 = Utf8               I
  • 3、方法的名称和描述符
    举例:int getB()
    在这里插入图片描述
 #9 = Methodref          #7.#42          // jvm/Hotspot/ConstantsTest.getB:()I#7 = Class              #41            // jvm/Hotspot/ConstantsTest#42 = NameAndType        #26:#27        // getB:()I #41 = Utf8               jvm/Hotspot/ConstantsTest#26 = Utf8               getB#27 = Utf8               ()I

Class 文件布局 如下(跟方法区布局息息相关的)

在这里插入图片描述

public class ConstantsTest {private static Integer a = 10;private int b;private String c = "cc";private static String d = "dd";public int getB() {return b;}public static int getA() {return a;}public static void main(String[] args) {ConstantsTest constantsTest = new ConstantsTest();constantsTest.getB();ConstantsTest.getA();}
}

//执行下面这个语句
javap -c -v -p ConstantsTest.class 得到

public class jvm.Hotspot.ConstantsTestminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref          #14.#34        // java/lang/Object."<init>":()V#2 = String             #35            // cc#3 = Fieldref           #7.#36         // jvm/Hotspot/ConstantsTest.c:Ljava/lang/String;#4 = Fieldref           #7.#37         // jvm/Hotspot/ConstantsTest.b:I#5 = Fieldref           #7.#38         // jvm/Hotspot/ConstantsTest.a:Ljava/lang/Integer;#6 = Methodref          #39.#40        // java/lang/Integer.intValue:()I#7 = Class              #41            // jvm/Hotspot/ConstantsTest#8 = Methodref          #7.#34         // jvm/Hotspot/ConstantsTest."<init>":()V#9 = Methodref          #7.#42         // jvm/Hotspot/ConstantsTest.getB:()I#10 = Methodref          #7.#43         // jvm/Hotspot/ConstantsTest.getA:()I#11 = Methodref          #39.#44        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;#12 = String             #45            // dd#13 = Fieldref           #7.#46         // jvm/Hotspot/ConstantsTest.d:Ljava/lang/String;#14 = Class              #47            // java/lang/Object#15 = Utf8               a#16 = Utf8               Ljava/lang/Integer;#17 = Utf8               b#18 = Utf8               I#19 = Utf8               c#20 = Utf8               Ljava/lang/String;#21 = Utf8               d#22 = Utf8               <init>#23 = Utf8               ()V#24 = Utf8               Code#25 = Utf8               LineNumberTable#26 = Utf8               getB#27 = Utf8               ()I#28 = Utf8               getA#29 = Utf8               main#30 = Utf8               ([Ljava/lang/String;)V#31 = Utf8               <clinit>#32 = Utf8               SourceFile#33 = Utf8               ConstantsTest.java#34 = NameAndType        #22:#23        // "<init>":()V#35 = Utf8               cc#36 = NameAndType        #19:#20        // c:Ljava/lang/String;#37 = NameAndType        #17:#18        // b:I#38 = NameAndType        #15:#16        // a:Ljava/lang/Integer;#39 = Class              #48            // java/lang/Integer#40 = NameAndType        #49:#27        // intValue:()I#41 = Utf8               jvm/Hotspot/ConstantsTest#42 = NameAndType        #26:#27        // getB:()I#43 = NameAndType        #28:#27        // getA:()I#44 = NameAndType        #50:#51        // valueOf:(I)Ljava/lang/Integer;#45 = Utf8               dd#46 = NameAndType        #21:#20        // d:Ljava/lang/String;#47 = Utf8               java/lang/Object#48 = Utf8               java/lang/Integer#49 = Utf8               intValue#50 = Utf8               valueOf#51 = Utf8               (I)Ljava/lang/Integer;
{private static java.lang.Integer a;descriptor: Ljava/lang/Integer;flags: ACC_PRIVATE, ACC_STATICprivate int b;descriptor: Iflags: ACC_PRIVATEprivate java.lang.String c;descriptor: Ljava/lang/String;flags: ACC_PRIVATEprivate static java.lang.String d;descriptor: Ljava/lang/String;flags: ACC_PRIVATE, ACC_STATICpublic jvm.Hotspot.ConstantsTest();descriptor: ()Vflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: ldc           #2                  // String cc7: putfield      #3                  // Field c:Ljava/lang/String;10: returnLineNumberTable:line 10: 0line 13: 4public int getB();descriptor: ()Iflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: getfield      #4                  // Field b:I4: ireturnLineNumberTable:line 17: 0public static int getA();descriptor: ()Iflags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=0, args_size=00: getstatic     #5                  // Field a:Ljava/lang/Integer;3: invokevirtual #6                  // Method java/lang/Integer.intValue:()I6: ireturnLineNumberTable:line 21: 0public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=2, args_size=10: new           #7                  // class jvm/Hotspot/ConstantsTest3: dup4: invokespecial #8                  // Method "<init>":()V7: astore_18: aload_19: invokevirtual #9                  // Method getB:()I12: pop13: invokestatic  #10                 // Method getA:()I16: pop17: returnLineNumberTable:line 25: 0line 26: 8line 27: 13line 28: 17static {};descriptor: ()Vflags: ACC_STATICCode:stack=1, locals=0, args_size=00: bipush        102: invokestatic  #11                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;5: putstatic     #5                  // Field a:Ljava/lang/Integer;8: ldc           #12                 // String dd10: putstatic     #13                 // Field d:Ljava/lang/String;13: returnLineNumberTable:line 11: 0line 14: 8
}

3.class运行时常量池

在这里插入图片描述

Class运行时常量池其实是当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中。 里面放的也是符号引用和字面量,跟我们的class文件常量池放的东西是一样的

可以把Class文件常量池看作静态常量池(里面是符号引用), 而运行时常量池是动态常量池(里面有直接引用),他俩是同一个东西,只是状态时机不同而已。

问题:Class 文件信息是否能跟方法区对应上来?在这里插入图片描述

发现是能跟够一一对应的上的。方法区其实就可以简单看成运行状态的Class文件的布局

在这里插入图片描述

1. 符号引用(脱离jvm 体系来讲,就单纯class文件的符号引用而已)

符号引用以一组符号来描述所引用的目标,在编译的时候一个每个java类都会被编译成一个class文件, 但在编译的时候虚拟机并不知道所引用类的地址,多以就用符号引用来代替 ,而在这个解析阶段就是为了把这个符号引用转化成为真正的地址的阶段

比如:class 文件里面有个方法调用getB()方法。 还没到准备阶段(虚拟机就会进入准备阶段。在这个阶段,虚拟机就会为这个类分配相应的内存空间,并设置默认初始值)。是不知道具体new 对象所在的地址的。class 文件里面只是符号引用,知道是用这个类的方法。

 public static void main(String[] args) {ConstantsTest constantsTest = new ConstantsTest();constantsTest.getB();
}
//对应的反编译 代码其实 是
9: invokevirtual #9                  // Method getB:()I但其实#9 是常量池里面的 // jvm/Hotspot/ConstantsTest.getB:()I

2.直接引用

直接引用和虚拟机的布局是相关的如果有了直接引用,那么直接引用的目标一定被加载到了内存中。(有具体引用地址的指针,被引用的类、方法或者变量已经被加载到内存中)

3.静态链接

当一个字节码文件被装载进 JVM 内部时,如果被调用的目标方法在编译期可知,且运行期保持不变时,这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接

比如:调用静态方法, 调用实例的私有构造器, 私有方法, 父类方法,被final修饰的方法(其实就是不能被子类重写的方法,能确定唯一性)

4.动态链接

如果被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期将调用的方法的符号转换为直接引用,由于这种引用转换过程具备动态性,因此也被称之为动态链接。

比如:(B b = new B2() ) 父类声明,子类实现的情况,方法被子类重写了。

案例分析

有一个父类B 和子类B2 ,子类B2实现了B的getA 方法

public class B {private int a = 2;public int getA() {return a;}public static void print() {System.out.println("aaa");}public final void b() {}private void c() {System.out.println("c");}
}//只能重写getA方法
public class B2 extends B {@Overridepublic int getA() {return 2;
}    

此时有个线程调用了声明为B ,但是实现为B2的方法

public static void main(String[] args) {B b2 = new B2();b2.getA();b2.b();
}

class文件编译结果如下:

0: new           #4                  // class jvm/Hotspot/B2
3: dup
4: invokespecial #5                  // Method jvm/Hotspot/B2."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #2                  // Method jvm/Hotspot/B.getA:()I
12: pop
13: aload_1
14: invokevirtual #6                  // Method jvm/Hotspot/B.b:()V
17: return

此时这个 b2.getA() 他是动态链接,他只有在运行期间才知道用了具体哪个类,因为他这个方法可以被重写了,他可以是B类的getA方法,也可以是B2的get方法。此时这个 b2.b() 他是静态链接,他在编译期就确定是B类的b方法,是可以直接引用的

问题 :动态链接跟什么有关系?

动态链接在栈帧里面,不会在停留在方法区里面,是跟线程有关系的
在这里插入图片描述

public class A {int a = 1;public int getA() {return a;}
}public class A2 extends A {@Overridepublic int getA() {return 10;}
}public class B {public int getB(A a) {return a.getA();}
}public class B2 extends B {@Overridepublic int getB(A a) {return a.getA()+1;}
}

线程调用

public static void main(String[] args) {B b2 = new B2();A a2 = new A2();b2.getB(a2);
}//java反编译之后得到
0: new           #2                  // class jvm/Hotspot/B2
3: dup
4: invokespecial #3                  // Method jvm/Hotspot/B2."<init>":()V
7: astore_1
8: new           #4                  // class jvm/Hotspot/A2
11: dup
12: invokespecial #5                  // Method jvm/Hotspot/A2."<init>":()V
15: astore_2
16: aload_1
17: aload_2
18: invokevirtual #6          // Method jvm/Hotspot/B.getB:(Ljvm/Hotspot/A;)I
21: pop
22: return

虽然我们初始化的是B2的类,但是符号引用是B,是根据声明量B来的
然后动态链接会帮助我们在用b2.getB方法的时候,帮我们指向B2 而不是一开始写的B。


http://chatgpt.dhexx.cn/article/WLYqUuWj.shtml

相关文章

java 查看类常量池_Java中常量以及常量池

1、举例说明 变量 常量 字面量 1 int a=10;2 float b=1.234f;3 String c="abc";4 final long d=10L; a,b,c为变量,d为常量 两者都是左值;10,1.234f,"abc",10L都是字面量; 2、常量池: 常量池专门用来用来存放常量的内存区域,常量池分为:静态常量池…

一文解析Java常量池、静态常量池、运行时常量池和字符串常量池的区别与联系

Java常量池关系图 Java常量池 Java常量池是Java编译器在编译Java源代码时&#xff0c;为了优化性能和节省空间所创建的一种常量缓存机制。它包含了所有的基本数据类型、字符串常量、符号引用等常量&#xff0c;这些常量都是在编译期被确定下来的&#xff0c;并被存储在.class文…

java常量池总结

java常量池 1.class常量池2.运行时常量池3.基本类型包装类常量池4.字符串常量池 1.class常量池 在JAVA中&#xff0c;Java类&#xff08;.java&#xff09;文件被编译后就会形成一份class文件&#xff1b;class文件中除了包含类的版本、字段、方法、接口等描述信息外&#xff…

java号码池_Java常量池详解

jvm虚拟内存分布图&#xff1a; 程序计数器&#xff1a;JVM执行程序的流水线。 本地方法栈&#xff1a;JVM调用操作系统方法所使用的栈。 虚拟机栈&#xff1a;JVM执行Java代码所使用的栈。 方法区&#xff1a;存放一些常量、静态变量、类信息等&#xff1b;可以理解为class文件…

java常量池在哪里_【Java基础】Java常量池在哪里? - 收获啦

1.java常量池的介绍 java中的常量池&#xff0c;通常指的是运行时常量池&#xff0c;它是方法区的一部分&#xff0c;一个jvm实例只有一个运行常量池&#xff0c;各线程间共享该运行常量池。 java常量池简介&#xff1a;java常量池中保存了一份在编译期间就已确定的数据。它里面…

java静态池_java 常量池静态变量详解

Java中的常量池&#xff0c;实际上分为两种形态&#xff1a;静态常量池和运行时常量池。 所谓静态常量池&#xff0c;即*.class文件中的常量池&#xff0c;class文件中的常量池不仅仅包含字符串(数字)字面量&#xff0c;还包含类、方法的信息&#xff0c;占用class文件绝大部分…

java常量池在哪里_Java常量池详细说明

java常量池技术 java中的常量池技术&#xff0c;是为了方便快捷地创建某些对象而出现的&#xff0c;当需要一个对象时&#xff0c;就可以从池中取一个出来(如果池中没有则创建一个)&#xff0c;则在需要重复创建相等变量时节省了很多时间。常量池其实也就是一个内存空间&#x…

java中常量池存的是什么_Java中常量池是什么?Java常量池的介绍

本篇文章给大家带来的内容是关于Java中常量池是什么?Java常量池的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 Java当中的常量池 在Java虚拟机jvm中,内存分布为:虚拟机堆,程序计数器,本地方法栈,虚拟机栈,方法区。 程序计数器是jvm执行程序的…

java long常量池_Java-常量池

Java-常量池 常量池是类文件中最复杂的数据结构。对于JVM字节码来说&#xff0c;如果操作数是很常用的数字&#xff0c;比如 0&#xff0c;这些操作数是内嵌到字节码中的。如果是字符串常量和较大的整数等&#xff0c;Class文件则会把这些操作数存储到常量池中&#xff0c;当使…

Java常量池原理以及垃圾回收

Java常量池 常量池&#xff1a;用于存放编译期间生成的各种字面量和符号引用 字面量&#xff1a;由字母数字等构成的字符串或数值常量&#xff0c;如int a 1中 1就是字面量 符号引用&#xff1a;编译原理中的概念&#xff1b;是相对直接引用来说的&#xff0c;主要包括三类常…

Java 常量池详解(一)字符串常量池

在Java的内存分配中&#xff0c;总共3种常量池&#xff1a; Java 常量池详解&#xff08;二&#xff09;class文件常量池 和 Java 常量池详解&#xff08;三&#xff09;class运行时常量池 1.字符串常量池(String Constant Pool&#xff09; 在JDK1.7之前运行时常量池逻辑包含…

Java常量池储存什么_JAVA常量池中存储的常量是什么

展开全部 我当初也存在这样一个疑问&#xff0c;下面我把e69da5e887aa3231313335323631343130323136353331333262356165当初所搜集的一些资料以及自己的理解贴出来给你看看(比较多&#xff0c;需要耐心点看&#xff0c;呵呵)&#xff1a; 理解Java常量池 JVM运行时数据区的内存…

深度剖析Java常量池

Class常量池 class常量池可以理解为是Class文件中的资源仓库。Class文件中除了包含类的版本、字段、方法、接口等描述信息外&#xff0c;还有一项信息就是常量池(constant pool table)&#xff0c;用于存放编译期生成的各种字面量和符号引用。 一个Class文件的16进制大体结构如…

Java常量池

Java常量池 一.相关知识 1.何为常量 第一种常量&#xff1a;是一个值&#xff0c;我们将这个值本身称为常量。比如&#xff1a; 整型常量&#xff1a;1024 实型常量&#xff1a;1.024 字符常量&#xff1a;g c w 字符串常量&#xff1a;"gcw" 逻辑常量&#xff1a;t…

Java 常量池

常量池分为 Class 常量池常量池、运行时常量池、字符串常量池。 1、 Class 常量池常量池&#xff08;静态常量池&#xff09; Java 文件被编译成 Class 文件&#xff0c;Class 文件中除了包含类的版本、字段、方法、接口等描述信息外&#xff0c;还有一项就是 Class 常量池&am…

JAVA常量池,一篇文章就足够入门了。(含图解)

前言 一直在《深入理解JVM》对常量池只有一个浅薄的了解&#xff0c;之前也遇到过这种题目&#xff0c;今天还是要挑出来进行一次全方位的了解。 常量池分类 常量池大体可以分为&#xff1a;静态常量池&#xff0c;运行时常量池。 静态常量池 存在于class文件中&#xff0c…

基于Elman神经网络的刀具剩余使用寿命预测(初学者+matlab代码实现)

1.Elman介绍 Elman神经网络是 J. L. Elman于1990年首先针对语音处理问题而提出来的&#xff0c;是一种典型的局部回归网络( global feed forward local recurrent)。Elman网络可以看作是一个具有局部记忆单元和局部反馈连接的递归神经网络 它的主要结构是前馈连接, 包括输入层、…

通过模拟退火改进的Elman神经网络(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 神经网络是一个庞大的体系和概念&#xff0c;根据处理信息的不同方式来区分不同的network。比如根据处理信息结果的传递方向&am…

基于遗传算法优化的Elman神经网络数据预测-附代码

基于遗传算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于遗传算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于遗传优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针…

【预测模型-ELAMN预测】基于海鸥算法优化ELMAN神经网络实现数据回归预测

1 简介 风能,作为一种重要,有潜力,无污染,可再生、可持续的能源,已经成为全球发电最为迅速的能源之一,越来越受到世界各国的青睐。近年来,为缓解能源短缺问题,改善环境,实现经济乃至人类的可持续发展,世界各国纷纷大力发展风能资源。然而,在实际操作中,风能固有的波动性和间歇…