第三章 垃圾收集器与内存分配策略

2017-03-24  本文已影响58人  骊骅

GC三件事

主要考虑的是方法区

如何判断对象已死

1、引用计数:实现简单,教科书答案,java虚拟机没有采用

2、根搜索算法:

基本思路就是通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

3、java里面可以作为GCRoots的对象:

a.虚拟机栈(栈桢中的本地变量表)中的引用的对象

b.方法区中的类静态属性引用的对象

c.方法区中的常量引用的对象

d.本地方法栈中JNI的引用的对象

4、如何判断一个对象已死

5、垃圾收集算法

算法名称 英文名 描述 优点 缺点
标记-清除 Mark-Sweep 算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象 1、效率不高;2、内存碎片,效率不高
复制算法 Copying 将内存分为一块较大的Eden空间和两块较小的Survivor空间,8:1,内存利用率90% 解决了效率问题【适合新生代】 利用率低了
标记-整理 Mark-Compact 标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存 减少复制,减少空间浪费
分代收集算法 Generational Collection 根据对象存活周期的不同将内存划分为几块。一般为新生代和老生代,新生代采用复制算法,老生代采用标记-清除 或是 标记-整理

6、垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现
HotSpot虚拟机的垃圾收集器

名字 新\老 生代 原理 优点 缺点 备注
Serial收集器 复制算法;收集器是一个单线程的收集器;必须暂停其他所有的工作线程,直到它收集结束 简单而高效,少了线程交互开销 Stop The World Client模式下的虚拟机新生代默认选择
ParNew收集器 ParNew收集器其实就是Serial收集器的多线程版本 多线程 单CPU还不如Serial收集器 是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作
Parallel Scavenge收集器 Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(Throughput)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间) 复制算法;并行
Serial Old收集器 使用“标记-整理”算法
Parallel Old收集器 Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法
CMS收集器(Concurrent Mark Sweep) CMS收集器是基于“标记—清除”算法实现的

并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状
态。

并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能
会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。

7、理解GC日志

2017-03-24T11:18:49.803+0800: 311976.229: [GC (Allocation Failure) 2017-03-24T11:18:49.803+0800: 311976.229: [ParNew: 1428004K->26220K(1485504K), 0.0369712 secs] 3356779K->1955081K(5155520K), 0.0373455 secs] [Times: user=0.13 sys=0.00, real=0.04 secs]

2017-03-24T11:18:49.803+0800:【1】 311976.229:【2】 [GC【3】 (Allocation Failure【4】) 2017-03-24T11:18:49.803+0800: 311976.229: [ParNew:【5】 1428004K->26220K【6】 (1485504K【7】), 0.0369712 secs【8】] 3356779K->1955081K【9】(5155520K【10】), 0.0373455 secs【11】] [Times: user=0.13 sys=0.00, real=0.04 secs【12】]

详解:

8、内存分配与回收策略

package study3;

/**
 *
 * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
 * @date 2017/03/24
 */
public class TestAllocation {
    public static void main(String[] args) {
        final int _1MB = 1024 * 1024;
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        // 出现一次Minor GC
        allocation4 = new byte[4 * _1MB];
    }
}

[GC [ParNew: 8118K->473K(9216K), 0.0075132 secs] 8118K->473K(19456K), 0.0086882 secs] [Times: user=0.00 sys=0.01, real=0.01 secs] 
Heap
 par new generation   total 9216K, used 4981K [7f9a00000, 7fa400000, 7fa400000)
  eden space 8192K,  55% used [7f9a00000, 7f9e66db0, 7fa200000)
  from space 1024K,  46% used [7fa300000, 7fa3767f0, 7fa400000)
  to   space 1024K,   0% used [7fa200000, 7fa200000, 7fa300000)
 concurrent mark-sweep generation total 10240K, used 0K [7fa400000, 7fae00000, 7fae00000)
 concurrent-mark-sweep perm gen total 21248K, used 4898K [7fae00000, 7fc2c0000, 800000000)
上一篇 下一篇

猜你喜欢

热点阅读