参考:

JVM的内存区域划分

Java GC的原理

通过图文给你讲明白java GC的实现原理

Java – 深入浅出GC自动回收机制

minor 英[ˈmaɪnə®] 美[ˈmaɪnɚ]
adj. 较小的,少数的,小…; 未成年的; [乐] 小调的,小音阶的; (两同姓男孩中) 年幼的;
n. 未成年人; 副修科目; 小公司; [逻辑学] 小前提;
vi. [主美国英语] 副修,选修,兼修;

major 英[ˈmeɪdʒə®] 美[ˈmedʒɚ]
adj. 主要的; 重要的; 大调的; 主修的(课程);
n. 主修科目; 大调; 陆军少校; 成年的;
vi. <美>主修,专攻; [美国英语][教育学]主修(in); 专攻;

运行时数据区

根据《Java虚拟机规范》的规定,运行时数据区通常包括这几个部分:程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。

java内存与GC垃圾回收

java内存与GC垃圾回收

GC分代与算法

GC :Garbage Collections 字面意思是垃圾回收器,释放垃圾占用的空间。

GC是对JVM中的内存进行标记和回收,Sun公司的JDK用的虚拟机都是HotSpot
对象化的实例是放在heap堆内存中的,这里讲的分代收集也是指对堆内存的回收。

JAVA GC采用了【分代思想】,
Java内存分配和回收的机制概括的说,就是:分代分配,分代回收。
将java堆分成【新生代,年老代,永久代】。
GC算法主要有【标记-清除,标记-压缩,复制算法】。

分代

java内存与GC垃圾回收

新生代(Young Generation): eden(8) + from(1) + to(1)

新生代被分成三个部分 eden区和2个survivor区(FromSpace和ToSpace,也有些人喜欢叫做Survivor1和Survivor2)。当创建对象,需要jvm分配内存时,会在新生代的eden区寻找合适的内存区域。如果当eden区内存不够时,会触发minor GC。eden区存活对象和from区的存活对象将会被复制到to区。当to区的对象年龄超过了晋升的年龄设置,对象将被提升到老年代。新生代GC用的是复制算法

“Young中的98%的对象都是朝生夕死,所以将内存分为一块较大的Eden和两块较小的Survivor1、Survivor2,JVM默认分配是8:1:1,每次调用Eden和其中的Survivor1(FromSpace),当发生回收的时候,将Eden和Survivor1(FromSpace)存活的对象复制到Survivor2(ToSpace),然后直接清理掉Eden和Survivor1的空间。”

年老代(Old Generation):

年老代里存放的都是存活时间较久的,经过多次Minor GC之后依然存活的对象,大小较大的对象,因此年老代使用标记整理算法。当年老代容量满的时候,会触发一次Major GC(full GC),回收年老代和年轻代中不再被使用的对象资源。年老代算法用的是标记-清除

永久代(Permanent Generation):

指内存的永久保存区域,主要存放Class和Meta(元数据)的信息。Class在被加载的时候被放入永久区域。它和和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。

GC

新生代的GC(Minor GC):

新生代通常存活时间较短基于【Copying算法】进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中,对应于新生代,就是在Eden和FromSpace或ToSpace之间copy。新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从Eden到Survivor,最后到老年代。

老年代的GC(Major GC/Full GC):

老年代与新生代不同,老年代对象存活的时间比较长、比较稳定,因此采用【标记(Mark)算法】来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并、要么标记出来便于下次进行分配,总之目的就是要减少内存碎片带来的效率损耗。

垃圾回收机制:

标记-清除回收法:

遍历对象图并且记录可到达的对象,以便删除不可到达的对象,一般使用单线程工作并且可能产生内存碎片

标记-压缩回收法:

前期与第一种方法相同,只是多了一步,将所有的存活对象压缩到内存的一端,这样内存碎片就可以合成一大块可再利用的内存区域,提高了内存利用率

复制回收法:

把现有内存空间分成两部分,gc运行时,它把可到达对象复制到另一半空间,再清空正在使用的空间的全部对象。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。

分代回收法:

把内存空间分为两个或者多个域,如年轻代和老年代,年轻代的特点是对象会很快被回收,因此在年轻代使用效率比较高的算法(复制)。当一个对象经过几次回收后依然存活,对象就会被放入称为老年的内存空间,老年代则采取标记-压缩算法

相关文章: