Java对象内存布局

一个Java对象在内存中包括3个部分:对象头、实例数据和对齐填充

java 对象的内存 如何分配 java对象的内存布局_java

一块是非堆区,一块是堆区。
堆区分为两大块,一个是Old区,一个是Young区。
Young区分为两大块,一个是Survivor区(S0+S1),一块是Eden区。 Eden:S0:S1=8:1:1
S0和S1一样大,也可以叫From和To。

java 对象的内存 如何分配 java对象的内存布局_老年代_02

根据之前对于Heap的介绍可以知道,一般对象和数组的创建会在堆中分配内存空间,关键是堆中有这么多区
域,那一个对象的创建到底在哪个区域呢?

对象创建所在区域

一般情况下,新创建的对象都会被分配到Eden区,一些特殊的大的对象会直接分配到Old区。

对象分配 是年轻还是老
年轻;一次垃圾回收,岁数增加1,默认15
老年;当对象大小特别大的时候, 年龄特别大的时候

为什么young会出现 eden和s0,s1?

因为分配对象,垃圾回收之后,对象需要连续的内存,但是不够了,不连续,所以对象分配失败,所以就出现了这三个区域。

为什么需要两个Survivor区?

最大的好处就是解决了碎片化。也就是说为什么一个Survivor区不行?第一部分中,我们知道了必须设置Survivor区。假设
现在只有一个Survivor区,我们来模拟一下流程:
刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。这样继续循环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的
存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。
永远有一个Survivor space是空的,另一个非空的Survivor space无碎片

新生代中Eden:S1:S2为什么是8:1:1?

自己理解:是因为s区必须要比例相等,为了相互转化,e区为新生代,大多都是朝生夕死,产生快
新生代中的可用内存:复制算法用来担保的内存为9:1
可用内存中Eden:S1区为8:1
即新生代中Eden:S1:S2 = 8:1:1

**担保机制 **

当s0/s1不够用 的时候,跟老年代借点空间 ,担保
Minor GC、Major GC、Full GC
Minor GC:新生代 ,major gc通常会伴随着minor gc,也就是会触发full gc
Major GC:老年代
Full GC:新生代+老年代
比如有对象A,B,C等创建在Eden区,但是Eden区的内存空间肯定有限,比如有100M,假如已经使用了
100M或者达到一个设定的临界值,这时候就需要对Eden内存空间进行清理,即垃圾收集(Garbage Collect),
这样的GC我们称之为Minor GC,Minor GC指得是Young区的GC。
经过GC之后,有些对象就会被清理掉,有些对象可能还存活着,对于存活着的对象需要将其复制到Survivor区,然后再清空Eden区中的这些对象。

Survivor区详解

由图解可以看出,Survivor区分为两块S0和S1,也可以叫做From和To。
在同一个时间点上,S0和S1只能有一个区有数据,另外一个是空的

Old区详解

从上面的分析可以看出,一般Old区都是年龄比较大的对象,或者相对超过了某个阈值的对象。
在Old区也会有GC的操作,Old区的GC我们称作为Major GC,每次GC之后还能存活的对象年龄也会+1,如果年龄超过了某个阈值,就会被回收。

java 对象的内存 如何分配 java对象的内存布局_java_03