方法区
1. 设置方法区大小与 OOM
- -XX:MetaspaceSize:设置元空间内存大小,比如-XX:MetaspaceSize=100m
- -XX:MaxMetaspaceSize:设置元空间最大内存,比如-XX:MaxMetaspaceSize=100m
2. 方法区内部结构:
- 类信息:对于类信息,JVM 必须在方法区中存储一下类型信息
- 类的完整有效名称(包名.类型)
- 类的直接父类的完整有效名
- 类的修饰符(public,abstract,final 等)
- 类实现的接口的有效列表
- 运行时常量池
- 静态变量
- 即时编译器编译后的代码缓存
3. 运行时常量池的理解:
- 运行时常量池是方法区的一部分
- 常量池表是 class 文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区中的运行时常量池中
- 在加载类和接口到虚拟机后就会创建对应的运行时常量池
- JVM 为每个已加载的类型都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的
- 运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用,此时不再是常量池中的符号地址了,这里替换为真实地址
- 运行时常量池类似于传统编程语言中的符号表,但它所包含的数据却比符号表要更加丰富一些
- 运行时常量池会抛出 OOM 异常
4. 方法区在 jdk6、jdk7、jdk8 中的演进细节:
- jdk6:有永久代,静态变量存放在永久代上
- jdk7:有永久代,但已经逐步“去永久代”,字符串常量池、静态变量移除,保存在堆中
- jdk8:无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆中