JVM 垃圾回收笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM 垃圾回收笔记相关的知识,希望对你有一定的参考价值。

1.JVM堆内存示意图(JDK1.8前)

JVM

JDK1.8(包含)后永久代改为原空间不在占用JVM堆内存,而是使用了物理内存。

2.JVM为什么要进行垃圾回收?

如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。

  1. GC是垃圾收集的意思(Gabage Collection),Java提供的GC功能可以自动也只能自动地回收堆内存中不再使用的对象,释放资源(目的),Java语言没有提供释放已分配内存的显式操作方法(gc方法只是通知,不是立即执行)。
  2. 对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。
  3. 垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,当一个对象不再被引用的时候,按照特定的垃圾收集算法来实现资源自动回收的功能。

3.垃圾回收算法有哪些?区别是什么?

复制算法:效率高,但空间使用率有限

标记-清除:内存使用率提升,但是内存碎片化严重

标记-整理:内存使用率提升,不存在内存碎片化,但是解决碎片化问题需要多次遍历内存进行合并故效率低下

4.垃圾回收器有哪些?区别是什么?

JVM

5.如何选择垃圾回收器?

6.最近一次JVM调优案例分析记录

背景:(刷脸、入网时传输图片)公司文件上传系统商户反应响应时间较长,平均10s左右

分析:配合各个部门进行排查,网络、运维(机器、硬件等),监控JVM GC运行情况后发现FULL GC时间过长平均在10s-15s左右

问题:线上环境jdk1.7,垃圾回收使用paraller scavenge(简称PS,吞吐量优先),开启动态内存分配,整堆内存32G,分配比例1/3,监控线上运行情况发现在早上10-12,下午14-16点为高峰期,大量请求打进导致endn区,由于开启动态分配内存(猜测JVM来不及反应当前这一笔)发生yong gc时导致S0或S1内存不够,导致全部打进老年代,PS在进行垃圾回收时回停止用户线程,由于分配内存较大导致回收时间长。

方案1:更改垃圾回收器(老年代使用CMS、年轻代使用parNew),重新分配内存及新生代S区比例(1:1,6:1:1),观察一段时间发现full gc比原来缩小15倍左右,但是yong gc提升0.4秒,S0或S1区即使发生yong gc进行交换后活跃对象还占用60%(猜测可能是因为副本同步导致对象还被占用无法释放)

方案2:更改垃圾回收器(老年代使用CMS、年轻代使用parNew),重新分配内存及新生代S区比例(1:2,6:1:1)



jvm学习笔记一(垃圾回收算法)

一:垃圾回收机制的原因

  java中,当没有对象引用指向原先分配给某个对象的内存时候,该内存就成为了垃圾。JVM的一个系统级线程会自动释放该内存块。垃圾回收意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。事实上,除了释放没用的对象,垃圾回收也可以清除内存记录碎片。由于创建对象和垃圾回收器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内存分配给新的对象。

  垃圾回收的优点:垃圾回收能自动释放内存空间,减轻编程的负担。首先,它能使编程效率提高。在没有垃圾回收机制的时候,可能要花许多时间来解决一个难懂的存储器问题。在用Java语言编程的时候,靠垃圾回收机制可大大缩短时间。其次是它保护程序的完整性, 垃圾回收是Java语言安全性策略的一个重要部份。

  垃圾回收的缺点:垃圾回收的开销影响程序性能。Java虚拟机必须追踪运行程序中有用的对象,而且最终释放没用的对象。这一个过程需要花费处理器的时间。其次垃圾回收算法的不完备性,早先采用的某些垃圾回收算法就不能保证100%收集到所有的废弃内存。当然随着垃圾回收算法的不断改进以及软硬件运行效率的不断提升,这些问题都可以迎刃而解。

二:垃圾收集的算法分析

  1.引用计数器算法:

  引用计数法是唯一没有使用根集的垃圾回收的方法,该算法使用引用计数器来区分存活对象和不再使用的对象。

  引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器-1,当计数器为0的时候,JVM就认为对象不再被使用,是“垃圾”了。

引用计数器实现简单,效率高;但是不能解决循环引用问问题(A对象引用B对象,B对象又引用A对象,但是A,B对象已不被任何其他对象引用),同时每次计数器的增加和减少都带来了很多额外的开销,所以在JDK1.1之后,这个算法已经不再使用了。

  2.根搜索方法:

  大多数垃圾回收算法使用了根集(root set)这个概念;所谓根集就是正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。垃圾回收首先需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。而根集通过任意路径不可达的对象符合垃圾收集的条件,应该被回收。下面介绍几个常用的算法。

  2.1 标记—清除算法(Mark-Sweep

  原理:标记—清除算法包括两个阶段:“标记”和“清除”。在标记阶段,确定所有要回收的对象,并做标记。清除阶段紧随标记阶段,将标记阶段确定不可用的对象清除。

 

  缺点:标记—清除算法是基础的收集算法,标记和清除阶段的效率不高,而且清除后回产生大量的不连续空间,这样当程序需要分配大内存对象时,可能无法找到足够的连续空间。

  垃圾回收前:

 

      技术分享

 

  垃圾回收后:

 

      技术分享

 

  绿色:存活对象 红色:可回收对象 白色:未使用空间

  2.2复制算法(Copying

  原理:复制算法是把内存分成大小相等的两块,每次使用其中一块,当垃圾回收的时候,把存活的对象复制到另一块上,然后把这块内存整个清理掉。

  缺点:复制算法实现简单,运行效率高,但是由于每次只能使用其中的一半,造成内存的利用率不高。现在的JVM用复制方法收集新生代,由于新生代中大部分对象(98%)都是朝生夕死的,所以两块内存的比例不是1:1(大概是8:1)

 

  垃圾回收前:

      技术分享

 

  垃圾回收后:

 

       技术分享

 

    绿色:存活对象 红色:可回收对象 白色:未使用空间

  2.3 标记—整理算法(Mark-Compact

  原理:标记—整理算法和标记—清除算法一样,但是标记—整理算法不是把存活对象复制到另一块内存,而是把存活对象往内存的一端移动,然后直接回收边界以外的内存。

  标记—整理算法提高了内存的利用率,并且它适合在收集对象存活时间较长的老年代。

  垃圾回收前:

      技术分享

  垃圾回收后:

      技术分享

      绿色:存活对象 红色:可回收对象 白色:未使用空间

  上面这四种是最基本的垃圾回收算法,在这四种算法思想之上发展出来其余算法,个人认为更多的是一种内存管理策略,甚至可以看成就是基本算法的组合应用,就像加减乘除与方程式的关系一样,因此将其分开描述。

 

  3.渐进式算法

    这类算法一般由基本算法组成,其核心思想是将内存分区域进行管理,在不同的区域和不同的时间采用不同的内存管理策略,从而避免因全系统的垃圾回收导致程序长时间暂停。这类算法一般有以下几种:

   3.1.火车算法

    这种算法把成熟的内存空间划为固定长度的内存块,算法每次在一个块中单独执行,每一个块属于一个集合。此算法的具体执行步骤较复杂,且没有具体的应用场景,在此不浪费笔墨,有兴趣的同学可以自己研究之。

    3.2.分代收集算法

    这种算法在sun/oracle公司的Hotspot虚拟机中得到应用,是java程序员需要重点关注的一种算法。

    这种算法是通过对对象的生命周期进行分析后得出的,它将堆内存分成了三个部分:年青代,年老代,持久代(相当于方法区)。处于不同生命周期的对象被存储于不同的区域,并使用不同的算法进行回收。这种算法的具体执行细节将会在后续的学习笔记中详细介绍。

  关于分代收集 详见 http://www.importnew.com/19255.html

    另外需要特别注意的是利用多线程实现的堆垃圾回收技术,这方面资料来源于网络,摘抄如下:

 4.多线程实现的堆垃圾回收技术

    4.1.串行收集

    串行收集使用单线程处理所有垃圾回收工作,因为无需多线程交互,实现容易,而且效率比较高。但是,其局限性也比较明显,即无法使用多处理器的优势,所以此收集适合单处理器机器。当然,此收集器也可以用在小数据量(100M左右)情况下的多处理器机器上。

    适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应用。

    缺点:只能用于小型应用。

    4.2.并行收集

    并行收集使用多线程处理垃圾回收工作,因而速度快,效率高。而且理论上CPU数目越多,越能体现出并行收集器的优势。

    适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用。举例:后台处理、科学计算。

    缺点:应用响应时间可能较长 。

    4.3.并发收集

    相对于串行收集和并行收集而言,前面两个在进行垃圾回收工作时,需要暂停整个运行环境,而只有垃圾回收程序在运行,因此,系统在垃圾回收时会有明显的暂停,而且暂停时间会因为堆越大而越长。

    适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。

 

参考:

http://blog.csdn.net/zsuguangh/article/details/6429592

http://blog.csdn.net/ol_beta/article/details/6791229

https://my.oschina.net/GameKing/blog/198347

以上是关于JVM 垃圾回收笔记的主要内容,如果未能解决你的问题,请参考以下文章

JVM笔记6-垃圾回收概述

jvm学习笔记一(垃圾回收算法)

JVM学习笔记GC——JAVA预言的垃圾回收

JVM学习笔记GC——JAVA语言的垃圾回收

JVM学习笔记2:垃圾回收算法及垃圾回收器原理解读及特性对比详解

JVM垃圾回收阅读笔记