总结篇--JVM(java虚拟机) 垃圾回收

2022-07-27,,,,

JVM垃圾回收

  • 垃圾回收就是回收那些不再使用的对象,即释放它们占用的内存。垃圾收集器跟踪所有正在使用的对象,并把其余部分当做垃圾。

    
一、JVM垃圾回收中的基本概念


概念 解释 说明
Minor  GC 小型GC 新生代GC,即发生在新生代的垃圾回收动作
Major  GC 大型GC 老年代GC,指发生在老年代的GC。CMS收集器中,当老年代满时会触发 Major GC。除了CMS收集器,其他都存在都不存在只针对年老代的收集
Full  GC 完全GC 对整个堆(新生代、年老代)和方法区进行垃圾收集

 

二、常见堆分类介绍


  • 研究发现,程序中的大多数可回收的内存可归为两类:

        (1)大部分对象很快就不再使用。
        (2)还有一部分对象不会立即无用,但也不会持续(太)长时间。

基于这一假设,VM中的内存被分为年轻代(Young Generation)年老代(Old Generation)。年老代有时候也称为年老区(Tenured)。
拆分成这样两个可清理的单独区域,允许采用不同的算法来大幅提高GC的性能。但这种方法也是有问题的,比如在不同分代中的对象可能会互相引用,在收集某一个分代时就会成为“事实上的”GC root。

 

三、堆内存池中的内存池划分。(注:不同的GC算法在实现细节上可能会有所不同)


(1)Eden(伊甸园、新生代,在年轻代中(Young Generation)):Eden是内存中的一个区域,用来分配新创建的对象。

        通常我们会有多个线程创建多个对象,所以Eden区被划分为多个线程本地分配缓冲区(TLAB)。
        通过这种缓冲区划分,大部分对象直接由JVM在对应线程的TLAB中分配,避免与其他线程的同步操作。

        如果TLAB中没有足够的内存空间,就会在共享Eden区(Shared Eden space)之中分配。如果共享Eden区也没有足够的空间,就会触发一次年轻代GC来释放空间。
        如果GC之后Eden区依然没有足够的空闲内存区域,则对象就会被分配到老年代空间(Old Generation)。

 

(2)Survivor Spaces(存活区,在年轻代中(Young Generation)):年轻代中所有存活对象都会被复制到“to”存活区,"to"区有对象,“from”区没有对象。
        任意时刻总有一个存活区是空的,存活的对象会在两个存活区之间复制,复制到另一个存活区之后,原本的存活区就会被清空。直到某些对象的存活时间达到一定的阈值,就会迁移到年老代。

(3)Old Generation(老年代,也称为Tenured):年老代中的对象大部分都是存活的,年老代GC发生的频率比年轻代小很多,采用移动对象的方式来实现最小化内存碎片。

(4)PermGen(永久代):在Java 8之前有一个特殊的空间,被称为永生代。这是存储元数据(metadata)的地方,比如class信息。

        实际上这块区域给java开发者造成了很多麻烦,因为很难去计算这块区域到底占用了多少内存空间。预测失败的结果就是导致产生永生代内存溢出。

(5)元数据区(Metaspace):既然计算元数据区所需的空间那么复杂,java8直接删除了永生代,改用Metaspace。此后,java中很多杂七杂八的东西都放置到普通的堆内存中。

        元数据区位于本地内存(native memory),不再影响到普通的java对象。
        默认情况下,Metaspace的大小只受限于java进程中可用的本地内存。
        这样程序就不再因为多加载了几个类/JAR包就导致永生代内存溢出。
        但如果Metaspace失控,则可能会导致很严重的内存交换(swapping),导致本地内存分配失败,可通过限制Metaspace大小的方式处理。

本文地址:https://blog.csdn.net/github_37130188/article/details/110262674

《总结篇--JVM(java虚拟机) 垃圾回收.doc》

下载本文的Word格式文档,以方便收藏与打印。