- 类型信息
对于每个加载的类型(class、interface、enum、annotation)JVM 必须在方法区中存储一下类型信息。
1 这个类型的完整有效名称
2 这个类型直接父类的完整有效名
3 这个类型的修饰符
4 这个类型直接接口的一个有序列表
- 域信息
1 JVM 必须在方法区中保存类型的所有域相关信息以及域的声明顺序
2 域的相关信息包括:域名称、域类型、域修饰符(public、private...)
- 方法(Method)信息
1 方法名称
2 方法返回类型
3 方法参数的数量和类型
4 方法的修饰符
5 方法的字节码
6 异常表(除 abstract 与 native 方法)
每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引
交互关系图
运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分,理解运行时常量池的话,我们先来说说字节码文件(Class 文件)中的常量池(常量池表)
常量池
一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述信息外,还包含一项信息那就是常量池表(Constant Pool Table),包含各种字面量和对类型、域和方法的符号引用。
为什么需要常量池?
一个 Java 源文件中的类、接口,编译后产生一个字节码文件。而 Java 中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。在动态链接的时候用到的就是运行时常量池。
运行时常量池
- 在加载类和结构到虚拟机后,就会创建对应的运行时常量池
- 常量池表(Constant Pool Table)是 Class 文件的一部分,用于存储编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中
- JVM 为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的
- 运行时常量池中包含各种不同的常量,包括编译器就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或字段引用。此时不再是常量池中的符号地址了,这里换为真实地址
- 运行时常量池,相对于 Class 文件常量池的另一个重要特征是:**动态性**,Java 语言并不要求常量一定只有编译期间才能产生,运行期间也可以将新的常量放入池中,String 类的 `intern()` 方法就是这样的
- 当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则 JVM 会抛出 OutOfMemoryError 异常。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!