-
运行时数据区域划分
JDK 1.8之前分为:线程共享(Heap堆区、Method Area方法区)、线程私有(虚拟机栈、本地方法栈、程序计数器)
JDK 1.8之后分为:线程共享(Heap堆区、Meta space元空间)、线程私有(虚拟机栈、本地方法栈、程序计数器)
-
堆(Heap)
是被线程共享的一块内存区域,
创建对象和数组都保存在Java堆内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域
。由于JVM采用
分代收集算法
,因此Java堆从GC角度还可以细分为:
新生代
(Eden区、From区、To区)和
老年代
新生代:
用来存放新生的对象。一般占用堆得1/3空间。由于频繁的创建对象,所以新生代会频繁触发MinorGC进行垃圾回收。新生代又分为Eden、From、To三个区
老年代:
主要存放应用程序中生命周期较长的内存对象。一般占用堆得2/3空间。老年代的对象较为稳定,所以MajorGC不会频繁执行
-
创建对象的内存分配
创建一个新对象,在堆中的分配内存。
大部分情况下,对象会在
Eden
区生成,当
Eden
区装填满的时候,会触发
Young Garbage Collection
,即
YGC
垃圾回收的时候,在
Eden
区实现清除策略,没有被引用的对象则直接回收。
依然存活的对象会被移送到
Survivor
区。
Survivor
区分为
From
和
To
两块内存区域。每次
YGC
的时候,它们将存活的对象复制到未使用的
Survivor
空间(
From或To
),然后将当前正在使用的空间完全清除,交换两块空间的使用状态。每次交换时,对象的年龄会加
+1
。
如果
YGC
要移送的对象大于
Survivor
区容量的上限,则直接移交给老年代。一个对象也不可能永远呆在新生代,在
JVM
中 一个对象从新生代晋升到老年代的阈值默认值是
15
,可以在
Survivor
区交换 14 次之后,晋升至老年代。