Java虚拟机所管理的内存将会包括《方法区、堆、虚拟机栈、本地方法栈、程序计数器》等运行时数据区域。
1.方法区
方法区存放类的信息、常量和静态变量,即类被编译后的class文件。更加具体地说,存放着:类的版本,字段,方法,接口和常量池。常量池里存储着字面量和符号引用。
符号引用包括:1.类的全限定名,2.字段名和属性,3.方法名和属性。
- 方法区存class文件信息、class文件常量池和运行时常量池
- 持久化(元空间)和数据区
方法区大小可以通过-XX:PermSize及-XX:MaxPermSize来进行调节。当方法区无法满足内存分配需求时,会抛出java.lang.OutOfMemoryError: PermGenspace的异常。
1.1 class文件信息
class文件信息包括:魔数,版本号,常量池,常量池计数器,类,父类索引和接口数组,字段,方法等信息,其中类里面又包括字段和方法的信息。
类型 | 名称 | 数量 |
---|---|---|
u4 | magic魔数 | 1 |
u2 | minor_version副版本号 | 1 |
u2 | major_version主版本号 | 1 |
u2 | constant_pool_count常量池计数器 | 1 |
cp_info | constant_pool常量池数据 | constant_pool_count - 1 |
u2 | access_flags访问标志 | 1 |
u2 | this_class类索引 | 1 |
u2 | super_class父类索引 | 1 |
u2 | interfaces_count接口计数器 | 1 |
u2 | interfaces接口数据 | interfaces_count |
u2 | fields_count 字段计数器 | 1 |
field_info | fields字段数据 | fields_count |
u2 | methods_count | 方法计算器1 |
method_info | methods 方法 | methods_count |
u2 | attribute_count | 1 |
attribute_info | attributes | attributes_count |
1.2 常量池
1.2.1 class文件常量池-静态常量池
静态常量池存储的是当class文件被java虚拟机加载进来后存放在方法区的一些字面量和符号引用,字面量包括字符串,基本类型的常量,符号引用其实引用的就是常量池里面的字符串,但符号引用不是直接存储字符串,而是存储字符串在常量池里的索引。
1.3 运行时常量池-动态常量池
动态常量池是当class文件被加载完成后,java虚拟机会将静态常量池里的内容转移到动态常量池里,在静态常量池的符号引用有一部分是会被转变为直接引用的,比如说类的静态方法或私有方法,实例构造方法,父类方法,这是因为这些方法不能被重写其他版本,所以能在加载的时候就可以将符号引用转变为直接引用,而其他的一些方法是在这个方法被第一次调用的时候才会将符号引用转变为直接引用的
1.4 持久代(元空间)
持久代,这个区域会存储包括类定义、结构、字段、方法(数据及代码)以及常量在内的类相关数据。JDK8开始,持久代已经被彻底删除了,取代它的是另一个内存区域也被称为元空间。
1.5 数据区
- 1.类加载器引用(classLoader)
- 2.运行时常量池
所有常量、字段引用、方法引用、属性 - 3.字段数据
每个方法的名字、类型(如类的全路径名、类型或接口) 、修饰符(如public、abstract、final)、属性 - 4.方法数据
每个方法的名字、返回类型、参数类型(按顺序)、修饰符、属性 - 5.方法代码
每个方法的字节码、操作数栈大小、局部变量大小、局部变量表、异常表和每个异常处理的开始位置、结 束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引