JVM中有特定的垃圾回收机制,堆内存划分为du Eden、Survivor 和 Tenured/Old 空间。

GC

即就是Java垃圾回收机制。

Full GC

是清理整个堆空间—包括年轻代和永久代

目前主流的JVM(HotSpot)采用的是分代收集算法

JVM解释

话不多说直接上图

java fullgc频繁 java中full gc_java fullgc频繁

  • 堆(Heap)
    是Jvm管理的内存中最大的一块。程序的主要数据也都是存放在堆内存中的,这一块区域被所有的线程所共享,通常出现线程安全问题的一般都是这个区域的数据出现的问题。
  • 方法区(Method Area)
    与Heap一样,也是各个线程共享的内存域,这块区域主要是用来存储类加载器加载的类信息,常量,静态变量,通俗的讲就是编译后的class文件信息。
  • Jvm栈
    与程序计数器一样,它是每个线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
  • 本地方法栈(Native Method Stacks)
    本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
  • 程序计数器
    程序计数器是每个线程独有的,所以是线程安全的。它主要用于记录每个线程的执行情况。

jvm heap区域

分为年轻代,老年代和持久代。

jvm heap规则:

  1. 对象优先在Eden区分配
  2. 大对象直接进入老年代(-XX:PretenureSizeThreshold=3145728 这个参数来定义多大的对象直接进入老年代)
  3. 长期存活的对象将进入老年代(在JDK8中测试,-XX:MaxTenuringThreshold=1的阀值设定根本没用)
  4. 动态对象年龄判定(虚拟机并不会永远地要求对象的年龄都必须达到MaxTenuringThreshold才能晋升老年代,如果Survivor空间中相同年龄的所有对象的大小总和大于Survivor的一半,年龄大于或等于该年龄的对象就可以直接进入老年代)
  5. 空间分配担保
  6. 只要老年代的连续空间大于(新生代所有对象的总大小或者历次晋升的平均大小)就会进行minor GC,否则会进行full GC
  • 英文图解如下:

触发Full GC执行的四种情况

  • 旧生代空间不足
    旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出如下错误:
    java.lang.OutOfMemoryError: Java heap space

解决:调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。

  • Permanet Generation空间满
    PermanetGeneration中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出如下错误信息:
    java.lang.OutOfMemoryError: PermGen space 解决:可采用的方法为增大Perm Gen空间或转为使用CMS GC。
  • CMS GC时出现promotion failed和concurrent mode failure
    对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能会触发Full GC。promotionfailed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代也放不下造成的;concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。
    解决:增大survivorspace、旧生代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的版本中有可能会由于JDK的bug29导致CMS在remark完毕后很久才触发sweeping动作。对于这种状况,可通过设置-XX:CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。
  • 统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间
    这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,如果之前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。

gc的回收算法

  • 标记-清除
  • 复制算法标记
  • 整理(Mark-Compat)算法
  • 分代收集(Generational Collection)算法

垃圾回收器

  • Serial收集器
  • ParNew收集器
  • Parallel Scavenge收集器
  • CMS(Concurrent Mark Sweep)收集器
  • G1(Garbage First)收集器(从JDK1.7 Update 14之后的HotSpot虚拟机正式提供了商用的G1收集器)关于垃圾回收器的使用。

备注:以上均为学习时的笔记,不足之处请留言督促,谢谢!