JVM 垃圾收集器与内存分配策略

来源:互联网 发布:双十一红包 淘宝联盟 编辑:程序博客网 时间:2024/06/03 23:38

印象笔记版

  1. 判断对象是否存活的方法:

    计数算法:给对象添加一个引用计数器,每当引用计数器加1,引用失效计数器减1,任何时刻都为0的对象不可能再被使用。缺陷是难以解决对象之间的相互循环引用的问题。
    根搜索算法;以名为“GC Roots”的对象为起始点。往下搜索,走过的路径称为“引用链”。当一个对象到GC Roots没有任何引用链相连时,该对象不可用。其中可以作为GC Roots的对象包括:
    虚拟机栈中引用的对象。
    方法区中的类静态属性引用的对象。
    方法区中的常量引用的对象。
    本地方法栈中JNI(即一般说的Native方法)的引用的对象。

       真正宣告一个对象死亡,至少要经历两次标记过程,上述根搜索为第一次标记,随后进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。   没有必要执行的条件:当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过。   若有必要执行finalize()方法,该对象会被放置在一个名为F-Queue的队列中,并在稍后由一条由虚拟机自动建立的、低优先级的Finalizer线程去执行。(执行指的是虚拟机会触发这个方法,但不承诺等待它运行结束)   垃圾收集器 在执行完finalize()方法后对F-Queue中的对象进行第二次小规模的标记,若对象仍未与引用链上的任何一个对象建立关联随后会被销毁。

    2.引用

    JDK1.2前:如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表这一个引用。
    JDK1.2后:将引用进行扩充:强引用,软引用,弱引用,虚引用
    强引用:代码中普遍存在的,类似Object obj = new Object();只要强引用存在,垃圾收集器永远不会回收被引用的对象。
    软引用:一些有用但非必需的对象。在系统发生内存溢出异常前会对此进行回收,若内存仍然不够才会发生内存溢出异常。SoftReference类实现。
    弱引用:非必需。在下次垃圾收集器工作时无论内存是否足够都被清理。WeakReference类实现。
    虚引用:幽灵引用/幻影引用,目的是希望在这个对象被回收时收到一个系统通知。PhantomReference类实现。

    3.无用的类:

    该类的所有实例都已经被回收,也就是java堆中不存在该类的任何实例。
    加载该类的ClassLoader已经被回收。
    该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

    虚拟机可以对满足上面3个条件的无用类进行回收。是否进行回收,HotSpot虚拟机提供-Xnoclassgc参数进行控制。

    4.垃圾收集算法:

    标记-清除算法:分标记、清除两个阶段。缺点有两点:一是效率问题,二是空间问题(产生大量不连续内存碎片)。
    复制算法:将内存容量一分为二,使用其中一块,当其满时,将存活对象复制到另一块,把使用过的对象清理掉。代价就是内存缩小一半。现实中常用的是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用其中的一块Survivor和Eden空间,当回收时,将两者存活对象移动至另一块Survivor空间后清理。Hotspot默认Eden和survivor大小比例为8:1.
    标记-整理算法:标记后让所有存活的对象向一端移动,清理掉边界以外的内存。
    分代收集算法:根据对象的存活周期将内存分为几块。一半分为新生代和老年代,新生代有大量对象死去,老年代对象存活率高。

    5.垃圾收集器:

    Serial收集器:单线程收集器,使用时必须暂停其他所有工作线程(Stop the world)。对于Client模式下的虚拟机来说是个不错的选择。
    ParNew收集器:多线程的serial收集器。Server模式下首选的新生代收集器。和Serial是唯二能与CMS收集器配合工作。并发即实现垃圾收集线程和用户线程同时工作。
    Parallel Scavenge收集器:特点是目标是达到一个可控制的吞吐量。自适应调节策略。
    Serial Old收集器
    Parallel Old收集器
    CMS(Concurrent Mark Sweep)收集器:以获取最短回收停顿时间为目标的收集器。分为4个步骤:初始标记,并发标记,重新标记,并发清除。初始标记和重新标记会stop the world。初始标记GC Roots能直接关联的对象,并发标记阶段进行GC Roots Tracing,重新标记是修正并发标记期间,因用户程序继续运作而导致标记产生变动的对象。缺点:1.默认启动回收线程数是(cpu数+3)/4,cpu少就很卡。2.无法处理浮动垃圾,3.基于标记-清除算法。
    G1收集器:基于“标记-整理”算法。精确控制停顿。基本实现不牺牲吞吐量前提下完成低停顿的内存回收。将java堆划分为多个大小固定的独立区域,跟踪区域内垃圾堆积程度,在后台维护一个优先列表,确保在有限的时间内获得最高的收集效率(G1收集器已在JDK 1.7 u4版本正式投入使用)。

    6.垃圾收集器参数总结

    -XX:+ 启用选项
    -XX:- 不启用选项
    -XX:=
    -XX:=

-XX:+UseSerialGC

Jvm运行在Client模式下的默认值,打开此开关后,使用Serial + Serial Old的收集器组合进行内存回收
-XX:+UseParNewGC

打开此开关后,使用ParNew + Serial Old的收集器进行垃圾回收
-XX:+UseConcMarkSweepGC

使用ParNew + CMS + Serial Old的收集器组合进行内存回收,Serial Old作为CMS出现“Concurrent Mode Failure”失败后的后备收集器使用。
-XX:+UseParallelGC

Jvm运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge + Serial Old的收集器组合进行回收
-XX:+UseParallelOldGC

使用Parallel Scavenge + Parallel Old的收集器组合进行回收
-XX:SurvivorRatio

新生代中Eden区域与Survivor区域的容量比值,默认为8,代表Eden:Subrvivor = 8:1
-XX:PretenureSizeThreshold

直接晋升到老年代对象的大小,设置这个参数后,大于这个参数的对象将直接在老年代分配
-XX:MaxTenuringThreshold

晋升到老年代的对象年龄,每次Minor GC之后,年龄就加1,当超过这个参数的值时进入老年代
-XX:UseAdaptiveSizePolicy

动态调整java堆中各个区域的大小以及进入老年代的年龄
-XX:+HandlePromotionFailure

是否允许新生代收集担保,进行一次minor gc后, 另一块Survivor空间不足时,将直接会在老年代中保留
-XX:ParallelGCThreads

设置并行GC进行内存回收的线程数
-XX:GCTimeRatio

GC时间占总时间的比列,默认值为99,即允许1%的GC时间,仅在使用Parallel Scavenge 收集器时有效
-XX:MaxGCPauseMillis

设置GC的最大停顿时间,在Parallel Scavenge 收集器下有效
-XX:CMSInitiatingOccupancyFraction

设置CMS收集器在老年代空间被使用多少后出发垃圾收集,默认值为68%,仅在CMS收集器时有效,-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSCompactAtFullCollection

由于CMS收集器会产生碎片,此参数设置在垃圾收集器后是否需要一次内存碎片整理过程,仅在CMS收集器时有效
-XX:+CMSFullGCBeforeCompaction

设置CMS收集器在进行若干次垃圾收集后再进行一次内存碎片整理过程,通常与UseCMSCompactAtFullCollection参数一起使用

7.java提倡的自动内存管理归结为自动化地解决了两个问题:给对象分配内存和回收分配给对象的内存。
内存分配规则:

对象优先在Eden分配:多少情况下,对象在新生代Eden区中分配。当Eden区没有足够空间,虚拟机发起一次Minor GC(新生代GC)。大对象直接进入老年代:指的是需要大量连续内存空间的java对象典型的是很长的字符串及数组。长期存活的对象将进入老年代:虚拟机对每个对象定义一个对象年龄计数器。动态对象年龄判定:如果在Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代。空间分配担保:在发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,若大于,进行一次Full GC(老年代GC),如果小于,查看HandlePromotionFailure设置是否允许担保失败,如果允许,只会进行Minor GC,如果不允许,改为进行一次Full GC。

注意:这里有许多参数没有列举出来。