上面主要分析了方法区以及方法区中的静态区域,下面将主要分析下常量池。常量池主要涉及到常量池里的内容和常量池解析这两块,这篇文章主要分析下常量池概念,大致说下常量池解析,以加深对常量池的理解。
在方法区中,每个类型都对应一个常量池,常量池中存储了诸如文字字符串、final变量值、类名和方法名常量。JVM把常量池组织为入口列表的形式,可通过索引来访问常量池中的各个入口,每个常量池入口的第一个字节都是个标志,用这个标志来表示该入口中存储的常量类型,如CONSTANT_Long表示里面存储的是long类型字面值,CONSTANT_Class_info表示里面存的是某个Class的类型信息(存的可能是个普通的字符串,然后经过常量池解析,则变成指向某个类的引用)。
除了字面常量值以外,常量池还可以容纳其它几种符号引用:类和接口的全限定名、字段名称和描述符、方法名称和描述符。
类和接口的全限定名指的是当前类的全限定名。
字段名称指的是类或接口的实例变量或类变量,字段的描述符是一个指示字段的类型的字符串。如在一个类中有以下形式的声明:A a = null, 则a为字段名,A为字段描述符。
方法的描述符也是个字符串,该字符串指示了方法的返回值和参数的数量、顺序和类型。
在运行时,JVM从常量池中获得符号引用,然后在运行时解析成引用项的实际地址,最后通过常量池中的全限定名、方法和字段描述符,把当前类或接口中的代码与其它类或接口中的代码联系起来。
讲到常量池,就涉及到常量池解析,常量池解析是非常复杂的,它分多种情况处理。这里,就列举个简单的例子,大家看看,大概了解下常量池解析的大概过程。
测试例子程序:
/**
* Dog的超类是个接口,而不是类
*/
public class Animal {
String id = "Animal"; //当类变量是static final
public void print() {
System.out.println("this is animal"+id);
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Animal a = new Dog();
}
}
下面将描述下JVM是如何处理Test类中的main()方法的第一条指令:
要运行Test程序,JVM找到对应的Test.class文件,并读入到方法区中。通过保存在方法区中的字节码,JVM开始执行main方法,执行时,它会一直指向当前类(Test类)的常量池。 main的第一条指令告诉JVM要为常量池中的第一项类分配足够的内存,于是JVM使用Test常量池指针找到第一项,发现它是一个对Animal类的符号引用(也就是对字符串“Animal”的引用),于是JVM检查方法区,看Animal类是否被装载了。
如JVM发现还没装载过Animal类时,它开始查找并装载Animal.class文件。
最后,JVM将一个直接指向方法区Animal类数据的指针来代替常量池第一项(也就是那个字符串”Animal”),以后,则可以通过该指针来快速访问Animal类了,这个就称为常量池解析。
说了那么多,常量池解析在这里作的处理就是把常量池中的字符串"Animal"解析成一个对类Animal的引用。
分享到:
相关推荐
常量池是类文件的核心组成部分,它存储了大量的资源,如字面量(Literal,包括基本类型和字符串)和符号引用(Symbolic Reference,如类和接口的全限定名、字段和方法的名称与描述符)。常量池的计数从1开始,方便...
解析阶段将类文件常量池中的符号引用替换为直接引用,使JVM可以直接访问内存中的目标。 3. 初始化(Initialization) 最后是初始化阶段,这是类加载的最后一步。在这个阶段,执行类初始化块(方法),初始化静态...
本节将详细介绍JVM的基本概念及其核心技术——HotSpot。 **HotSpot VM** 是Oracle公司提供的一个高性能Java虚拟机实现,它具有以下特点: - **主要实现语言**:C++ - **执行模式**:采用了解释器和编译器混合的工作...
方法区用于存储每个类的信息(包括类的方法和字段)、静态变量、常量池等数据。它在逻辑上属于堆的一部分,但为了方便管理,通常会单独分配一块内存。 #### 栈内存(Stack) 每个线程都有一个私有的栈空间,用于存储...
2. **常量池**:常量池是Class文件的重要组成部分,它包含两类常量:字面量和符号引用。字面量涵盖文本字符串、final常量等,而符号引用涉及类和接口的全限定名、字段和方法的名称及描述符。常量池的容量计数是从1...
《深入理解JVM工具——开启Java世界探索之旅》 在Java开发领域,JVM(Java Virtual Machine)扮演着至关重要的角色。它不仅是Java程序运行的基础,更是优化代码、解决性能问题的关键所在。为了更好地理解和利用JVM...
此外,JVM还有一块特殊的内存区域——方法区,用于存储类的信息,如类的静态变量和常量池等。理解这些内存区域的划分和工作方式,对于优化内存使用和避免内存泄漏至关重要。 三、类加载机制 JVM的类加载机制包括...
【JVM 分享】——深入理解Java程序的生命周期与执行机制 Java程序的生命周期始于源码,经过编译、加载和执行,最终在Java虚拟机(JVM)上运行。这个过程涉及到了编译器、类文件、虚拟机以及相关的优化技术。下面将...
- 常量池:String对象在创建时会尝试在字符串常量池中查找是否存在相同的字符串,如果存在,就直接返回其引用,否则会在堆中创建新的对象并将其放入常量池。 2. 字符串创建: - 直接赋值创建:如`String str = ...
- **方法区(Method Area)**:也称为永久代,用于存储类的信息、静态变量、常量池等内容。 #### JVM指令集体系结构 JVM指令集体系结构主要包括: - **指令集与CPU架构**:JVM指令集是一组定义好的操作码,用于...
- 每个`.class`文件包含了类的所有信息,包括但不限于类的结构、常量池、字段、方法等。 - 当JVM加载`.jar`文件时,会逐个加载其中的`.class`文件。 2. **DVM执行文件格式**: - Android平台上的Java程序也会先...
- **字符串池**:理解字符串常量池的作用,避免不必要的复制。 9. **JIT编译器** - **即时编译**:HotSpot JVM的C1和C2编译器将热点代码编译为原生机器码,提升执行效率。 - **编译触发条件**:如方法调用次数、...
方法区,有时被称为永久代(PermGen),主要用来存储类的信息、静态变量、常量池等内容。虽然理论上永久代不需要频繁进行垃圾回收,但在实践中仍然有可能发生内存溢出。例如,当加载了大量的类并且没有足够的内存来...
《JVM性能调优——JVM内存整理及GC回收》是针对Java开发人员的重要主题,尤其是在大型企业级应用中,确保JVM(Java虚拟机)的高效运行是至关重要的。本资料深入探讨了如何通过调整JVM内存设置和优化垃圾回收机制来...
《深入解析JVM字节码调用图生成器——基于jvm-callgraph开源项目》 在Java虚拟机(JVM)的世界里,理解和优化代码执行性能是至关重要的。为了达到这一目的,开发者需要深入理解程序的运行时行为,其中就包括了类与...
在深入探讨`struct example`的上下文中,我们首先聚焦于字节码——一种由Java虚拟机(JVM)理解的二进制类格式。这种格式由JVM规范定义,是Java源代码编译后的产物。尽管大多数情况下,这些类是由编译器从Java源代码...
- **字符串常量池**:对于字符串字面量,Java提供了一个特殊的优化机制——字符串常量池。字符串字面量在创建时会自动进行去重操作,从而节省内存空间。例如: ```java String str1 = "abc"; String str2 = "abc...
这些区域分别存储不同的数据,例如方法执行上下文、对象实例和常量池等。 3. **垃圾回收**:Java的自动内存管理主要依赖于垃圾回收(Garbage Collection, GC)。GC负责识别并清理不再使用的对象,以释放内存。常见...
通过这种方式,我们可以观察到字节码文件的结构,它包含了常量池、方法、属性等信息。 字节码文件中包含的信息不仅仅是源代码的简单映射,还包括了编译器生成的许多附加信息,用于在运行时支持类的加载、链接和执行...
- **解析(Resolve)**:将常量池内的符号引用替换为直接引用的过程。 - **初始化(Initialization)**:执行类构造器`()`方法,对类变量进行初始化。 #### 二、类加载器概述 **1. 定义** 类加载器是Java中用于加载...