关于这一段代码 有几个不是让人很理解的地方,我一一说来。

1.Desired survivor size 524288 bytes

  关于这个512KB空间是怎么来的,JVM有这样一个参数:

  -XX:TargetSurvivorRatio:目标存活率,默认为50%,表明所有age的survivor space对象的大小如果超过Desired survivor size,则重新计算threshold,以age和MaxTenuringThreshold的最小值为准,否则以MaxTenuringThreshold为准.

  简单的说,如果要分配的Survivor空间是1M那么,desired survivor size 就是512KB,这个大小影响的是Tenuring Threshold参数

  当你试图放入800KB的对象是,Survivor from是运行你放入的,但是Tenuring Threshold大小会变成1(就算你之前是15,这里也会动态改成1),即下次GC发生时,age=1的统统放入老年代

2.Eden,Survivor from,to的关系

  对象分配空间的时候,若Eden仍有区域时,都会将对象放置Eden,持续新增对象一段时间后,Eden无法容纳时,这个时候就会发生一次Minor GC。

  当发生Minor GC时,会将Eden和 Survivor from中的幸存对象存放在Survivor to中,同时这些对象的age+1。

  若Survivor to无法容纳幸存对象,就将无法容纳的对象放置在永久带中。

  当GC时,存在对象的age=Tenuring Threshold时,不管Survivor to是否空间足够,都将他们放入永久代。

发生GC的前提,放入对象时空间不够,放入对象后空间占用完毕。


这段例子中,当XX:MaxTenuringThreshold=1时

a1 = 0.25M,a2=4M;

分配a3=4M时,Eden无法容纳4M的对象了,发起Minor GC,此时a1,a2 age=1,

这个时候,Survivor最大容量1M,无法同时容纳存活的4.5M a1,a2

虚拟机将4M的a2放入老年代,同时将0.25M的a1放入Survivor to中,此时空间分布Eden(0M),Survivor from(0.25M),Old(4M)

放入4M的a3,此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)

a3=null;只是说明了a3无引用,但是数组空间仍然存在,只是提示jvm我下次可以被回收了

a3=4M,又分配了4M的空间,这个时候Eden 4+4=8M 已经满了,触发一次GC(这时,jvm会清理age=1的对象,a1,a2被放在了老年代)

发现之前创建的4M数组没有GC Root相关联,而且不符合自救规则,回收。

此时空间分布Eden(4M),Survivor from(0M),Old(4.25M)

/**
* VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:+PrintTenuringDistribution
*
*/
@SuppressWarnings("unused")
public static void testTenuringThreshold() {
byte[] allocation1, allocation2, allocation3;
allocation1 = new byte[_1MB / 4]; //262144 什么时候进入老年代决定于XX:MaxTenuringThreshold设置
allocation2 = new byte[4 * _1MB]; //
allocation3 = new byte[4 * _1MB];
allocation3 = null;
allocation3 = new byte[4 * _1MB];
    /**
*
* XX:MaxTenuringThreshold=1
[GC [DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age 1: 418144 bytes, 418144 total
: 4695K->408K(9216K), 0.0054252 secs] 4695K->4504K(19456K), 0.0054708 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC [DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age 1: 136 bytes, 136 total
: 4668K->0K(9216K), 0.0013601 secs] 8764K->4504K(19456K), 0.0013867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 4260K [0x32750000, 0x33150000, 0x33150000)
eden space 8192K, 52% used [0x32750000, 0x32b78fe0, 0x32f50000)
from space 1024K, 0% used [0x32f50000, 0x32f50088, 0x33050000)
to space 1024K, 0% used [0x33050000, 0x33050000, 0x33150000)
tenured generation total 10240K, used 4504K [0x33150000, 0x33b50000, 0x33b50000)
the space 10240K, 43% used [0x33150000, 0x335b60a0, 0x335b6200, 0x33b50000)
compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
the space 12288K, 3% used [0x33b50000, 0x33bae5c0, 0x33bae600, 0x34750000)
ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
*/
}

这段例子中,当XX:MaxTenuringThreshold=8时

a1 = 0.25M,a2=4M;

分配a3=4M时,Eden无法容纳4M的对象了,发起Minor GC

这个时候,Survivor最大容量1M,无法同时容纳存活的4.5M a1,a2

虚拟将4M的a2放入老年代,同时将0.25M的a1放入Survivor to中,此时空间分布Eden(0M),Survivor from(0.25M),Old(4M)

放入3M的a3,此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)

a3=null;只是说明了a3无引用,但是数组空间仍然存在,只是提示jvm我下次可以被回收了

a3=4M,又分配了4M的空间,这个时候Eden 4+4=8M 已经满了,触发一次GC

发现之前创建的4M数组没有GC Root相关联,而且不符合自救规则,回收。

此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)

/**
*
* XX:MaxTenuringThreshold =8
[GC [DefNew
Desired survivor size 524288 bytes, new threshold 8 (max 8)
- age 1: 418144 bytes, 418144 total
: 4695K->408K(9216K), 0.0036693 secs] 4695K->4504K(19456K), 0.0036983 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC [DefNew
Desired survivor size 524288 bytes, new threshold 8 (max 8)
- age 1: 136 bytes, 136 total
- age 2: 417936 bytes, 418072 total
: 4668K->408K(9216K), 0.0010034 secs] 8764K->4504K(19456K), 0.0010296 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 4668K [0x32750000, 0x33150000, 0x33150000)
eden space 8192K, 52% used [0x32750000, 0x32b78fe0, 0x32f50000)
from space 1024K, 39% used [0x32f50000, 0x32fb6118, 0x33050000)
to space 1024K, 0% used [0x33050000, 0x33050000, 0x33150000)
tenured generation total 10240K, used 4096K [0x33150000, 0x33b50000, 0x33b50000)
the space 10240K, 40% used [0x33150000, 0x33550010, 0x33550200, 0x33b50000)
compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
the space 12288K, 3% used [0x33b50000, 0x33bae5b8, 0x33bae600, 0x34750000)
ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
*/

读《深入理解jvm虚拟机》之长期存活对象进入老年代,有感!!!!的更多相关文章

  1. 推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)

    欢迎一起学习 <提升能力,涨薪可待篇> <面试知识,工作可待篇 > <实战演练,拒绝996篇 > 欢迎关注我博客 也欢迎关注公 众 号[Ccww笔记],原创技术文章 ...

  2. 深入理解JVM虚拟机10:JVM常用参数以及调优实践

    转自http://www.rowkey.me/blog/2016/11/02/java-profile/?hmsr=toutiao.io&utm_medium=toutiao.io&u ...

  3. 深入理解JVM虚拟机3:垃圾回收器详解

    JVM GC基本原理与GC算法 Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Java深受大家欢迎的众多特性之一,能够帮助程 ...

  4. 《深入理解JVM虚拟机》读书笔记

    前言:<深入理解JVM虚拟机>是JAVA的经典著作之一,因为内容更偏向底层,所以之前一直没有好好的阅读过.最近因为刚好有空,又有了新目标.所以打算和<构架师的12项修炼>一起看 ...

  5. 进入JVM的世界:《深入理解JVM虚拟机》-- 思维导图

    进入JVM的世界:<深入理解JVM虚拟机>-- 思维导图 之前一直都是零零散散的看了些JVM的知识,心想这样不行啊!于是便抽空看了一下这本神书,阅罢,醍醐灌顶.豁然开朗.真正的是知其然,更 ...

  6. Java工程师学习指南第6部分:深入理解JVM虚拟机

    本文整理了微信公众号[Java技术江湖]发表和转载过的JVM虚拟机相关优质文章,想看到更多Java技术文章,就赶紧关注本公众号吧吧. JVM原理分析,看了都说好 JVM 深入学习:Java 解析 Cl ...

  7. 深入理解JVM虚拟机11:Java内存异常原理与实践

    本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...

  8. 深入理解JVM虚拟机1:JVM内存的结构与消失的永久代

    本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutori ...

  9. JVM中的堆的新生代、老年代、永久代详解

    JVM中的堆一般分为三大部分:新生代.老年代.永久代,其大致的占比如下:  一.新生代 新生代主要用来存放新生的对象.一般占据堆空间的1/3.在新生代中,保存着大量的刚刚创建的对象,但是大部分的对象都 ...

随机推荐

  1. asp.net MVC 4.0 Controller回顾——ModelBinding实现过程

    以DefaultModelBinder为例 为简单模型绑定(BindSimpleModel)和复杂模型绑定(BindComplexModel) public virtual object BindMo ...

  2. 50个必备的jQuery代码段

    本文会给你们展示50个jquery代码片段,这些代码能够给你的javascript项目提供帮助.其中的一些代码段是从jQuery1.4.2才开始支持的做法,另一些则是真正有用的函数或方法,他们能够帮助 ...

  3. (转载)C#中的lock关键字

    lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.这是通过在代码块运行期间为给定对象获取互斥锁来实现的. 先来看看执行过程,代码示例如下: 假设线程A先执行,线程B稍微慢一点.线程A执 ...

  4. 兼容ie8的圆形进度条

    主要是利用html5中的svg 画出圆形进度条 并且兼容ie8 https://github.com/GainLoss/Circular-progress-bar

  5. windows phone 8.0 的网络图片异步加载方案

    买了一本林政的8.1UI的书,看到一个使用弱引用对像来解决图片缓存的问题,刚好自已写的应用也遇到这个问题,于是小改动了一下代码,搬到了8.0版本来使用,代码由 zhxilin℃+ 大神提供了部分解决代 ...

  6. 前台使用load一个集合后台接受的方法

    前台: var imageCaseList = []; }; imageCaseList.push(data); $('#showData').load(url, { querys: imageCas ...

  7. UVA 215 Spreadsheet Calculator (模拟)

    模拟题.每个单元格有表达式就dfs,如果有环那么就不能解析,可能会重复访问到不能解析的单元格,丢set里或者数组判下重复. 这种题首先框架要对,变量名不要取的太乱,细节比较多,知道的库函数越多越容易写 ...

  8. 2017.12.22 Java序列化中你不知道的事(一)

    Java 序列化简介 Java 对象序列化是 JDK 1.1 中引入的一组开创性特性之一,用于作为一种将 Java 对象的状态转换为字节数组,以便存储或传输的机制,以后,仍可以将字节数组转换回 Jav ...

  9. 解决ssh登录慢,等待时间长的问题

    有时候在ssh远程登录到其他主机上时发现登录时间太长,经过亲自测试,发现主要有两个问题会导致ssh登录慢: 1.使用了dns反查,这样的话当ssh某个IP时,系统会试图通过DNS反查相对应的域名,如果 ...

  10. 有关a++,++a的基础问题

    今天跟朋友讨论java的赋值与自增问题 @Test public void test2() { int a = 5; int b = a++; System.out.println("a = ...