原文链接:https://blog.csdn.net/u014493323/article/details/82921740

虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

学习jvm的人,基本都阅读过上面这段话,这里讲的是动态年龄的判定。对于动态的判定的条件就是相同年龄所有对象大小的总和大于Survivor空间的一半,然后算出的年龄要和MaxTenuringThreshold的值进行比较,以此保证MaxTenuringThreshold设置太大(默认15),导致对象无法晋升。

问题的提出
场景假设
如果说非得相同年龄所有对象大小总和大于Survivor空间的一半才能晋升。我们看下面的场景

MaxTenuringThreshold为15
年龄1的对象占用了33%
年龄2的对象占用33%
年龄3的对象占用34%。
开始推论
按照晋升的标准。首先年龄不满足MaxTenuringThreshold,不会晋升。
每个年龄的对象都不满足50%。,不会晋升。
得到假设结论
Survivor都占用了100%了,但是对象就不晋升。导致老年代明明有空间,但是对象就停留在年轻代。但这个结论似乎与jvm的表现不符合,只要老年代有空间,最后还会晋升的。

问题的解答
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
//survivor_capacity是survivor空间的大小
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
size_t total = 0;
uint age = 1;
while (age < table_size) {
total += sizes[age];//sizes数组是每个年龄段对象大小
if (total > desired_survivor_size) break;
age++;
}
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
...
}

我把晋升年龄计算的代码摘出。我们来看看动态年龄的计算。代码中有一个TargetSurvivorRatio的值。

-XX:TargetSurvivorRatio 目标存活率,默认为50%

通过这个比率来计算一个期望值,desired_survivor_size 。
然后用一个total计数器,累加每个年龄段对象大小的总和。
当total大于desired_survivor_size 停止。
然后用当前age和MaxTenuringThreshold 对比找出最小值作为结果
总体表征就是,年龄从小到大进行累加,当加入某个年龄段后,累加和超过survivor区域*TargetSurvivorRatio的时候,就从这个年龄段网上的年龄的对象进行晋升。

再次推演
还是上面的场景。 年龄1的占用了33%,年龄2的占用了33%,累加和超过默认的TargetSurvivorRatio(50%),年龄2和年龄3的对象都要晋升。

小结
动态对象年龄判断,主要是被TargetSurvivorRatio这个参数来控制。而且算的是年龄从小到大的累加和,而不是某个年龄段对象的大小。看完后先记住这个参数吧TargetSurvivorRatio,虽然你以后基本不会调整他。

jvm误区--动态对象年龄判定的更多相关文章

  1. JVM 垃圾回收机制( 一) 回收对象的判定

    关于JVM 的垃圾回收机制,我们一般都没过多深入,因为JAVA 和 C++ 的一个很大区别就是,JAVA 帮我们做了垃圾回收,而不用像C++ 那么样手动进行回收,当然任何自动的东西都存在一定弊端,比如 ...

  2. JVM 中的对象及引用

    JVM中对象的创建过程 对象的内存分配 虚拟机遇到一条 new 指令时,首先检查是否被类加载器加载,如果没有,那必须先执行相应的类加载过程. 类加载就是把 class 加载到 JVM 的运行时数据区的 ...

  3. JVM中的对象

    虚拟机中的对象 对象的分配 虚拟机遇到一条new指令时:根据new的参数是否能在常量池中定位到一个类的符号引用,如果没有,说明还未定义该类,抛出ClassNotFoundException: 1)检查 ...

  4. JVM GC之对象生死

    1.简述 在Java内存运行时区域的各个部分中,程序计数器.虚拟机栈.本地方法栈3个区域随着线程而生,随着线程而亡.栈中的栈帧随着方法的进入和退出而有条不紊的进行着入栈和出栈操作. 每个栈帧需要分配多 ...

  5. JVM如何判断对象能否被回收

    •写在前面说起Java和C++,很容易想到让人疯狂的指针,Java使用了内存动态分配和垃圾回收技术,让我们从C++的各种指针问题中摆脱出来,更加专心于业务逻辑,不过如果我们需要深入了解java的JVM ...

  6. JVM的艺术-对象创建与内存分配机制深度剖析

    JVM的艺术-对象创建与内存分配机制深度剖析 引言 本章将介绍jvm的对象创建与内存分配.彻底带你了解jvm的创建过程以及内存分配的原理和区域,以及包含的内容. 对象的创建 类加载的过程 固定的类加载 ...

  7. JVM学习之对象的状态

    堆中存放着几乎所有的对象实例,垃圾收集器在堆堆进行回收前,首先要确定这些对象哪些还“活着”,哪些已经“死去”.方法有如下两种: (1)引用计数法 算法思想:为对象添加一个引用计数器,每当有一个地方引用 ...

  8. JVM垃圾收集器&对象的引用回收

    1.介绍垃圾收集器 垃圾收集器(Garbage Collection,GC)就是用于回收方法区和堆区,其他程序计数器.虚拟机栈.本地方法栈这3个区域都是随线程而生,随线程而灭,栈中的栈帧会随着方法的进 ...

  9. 【JVM】java对象

    一.对象内存布局 对象在内存中存储可分为3块区域:对象头,实例数据,对齐填充 1.对象头 对象头包含两部分内容. 第一部分:存储对象自身的运行时数据,哈希吗(hashCode),GC分代年龄,锁状态标 ...

随机推荐

  1. LOJ6071. 「2017 山东一轮集训 Day5」字符串 [SAM]

    LOJ 思路 这种计数题显然是要先把每一个合法的串用唯一的方法表示出来.(我连这都没想到真是无可救药了) 如何唯一?容易想到把前缀尽可能多地在第一个串填掉,然后填第二个,第三个-- 如何做到这样?可以 ...

  2. (5)Go数组

    数组 数组是同一种数据类型元素的集合. 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化. 基本语法: // 定义一个长度为3元素类型为int的数组a var a [3] ...

  3. Django基础(2)-如何安装特定版本的Django项目

    Django1.0版本和2.0版本的差异较大,这里jacky更常用的Django的1.9.8的版本,本小节jacky将给大家分享如何用Pycharm创建1.9.8版本的项目 (一)使用Pycharm配 ...

  4. element ui的table的头部自定义

    <el-table-column label="级别" min-width="120" prop="clueLevel" align= ...

  5. Git的使用(1) —— 版本库

    1. 简介 Git作为一个分布式版本控制系统,其优点是不需要一直连接远端版本库就可以使用. 故其为实现分布版本控制专门设计了一整套的存储区间和语句,用来实现. (1) 本地版本库:建立在本机磁盘上的文 ...

  6. fdconnection自动重连

    fdconnection自动重连 1)设置 FDConnection1.ResourceOptions.AutoReconnect := True; 控制自动连接的恢复. 使用AutoReconnec ...

  7. linux cat 文件编码

    test.log是utf-16的编码 cat test.log会报错 但是我们可以cat的时候指定编码格式 iconv -f 文件编码 -t 终端编码 input.log iconv -f utf-1 ...

  8. 微信小程序wx.uploadFile的两个坑

    -- setImage:function(e){ var _this = this //坑1 wx.chooseImage({ count: , sizeType: ['original', 'com ...

  9. python监控rabbitmq的消息队列数量

    [root@localhost chen]# cat b.py #!/usr/bin/python # -*- coding: UTF-8 -*- import json,time import re ...

  10. flutter中的网络请求和下拉刷新上拉加载,toast的案例

    添加依赖 pull_to_refresh: ^1.5.6 dio: ^2.1.0 fluttertoast: ^3.0.1 DioUtil import 'package:dio/dio.dart'; ...