JAVA GC简介

什么是“GC”

    垃圾回收机制。

为什么要用“GC”

    众所周知,JAVA 这语言,与C语言不同,Java内存(堆内存)的分配与回收由JVM垃圾收集器自动完成,比如 C语言自己定义的变量,不用时需要 自己回收这个变量 。JAVA 这就是自动完成了,自动检测,无用的垃圾,回收,从而释放内存。一个人工,一个自动化。

先看一下JVM内存结构

面试题:“你能不能谈谈, GC”(深入理解)

  • 栈:存放局部变量

  • 堆:存放所有new出来的东西

  • 方法区:被虚拟机加载的类信息、常量、静态常量等。

  • 程序计数器(和系统相关)

  • 本地方法栈

堆内存就是GC管理的主要区域(知识点,重点)

    然后JVM又把堆内存分三代,新生代,老年代,持久代。

面试题:“你能不能谈谈, GC”(深入理解)

新生代:分为eden ,From Survivor ,TO Survivor

1、绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快。(每次新生代的垃圾回收(又称Minor GC)采用copy算法,之后再讲)

2、最初一次,当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区From (此时,TO 是空白的,两个Survivor总有一个是空白的);

3、下次Eden区满了,再执行一次Minor GC,将消亡的对象清理掉,将存活的对象复制到TO 中,然后清空Eden区同时也 将From 中消亡的对象清理掉,将存活的对象也复制到TO 区,然后清空From区;之后,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

4、如果没有填满,当两个存活区切换了几次(每进行一次MinorGC,都会在存活的对象做一个标记,加1,当标记的值大于15,HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,进入老年代)之后,仍然存活的对象(其实只有一小部分,比如,我们自己定义的对象),将被复制到老年代。

老年代

    在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代,该区域中对象存活率高。老年代的垃圾回收(又称Major GC)通常使用“标记-清理”或“标记-整理”算法。整堆包括新生代和老年代的垃圾回收称为Full GC(HotSpot VM里,除了CMS之外,其它能收集老年代的GC都会同时收集整个GC堆,包括新生代)

当老年代的空间不足时,会触发Major GC/Full GC,速度一般比Minor GC慢10倍以上。

持久代(永久代)

    在JDK8之前的HotSpot实现中,类的元数据如方法数据、方法信息(字节码,栈和变量大小)、运行时常量池、已确定的符号引用和虚方法表等被保存在永久代中,32位默认永久代的大小为64M,64位默认为85M,可以通过参数-XX:MaxPermSize进行设置。GC不会在主程序运行期对永久区域进行清理,这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。

    所以虚拟机团队在JDK8的HotSpot中,把永久代从Java堆中移除了,并把类的元数据直接保存在本地内存区域(堆外内存),称之为元空间。

    元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入java堆中. 这样可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。

总结:

  • 为了分代垃圾回收,Java堆内存分为3代:新生代,老年代和永久代。

  • 新的对象实例会优先分配在新生代,在经历几次Minor GC后(默认15次),还存活的会被移至老年代(某些大对象会直接在老年代分配)。

  • Minor GC发生在新生代,当Eden区没有足够空间时,会发起一次Minor GC,将Eden区中的存活对象移至Survivor区。Major GC发生在老年代,当升到老年代的对象大于老年代剩余空间时会发生Major GC。

  • 发生Major GC时用户线程会暂停,会降低系统性能和吞吐量。

  • JVM的参数-Xmx和-Xms用来设置Java堆内存的初始大小和最大值。依据个人经验这个值的比例最好是1:1或者1:1.5。比如,你可以将-Xmx和-Xms都设为1GB,或者-Xmx和-Xms设为1.2GB和1.8GB。

  • Java中不能手动触发GC,但可以用不同的引用类来辅助垃圾回收器工作

猜你喜欢

转载自blog.csdn.net/akaks0/article/details/79705974