Java中的GC机制

这是一篇转载自“http://yemengying.com/2016/05/13/jvm-GC/”的一篇很好的关于垃圾回收机制的文章,总结的很到位,非常感谢Giraffe童鞋的贡献,向原文作者致敬!这里只是简单的罗列,跟详细的细节可以仔细的研究下原文,连接如上。
Java中的垃圾回收机制
1.关键字约定
    Young generation –>新生代
    Tenured / Old Generation –>老年代
    Perm Area –>永久代
2.GC机制的核心
    在Java中,对象实例都是在堆上创建。一些类信息,常量,静态变量等存储在方法区。堆和方法区都是线程共享的。
    GC机制是由JVM提供,用来清理需要清除的对象,回收堆内存。
    GC机制将Java程序员从内存管理中解放了出来,可以更关注于业务逻辑。
    在Java中,GC是由一个被称为垃圾回收器的守护线程执行的。
    在从内存回收一个对象之前会调用对象的finalize()方法。
    作为一个Java开发者不能强制JVM执行GC;GC的触发由JVM依据堆内存的大小来决定。
    System.gc()和Runtime.gc()会向JVM发送执行GC的请求,但是JVM不保证一定会执行GC。
    如果堆没有内存创建新的对象了,会抛出OutOfMemoryError。
    3.GC机制正对的是什么对象?
    了解GC机制的第一步就是理解什么样的对象会被回收。
    当一个对象通过一系列根对象(比如:静态属性引用的常量)都不可达时就会被回收。
    简而言之,当一个对 象的所有引用都为null。
    循环依赖不算做引用,如果对象A有一个指向对象B的引用,对象B也有一个指向对象A的引用,除此之外,它们没有其他引用,那么 对象A和对象B都、需要被回收(如下图,ObjA和ObjB需要被回收)。

这里写图片描述

    4.在Java开发中,堆内存是如何划分的?
Java开发和C语言和C++是最大的区别就是解放了程序员在开发过程中对内存占用率的考虑,完全的交给javaJVM中的GC机制来处理Java中所创建的对象,那么在了解JavaGC机制时必须了解Java中对于堆内存的划分。
首先要明确,Java中对象都在堆上创建。
Java的JVM为了GC,堆内存分为三个部分,也可以说三代,分别称为新生代,老年代和永久代。其中新生代又进一步分为Eden 区,Survivor 1区和Survivor 2区(如下图)。新创建的对象会分配在Eden区,在经历一次Minor GC后会被移到Survivor 1区,再经历一次Minor GC后会被移到Survivor 2区,直到升至老年代,需要注意的是,一些大对象(长字符串或数组)可能会直接存放到老年代。

这里写图片描述

永久代有一些特殊,它用来存储类的元信息。对于GC是否发生在永久代有许多不同的看法,在我看来这取决于采用的JVM。大家可以通过创建大量的字符串来观察是发生了GC还是抛出了OutOfMemoryError。
5.GC算法
这个在之前的了解GC还不深入的情况,还是只知道GC一些很基础简单的东西,很少了解关于GC算法的概念和过程。
5.1 标记清除算法
分为标记和清除两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。该算法的缺点是效率不高并且会产生不连续的内存碎片。

这里写图片描述

5.2 复制算法
把内存空间划为两个区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中 的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。优点:实现简单,运行高效。缺点:会浪费一定的内存。一般 新生代采用这种算法。

这里写图片描述

5.3 标记整理算法
标记阶段与标记清除算法一样。但后续并不是直接对可回收的对象进行清理,而是让所有存活对象都想一端移动,然后清理。优点是不会造成内存碎片。

这里写图片描述

6.总结
    为了分代垃圾回收,Java堆内存分为3代:新生代,老年代和永久代。
    新的对象实例会优先分配在新生代,在经历几次Minor GC后(默认15次),还存活的会被移至老年代(某些大对象会直接在老年代分配)。
    永久代是否执行GC,取决于采用的JVM。
    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,但可以用不同的引用类来辅助垃圾回收器工作(比如:弱引用或软引用)。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java的垃圾回收机制(Garbage Collection)是Java虚拟机(JVM)自动回收不再使用的对象的过程。Java的垃圾回收机制是基于JVM实现的,其工作原理是通过监控Java程序的活动,查找不再使用的对象,并释放它们所占用的内存空间,从而防止内存泄漏和内存溢出。 Java的垃圾回收机制可以分为两种类型:标记-清除和复制算法。 标记-清除算法: 1. 标记所有活动对象 2. 清除所有未标记的对象 3. 缺点:会留下大量的碎片化空间,导致内存使用率下降。 复制算法: 1. 把内存分成两个部分,一部分用于存储对象,另一部分则保持空闲状态。 2. 当需要进行垃圾回收时,将还存活的对象复制到未使用的内存空间。 3. 清空已使用的内存空间 4. 优点:不会产生碎片化空间,内存使用率高。 Java垃圾回收机制的触发条件: 1. 内存空间不足 2. 程序调用System.gc()方法 3. 程序调用Runtime.getRuntime().gc()方法 Java垃圾回收机制的优缺点: 优点: 1. 不需要手动管理内存空间,避免了内存泄漏和内存溢出的问题。 2. 对于大型的项目,垃圾回收机制可以提高开发效率和代码质量。 缺点: 1. 垃圾回收机制会消耗一定的CPU资源和内存空间,有可能会导致程序运行速度变慢。 2. 由于垃圾回收机制是自动执行的,无法完全控制,有时会导致应用程序出现不可预测的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值