jvm 垃圾判定与垃圾回收器

简介: 任何对象都有它的生命周期,所以jvm需要定时地回收掉不用的内存,防止内存耗完。GC的时候必须暂停所有的java线程,不可以出现在分析过程中对象引用关系还在不停变化的情况。否则分析结果的准确性无法保证。 这种暂停线程的现象叫"stop the world",它给用户带去了不良体验,但无法完全避免。 1.对象存活判定 首先,需要知道哪些对象还在存活以及哪些对象可以回收,判定方法主要有引用

任何对象都有它的生命周期,所以jvm需要定时地回收掉不用的内存,防止内存耗完。GC的时候必须暂停所有的java线程,不可以出现在分析过程中对象引用关系还在不停变化的情况。否则分析结果的准确性无法保证。
这种暂停线程的现象叫"stop the world",它给用户带去了不良体验,但无法完全避免。

1.对象存活判定

首先,需要知道哪些对象还在存活以及哪些对象可以回收,判定方法主要有引用计数法以及引用链法两种,jvm使用的是后者 引用链法

1.1引用计数法

为每个对象维护一个引用计数器,每当有一个地方引用它时,此计数器+1,当引用失效时,计数器-1.当计数器变为0时就说明此对象可以被回收。
计数器+1的情况有:赋值给一个引用,放入一个容器等。
计数器-1的情况有:原引用指向其他的对象。
引用计数法并没有被用在java虚拟机中,因为它不能解决对象间循环引用问题。如:
class MyClass{
public Object obj;
}
main(){
MyClass a=new MyClass();
MyClass b=new MyClass();
a.obj=b;
b.obj=a;
b=a=null;//此时a与b对象都不能再次被访问,但它们的引用计数并不为0.
}

1.2引用链法

维护一批"gc roots"作为一批树的根,new出来的java对象作为节点。父子节点间的关系即为引用关系,当一个节点与根相连通时,对象不被回收;当二者不连通时,对象会被回收。它解决了对象间的循环引用问题。

一般选取各个线程中的线程栈中的对象作GCRoots。

2.finalize()方法

Object基类方法,用于定义垃圾收集器在回收对象所占内存之前所做的清理工作。它的设计目的就是回收特殊渠道申请的内存,比如本地代码申请的内存。

3.老年代垃圾收集器

3.1 CMS收集器

CMS,Concurrent Mark Sweep。
特点:追求停顿时间最短。它是 老年代收集器。
服务端的java程序重视响应速度,希望系统停顿时间最短,以给用户带来良好的体验。
CMS收集器是基于“标记-清除”算法实现的,分为四个步骤——初始标记,并发标记,重新标记,并发清除。
阶段 简述 时长 停止工作线程
初始标记 标记 GCRoots能直接关联到的对象 Y
并发标记 进行GC Roots tracing的过程 N
重新标记 修正并发标记期间产生变动的标记 Y
并发清除 执行内存回收 N

CMS的回收线程数x=(cpu数量+3)/4。

3.1.1 vm参数

由于在并发清除阶段,垃圾回收线程与用户线程并发执行,所以不能像其他收集器那样等到老年代几乎被占满了再进行收集,而是需要预留一部分供GC线程自身使用。所以会有一个比例阀值x(如0.9),老年代已经用掉的空间超过x时进行CMS回收。这个阀值x可以通过“ -XX:CMSInitiatingOccupancyFraction”参数来调整。适当调高此参数可以降低内存回收次数从而获取更好的性能。
如果CMS回收期间内存不够用,就会出现一次“Concurent Mode Failure”失败。虚拟机就会临时启用Serial Old收集器来重新进行老年代的收集。

3.2 Parallel Old

Parallel Old是Parallel Scavenge的老年代版本。

3.3 Serial Old

Serial Old是Serial收集器的老年代版本。

4.年轻代收集器

年轻代也成为新生代。新生代GC也是需要 stop the world的,通常为 几十毫秒
每当eden区满,就触发一次yong GC。

4.1 Serial

Serial是最基本、历史悠久的年轻代收集器。它在GC时必须暂停所有工作线程,所以现在一般不用了。

4.2 ParNew

ParNew其实就是Serial的多线程版本。现在一般也不用。

4.3 Parallel Scavenge

Parallel Scavenge的目标是达到一个可控制的吞吐量。吞吐量=工作线程运行时间 / (工作线程运行时间+垃圾收集时间).。虚拟机总共运行了100分钟,其中垃圾收集花费1分钟,那么吞吐量就是99%。


5.gc日志打印

JVM提供了大量命令行参数,打印信息,供调试使用。主要有以下一些:

  • -XX:+PrintGC
    输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs]

                    [Full GC 121376K->10414K(130112K), 0.0650971 secs]

  • -XX:+PrintGCDetails
    输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]

                    [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

  • -XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用
    输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
  • -XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用
    输出形式:Application time: 0.5291524 seconds
  • -XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间。可与上面混合使用
    输出形式:Total time for which application threads were stopped: 0.0468229 seconds
  • -XX:PrintHeapAtGC:打印GC前后的详细堆栈信息
    输出形式:
    34.702: [GC {Heap before gc invocations=7:
     def new generation   total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
    eden space 49152K,  99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
    from space 6144K,  55% used [0x221d0000, 0x22527e10, 0x227d0000)
      to   space 6144K,   0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
     tenured generation   total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
    the space 69632K,   3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
     compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
       the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
        ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
        rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
    34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:
     def new generation   total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
    eden space 49152K,   0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
      from space 6144K,  55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
      to   space 6144K,   0% used [0x221d0000, 0x221d0000, 0x227d0000)
     tenured generation   total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
    the space 69632K,   4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
     compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
       the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
        ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
        rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
    }
    , 0.0757599 secs]
  • -Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析。

目录
相关文章
|
4月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
403 55
|
6月前
|
Prometheus 监控 算法
CMS圣经:CMS垃圾回收器的原理、调优,多标+漏标+浮动垃圾 分析与 研究
本文介绍了CMS(Concurrent Mark-Sweep)垃圾回收器的工作原理、优缺点及常见问题,并通过具体案例分析了其优化策略。重点探讨了CMS的各个阶段,包括标记、并发清理和重标记
CMS圣经:CMS垃圾回收器的原理、调优,多标+漏标+浮动垃圾 分析与 研究
|
9月前
|
监控 算法 Java
Java虚拟机(JVM)垃圾回收机制深度剖析与优化策略####
本文作为一篇技术性文章,深入探讨了Java虚拟机(JVM)中垃圾回收的工作原理,详细分析了标记-清除、复制算法、标记-压缩及分代收集等主流垃圾回收算法的特点和适用场景。通过实际案例,展示了不同GC(Garbage Collector)算法在应用中的表现差异,并针对大型应用提出了一系列优化策略,包括选择合适的GC算法、调整堆内存大小、并行与并发GC调优等,旨在帮助开发者更好地理解和优化Java应用的性能。 ####
221 27
|
4月前
|
缓存 算法 Java
JVM深入原理(八)(一):垃圾回收
弱引用-作用:JVM中使用WeakReference对象来实现软引用,一般在ThreadLocal中,当进行垃圾回收时,被弱引用对象引用的对象就直接被回收.软引用-作用:JVM中使用SoftReference对象来实现软引用,一般在缓存中使用,当程序内存不足时,被引用的对象就会被回收.强引用-作用:可达性算法描述的根对象引用普通对象的引用,指的就是强引用,只要有这层关系存在,被引用的对象就会不被垃圾回收。引用计数法-缺点:如果两个对象循环引用,而又没有其他的对象来引用它们,这样就造成垃圾堆积。
128 0
|
4月前
|
算法 Java 对象存储
JVM深入原理(八)(二):垃圾回收
Java垃圾回收过程会通过单独的GC线程来完成,但是不管使用哪一种GC算法,都会有部分阶段需要停止所有的用户线程。这个过程被称之为StopTheWorld简称STW,如果STW时间过长则会影响用户的使用。一般来说,堆内存越大,最大STW就越长,想减少最大STW,就会减少吞吐量,不同的GC算法适用于不同的场景。分代回收算法将整个堆中的区域划分为新生代和老年代。--超过新生代大小的大对象会直接晋升到老年代。
94 0
|
6月前
|
缓存 监控 算法
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略
|
7月前
|
存储 算法 Java
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
89 6
|
10月前
|
机器学习/深度学习 监控 算法
Java虚拟机(JVM)的垃圾回收机制深度剖析####
本文深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法、性能调优策略及未来趋势。通过实例解析,为开发者提供优化Java应用性能的思路与方法。 ####
218 28
|
9月前
|
算法 网络协议 Java
【JVM】——GC垃圾回收机制(图解通俗易懂)
GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)
|
9月前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####