文章目录
- 1.堆(heap)
- 1.1 堆的概述
- 1.2 堆的内部结构
- 1.3 堆分代垃圾回收流程的简单理解
- 2.方法区( Method Area)
- 2.1 `HotSpot`方法区的演进
- 2.2方法区的内部结构
- 2.3.1 常量池和运行时常量池概念区别
1.堆(heap)
1.1 堆的概述
- 一个JVM实例
只存在一个堆内存
,堆也是Java内存管理的核心区域。. Java堆区在JVM启动的时候即被创建,其空间大小也就确定了。是JVM
管理的最大
一块内存空间。 - 堆内存的大小是可以调节的。
《Java虚拟机规范》规定,堆可以处于物理上不连续
的内存空间中,但在逻辑上它应该被视为连续
的。 - 所有的线程共享Java堆,在这里还可以划分线程
私有的缓冲区
( Thread
Local Allocation Buffer,TLAB
)。
1.2 堆的内部结构
引用自https://blog.csdn.net/lovely_girl1126/article/details/106806879
堆的内部结构主要包括
1.新生区:伊甸园区,幸存者0区,幸存者1区
2.老年区:一般是最大的区
3:元空间(jdk1.7及以前为永久代,元空间和永久代尽管上在逻辑上是堆的一部分,但实际位置并不在堆内)
1.3 堆分代垃圾回收流程的简单理解
1.新生对象在伊甸园区内存足够的情况下一般会分配到伊甸园区。
2.新生区在会进行Minor GC
。
3.minor Gc一般在伊甸园内存不够时进行,当该区进行gc的时候,存活对象会放入幸存者0区,于此同时会对另一个幸存者区年龄增加,存活判断,判断是否进入养老区,或者被回收,于此同时将该幸存者区对象移动到另一个幸存者区中,一个幸存者区置空,置空的区叫做幸存者0区,不置空的区为幸存者1区。
4.幸存者区的回收不单独进行
,一般伴随伊甸园区的回收进行。
5.一般将年龄阈值
或者过半对象数量年龄
作为进入养老区的条件。
6.养老区的gc叫major Gc
,不过,只有CMS GC
会单独回收养老区,Full Gc
一般会包括所有的堆空间和方法区
7.对象如果过大,某区不能满足,则直接放置到能放置的下面的区。
2.方法区( Method Area)
2.1 HotSpot
方法区的演进
1.在jdk7及以前,习惯上把方法区,称为永久代。jdk8开始,使用元空间取代了永久代
2.本质上,方法区和永久代并不等价。仅是对hotspot而言的。《Java虚拟机规范》对如何实现方法区,不做统一要求。例如:BEA JRockit/ IBMJ9中不存在永久代的概念。
3.永久代相对来说容易oom。(超过永久代空间的上限)
2.2方法区的内部结构
《深入理解Java 虚拟机》书中对方法区(Method Area)存储内容描述如下
它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等
。
2.3.1 常量池和运行时常量池概念区别
1.常量池在编译时确定,在字节码文件中已经体现
2.运行时常量池是方法区的一部分
- 运行时常量池( Runtime Constant Poo1)是方法区的一部分。
- 常量池表(Constant Pool Table)是class文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。运行时常量池,在加载类和接口到虚拟机后,就会创建对应的运行时常量池。
- JVM为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的。
- 运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了,这里换为真实地址。
- 运行时常量池,相对于class文件常量池的另一重要特征是:具备动态性。
运行时常量池类似于传统编程语言中的符号表(symbol table),但是它所包含的数据却比符号表要更加丰富一些。 - 当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则JVM会抛outofMemoryError异常。