文章目录
1.栈、堆、方法区的交互关系
2.方法区的理解
方法区在哪里:
方法区的基本理解:
HotSpot中方法区的演进:
3.设置方法区大小与OOM
设置方法区内存大小:
如何解决这些OOM:
4.方法区的内部结构
4.1 方法区存储什么
4.2 方法区的内部结构
-
类型信息:
-
域信息:
-
方法信息:
-
no-final的类变量:
public static int count;
descriptor: I
flags: ACC_PUBLIC, ACC_STATIC
public static final int number;
descriptor: I
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: int 2
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_1
1: putstatic #5 // Field count:I
4: return
LineNumberTable:
line 17: 0
4.2 常量池VS运行时常量池
常量池VS运行时常量池:
- 方法区,内部包含了运行时常量池。
- 字节码文件,内部包含了常量池。
- 要弄清楚方法区,需要理解清楚ClassFile,因为加载类的信息都在方法区。
- 要弄清楚方法区的运行时常量池,需要理解清楚ClassFile中的常量池。
为什么需要常量池:
常量池中有什么:
小结:
常量池,可以看做是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型。
运行时常量池:
- 运行时常量池(Runtime Constant Pool)是方法区的一部分。
- 常量池表(Constant Pool Table)是Class文件的一部分,用于存放编译器生成的各种字面量与符合引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
- 运行时常量池,在加载类和接口到虚拟机后,就会创建对应的运行时常量池。
- JVM为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的。
- 运行时常量池中包含多种不同的常量,包括编译器就已经明确的数值字面量,也包括到运行时解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了,这里转换为真实地址。
》运行时常量池,相对于Class文件常量池的另一重要特征是:具备动态性。- 运行时常量池类似于传统编程语言的符号表(symbol table),但是它所包含的数据却比符号表要更加丰富一些。
- 当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则JVM会抛出OutOfMemoryError异常。
5.图示举例方法区的使用
6.方法区的演进细节
永久代为什么要用元空间替代:
StringTble为什么要调整位置:
静态变量存在哪里?
7.方法区的垃圾回收
方法区的垃圾回收主要回收两部分内容:常量池中废弃的常量和不再使用的类型。
常量池回收:
类型回收: