java GC分析浅谈

GC分析是为了进一步优化系统性能,性能优化是一个很大的领域,CPU、cache命中、IO各个方面都要综合进行考虑,这里我们只讲其中的一小部分,GC分析。在进行性能优化之前先要根据业务场景制定一个明确的性能需求指标,优化是一个无止境的事情,先制定好性能优化指标以便平衡投入和产出的问题。性能需求指标一般有以下几个:

  1. 应用预期的吞吐量是多少?
  2. 请求和响应之间的延迟预期是多少?
  3. 应用支持多少并发用户或并发任务?
  4. 当并发用户数或并发任务数达到最大时,可接受的吞吐量和延迟是多少?
  5. 最差情况下的延迟是多少?
  6. 要使垃圾收集引入的延迟在可容忍范围之内,垃圾回收的频率应该是多少?

一、GC判断方法(如何判断Java对象需要被回收)

一般我们把Java内存划分为以下几个区域,如图:
内存模型
我们常说的垃圾回收指的是回收掉堆内存,那如何来判断堆内存里的对象需要回收呢,业界通用有以下两种办法:

  1. 引用计数算法:引用计数法记录着每一个对象被其它对象所持有的引用数,被引用一次就加一,引用失效就减一;引用计数器为0则说明该对象不再可用;当一个对象被回收后,被该对象所引用的其它对象的引用计数都应该相应减少,它很难解决对象之间的相互循环循环引用实例
  2. 可达性分析算法:从GC Root对象向下搜索其所走过的路径称为引用链,当一个对象不再被任何的GC root对象引用链相连时说明该对象不再可用,GC root对象包括四种:方法区中常量和静态变量引用的对象,虚拟机栈中变量引用的对象,本地方法栈中引用的对象; 解决循环引用是因为GC Root通常是一组特别管理的指针,这些指针是tracing GC的trace的起点。它们不是对象图里的对象,对象也不可能引用到这些“外部”的指针。

Java GC采用的是第二种方法,可达性分析算法,接下来我们了解下Java对象的四种引用,这方面的知识在进行一般的业务开发时用的较少,但在深入优化GC时还是需要掌握的。

  • 强引用 :创建一个对象并把这个对象直接赋给一个变量,eg :Person person = new Person(“sunny”);不管系统资源有么的紧张,强引用的对象都绝对不会被回收,即使他以后不会再用到。
  • 软引用 :通过SoftReference类实现,eg : SoftReference p = new SoftReference(new Person(“Rain”));内存非常紧张的时候会被回收,其他时候不会被回收,所以在使用之前要判断是否为null从而判断他是否已经被回收了。
  • 弱引用 :通过WeakReference类实现,eg : WeakReference p = new WeakReference(new Person(“Rain”));不管内存是否足够,系统垃圾回收时必定会回收。
  • 虚引用:不能单独使用,主要是用于追踪对象被垃圾回收的状态,为一个对象设置虚引用关联的唯一目的是希望能在这个对象被收集器回收时收到一个系统通知。通过PhantomReference类和引用队列ReferenceQueue类联合使用实现。

二、垃圾回收算法(如何回收Java对象)

1、标记—清除算法
算法的执行过程与名字一样,先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象。该算法有两个问题:
1)标记和清除过程效率不高。主要由于垃圾收集器需要从GC Roots根对象中遍历所有可达的对象,并给这些对象加上一个标记,表明此对象在清除的时候被跳过,然后在清除阶段,垃圾收集器会从Java堆中从头到尾进行遍历,如果有对象没有被打上标记,那么这个对象就会被清除。显然遍历的效率是很低的;
2)会产生很多不连续的空间碎片,所以可能会导致程序运行过程中需要分配较大的对象的时候,无法找到足够的内存而不得不提前出发一次垃圾回收。
标记清除

2、复制算法
复制算法是为了解决标记-清除算法的效率问题的,其思想如下:将可用内存的容量分为大小相等的两块,每次只使用其中的一块,当这一块内存使用完了,就把存活着的对象复制到另外一块上面,然后再把已使用过的内存空间清理掉。这样当垃圾收集器进行回收的时候就不用考虑空间碎片的问题,缺点在于把内存缩小为原来的一半,代价未免有点大。
这里写图片描述
当然正是由于其缩小内存为原来的一半代价大的问题,现代的JVM并不是按照1:1划分内存空间的,二是将内存分为一块较大的Eden区和两块较小的S


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部