JVM虚拟机 - 内存
在JVM虚拟机中,内存部分大致可以分为以下几类:
- Heap:堆
- NonHeap:非堆
- CodeCache:缓存编辑后的机器码的内存区域
- CompressedClassSpace:类压缩空间
- MetaSpace:元空间(其实就是永久代,1.7之前叫永久代,1.8之后叫元空间)
- HeapedEnSpace:Eden区
- HeapOldGen:老年代
- HeapSurvivorSpace:S0和S1区
- Direct:直接内存
贴上示意图:
这张图其实画的有些不对,在Heap区,Old和Young的比例应该是2:1,然后Eden和S0、S1的比例应该是8:1:1。
接下来主要来讨论下新生代,老年代和元空间(永久代)。
1. 新生代
新生代有Eden、From、To区域(From、To即S0、S1区域)。
Eden主要用于存放新创建的对象,它会在第一次GC发生时,将对其内部的存活的对象放入到From或者To区域。
From和To区域都是Survivor区域,主要用于GC时,在对象复制时提供作用(复制算法),以及承担新生代和老年代之间的缓冲作用。
也就是说,对于整个新生代而言,会发生频繁的GC操作(Young GC)。
2. 老年代
有以下几种情况,可以使对象进入到老年代中:
-
大对象:指一个占用大量连续存储空间的对象
-
生命周期较长的对象
新生代中的每个对象都有一个年龄计数器,当新生代发生一次MinorGC后,存活下来的对象的年龄就加一,当年龄超过一定值时,就将超过该值的所有对象转移到老年代中去。
-
相同年龄的对象内存超过Survior内存一半的对象
如果当前新生代的Survior中,年龄相同的对象的内存空间总和超过了Survior内存空间的一半,那么所有年龄相同的对象和超过该年龄的对象都被转移到老年代中去。无需等到对象的年龄超过MaxTenuringThreshold才被转移到老年代中去。
Full GC 是发生在老年代的垃圾收集动作,所采用的是标记-清除算法。老年代如果频繁GC,那肯定是存在问题,需要去排查。
3. 元空间
JDK1.8和1.7最大的区别就是:元空间取代了永久代(在1.7的时候,常量池从永久代移至了堆空间中)。
元空间本质和永久代类似,都是对方法区的实现,两者的区别在于:元空间并不在虚拟机中,而是使用本地内存。所以此时的JVM运行时内存区域应该是这样的(摘自别人的图):