可回收判定两种算法
引用计数法(Reference Counting):引用为0时可回收。
可达性分析法(Reachability Analysis): 从GCRoots对象到这个对象不可达。
GCRoots:
  • 本地变量表引用的对象;
  • 方法区中静态属性引用的对象
  • 方法区中常量引用的对象
  • Native方法栈引用的对象。
个人理解,即在生命周期内不会变得不可达的对象。
 
垃圾收集算法
复制算法,一般用于新生代的minor gc,效率较高;
标记-整理算法,用于老年代的full gc,效率较低。
 

内存分配回收策略
1、在新生代 Eden区分配内存(大对象可能直接分配到老年代)。新生代内存不够用,则触发minor gc到步骤2;
2、标记可回收对象;
3、将存活对象复制到Survivor区(to survivor),年龄计数器+1,年龄超过阈值的对象复制到老年代,或按动态年龄判定复制到老年代;
4、清空Eden区和from survivor区。存活下来的对象(年龄>=1)留在了survivor区;
5、触发minor gc之前检查,发现分配担保有风险(老年代剩余空间小于所有对象总空间),且HandlePromotionFailure=false,则触发一次full gc。
6、触发minor gc之前检查,虽然HandlePromotionFailure=true,但分配担保失败概率较高,则触发一次full gc。
7、如果在写老年代时,发现老年代不够用(担保失败),则触发一次full gc; 
 

测试代码
public class TestGC{
public static void main(String[] argv){
BigObj obj1 = new BigObj();
BigObj obj2 = new BigObj();
obj1 = new BigObj();
obj2 = new BigObj();
BigObj obj3 = new BigObj();
BigObj obj4 = new BigObj();
}
static class BigObj{
private byte[] arr = new byte[3145728];
}
}
执行命令:java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -classpath .  TestGC
运行结果
 

[GC [PSYoungGen: 6831K->432K(9216K)] 6831K->6576K(19456K), 0.0033010 secs] [Times: user=0.02 sys=0.01, real=0.00 secs]
[Full GC [PSYoungGen: 432K->0K(9216K)] [ParOldGen: 6144K->6373K(10240K)] 6576K->6373K(19456K) [PSPermGen: 2586K->2585K(21504K)], 0.0069120 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[Full GC [PSYoungGen: 6315K->0K(9216K)] [ParOldGen: 6373K->6371K(10240K)] 12689K->6371K(19456K) [PSPermGen: 2585K->2585K(21504K)], 0.0044660 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 9216K, used 6339K [0x00000007ff600000, 0x0000000800000000, 0x0000000800000000)
eden space 8192K, % used [0x00000007ff600000,0x00000007ffc30cf0,0x00000007ffe00000)
from space 1024K, % used [0x00000007ffe00000,0x00000007ffe00000,0x00000007fff00000)
to space 1024K, % used [0x00000007fff00000,0x00000007fff00000,0x0000000800000000)
ParOldGen total 10240K, used 6371K [0x00000007fec00000, 0x00000007ff600000, 0x00000007ff600000)
object space 10240K, % used [0x00000007fec00000,0x00000007ff238fc0,0x00000007ff600000)
PSPermGen total 21504K, used 2592K [0x00000007f9a00000, 0x00000007faf00000, 0x00000007fec00000)
object space 21504K, % used [0x00000007f9a00000,0x00000007f9c88310,0x00000007faf00000)

这段代码一共生成了6个对象,分别叫做 obj1,obj2,obj1_,obj2_,obj3,obj4;
预想的结果是:
  1. obj1和obj2分配到新生代Eden区,约6M;
  2. 分配obj1_时,eden区空间不足,触发一次minor gc。由于survivor区大小只有1M,将obj1和obj2复制到老年代,eden区清空(日志中还有432k不知道是什么内容)
  3. obj1_和obj2_分配到新生代Eden区,约6M;此时obj1和obj2都变成了可回收对象;
  4. 分配obj3时,eden区空间不足,触发一次minor gc。由于空间担保失败,触发full gc,老年代的obj1和obj2清空,新生代的obj1_和obj2_复制到老年代,eden区清空。此时老年代占用6M,新生代0M;
  5. obj3和obj4分配到eden区。最终老年代占用6M,新生代占用6M。
日志和预想的结果有出入,好像是在第2步后额外触发了一次full gc。可能和Parallel Scavenge的悲观策略有关
另外,从日志可以看出,虚拟机使用的收集器组合是Parallel Scavenge+Parallel Old。

《深入理解java虚拟机》读书笔记——垃圾收集与内存分配策略的更多相关文章

  1. 深入理解Java虚拟机二:垃圾收集与内存分配

    垃圾收集:垃圾收集要完成三件事,包括哪些内存需要回收,什么时候回收及如何回收. 1.需要回收的内存判定:没有引用指向原先分配给某个对象的内存时,则该内存是需要回收的垃圾 Java垃圾收集器在对内存进行 ...

  2. 深入理解Java虚拟机 -- 读书笔记(1):JVM运行时数据区域

    深入理解Java虚拟机 -- 读书笔记:JVM运行时数据区域 本文转载:http://blog.csdn.net/jubincn/article/details/8607790 本系列为<深入理 ...

  3. 【Todo】深入理解Java虚拟机 读书笔记

    有一个在线系列地址 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> http://book.2cto.com/201306/25426.html 已经下载了这本书(60多M ...

  4. 深入理解Java虚拟机读书笔记2----垃圾收集器与内存分配策略

    二 垃圾收集器与内存分配策略 1 JVM中哪些内存需要回收?     JVM垃圾回收主要关注的是Java堆和方法区这两个区域:而程序计数器.虚拟机栈.本地方法栈这3个区域随线程而生,随线程而灭,随着方 ...

  5. 深入理解Java虚拟机读书笔记5----虚拟机字节码执行引擎

    五 虚拟机字节码执行引擎   1 运行时栈帧结构     ---栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机运行时数据区中的虚拟机栈的栈元素.     ---栈帧中存储了方法的局部变 ...

  6. 深入理解Java虚拟机读书笔记7----晚期(运行期)优化

    七 晚期(运行期)优化 1 即时编译器(JIT编译器)     ---当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”,包括被多次调用的方法和被多次执行的循环体.     ...

  7. 深入理解Java虚拟机读书笔记1----Java内存区域与HotSpot虚拟机对象

    一 Java内存区域与HotSpot虚拟机对象 1 Java技术体系.JDK.JRE?     Java技术体系包括:         · Java程序设计语言:         · 各种硬件平台上的 ...

  8. 深入理解java虚拟机读书笔记--java内存区域和管理

    第二章:Java内存区域和内存溢出异常 2.2运行时数据区域 运行时数据区分为方法区,堆,虚拟机栈,本地方法栈,程序计数器 方法区和堆是线程共享的区域 虚拟机栈,本地方法栈,程序计数器是数据隔离的数据 ...

  9. 深入理解Java虚拟机——读书笔记

    首先 强烈推荐周志明老师的这本书,真的可以说是(起码中文出版界)新手了解Java虚拟机必须人手一本的教科书!!!   第二部分自动内存管理机制 由于Java虚拟机的多线程是通过线程轮流切换并分配处理器 ...

随机推荐

  1. 在qt creator中使用imread并将图片显示到QLable中时没反应

    调试时发现Mat m = imread("")函数运行了,但是将鼠标放在m上面时,发现m是空的,但是竟然能往下运行,简直恶心,于是我在后面加上判断m.empty(),发现返回了tu ...

  2. php 服务端允许跨域访问

    加上需要允许跨域访问,配置如下(一下配置内容前不允许有其他任何输出操作): //设置允许跨域的 请求源地址//方式一:header("Access-Control-Allow-Origin: ...

  3. meven仓库设置局域网私服

    找到设置文件 在设置文件中配置私服地址

  4. 20. Web proxies (网页代理 4个)

    用于评估Web应用程序漏洞的基于Java的Web代理. 它支持在运行时编辑/查看HTTP / HTTPS消息,以更改Cookie和表单字段等项. 它包括网络流量记录器,网络蜘蛛,哈希计算器和用于测试常 ...

  5. Python_day_01

    python                                                       (1024程序员节) 语言分为很多种,但是如果要想和计算机交流,就必须知道计算 ...

  6. Django学习笔记之验证和授权

    验证和授权概述 Django有一个内置的授权系统.他用来处理用户.分组.权限以及基于cookie的会话系统.Django的授权系统包括验证和授权两个部分.验证是验证这个用户是否是他声称的人(比如用户名 ...

  7. GitHub Pages:静态站点托管服务(待补充)

    不管是 react 还是 vue 项目路由都必须使用 hash 方式,否则页面打不开,切记!!! 如果使用的是 vue-cli 3 创建项目,那么你要在根目录创建 vue.config.js 文件,并 ...

  8. mysql 存储过程的实现原理

    一.描述 存储过程是一组可以完成特定功能的SQL语句集,经编译后存储在数据库中 statement语句(DDL.DML.导出及管理语句等).异常处理.流程控制二.创建存储过程 系统做语句分析,如果没有 ...

  9. bzoj5108: [CodePlus2017]可做题

    Description qmqmqm希望给sublinekelzrip出一道可做题.于是他想到了这么一道题目:给一个长度为n的非负整数序列ai,你需 要计算其异或前缀和bi,满足条件b1=a1,bi= ...

  10. C# 6.0:Expression – Bodied Methods

    Expression-bodied 方法是C# 6.0 中另一个能简化代码的特性.我们已经对lambda表达式将funciton和delegation关联起来的这种用法很熟悉了.Expression- ...