YGC前后新生代是否变大分析详解

问题描述

我们都知道gc是为了释放内存,但是你是否碰到过ygc前后新生代反增不减的情况呢?gc日志效果类似下面的:

2016-05-18T15:06:13.011+0800: [GC [ParNew (promotion failed): 636088K->690555K(707840K), 0.2958900 secs][CMS: 1019739K->1019733K(1310720K), 2.6208600 secs] 1655820K->1655820K(2018560K), [CMS Perm : 205486K->205486K(262144K)], 2.9174390 secs] [Times: user=3.74 sys=0.01, real=2.91 secs]

从上面的gc日志来看,我们新生代使用的是ParNew,而老生代用的是CMS GC,我们注意到ParNew的效果是新生代从636088K新增到了690555K,这是什么情况?

原理分析

要解释这个问题,我们先要弄清楚YGC的过程,parNew是新生代的gc算法,简单来说从gc roots开始扫描对象,当扫到一个只要是属于新生代的对象就将其挪到to space,但是老的对象还不会做释放,直到gc完成之后再看是否释放老的对象(比如说上面我们看到了promotion failed的关键字,意味着晋升失败了,也就是说to和old都装不下新生代晋升来的对象,那么在这种情况下其实是不会对eden和from里的老对象做释放的,尽管to space里已经可能存在一份副本了),但是在gc前后不管是否晋升成功,都会对from space和to space做一个对换,也就是原来的from变成to,原来的to变成from,再来看看打印gc前后内存变化的代码

void GenCollectedHeap::print_heap_change(size_t prev_used) const {
  if (PrintGCDetails && Verbose) {
    gclog_or_tty->print(" "  SIZE_FORMAT
                        "->" SIZE_FORMAT
                        "("  SIZE_FORMAT ")",
                        prev_used, used(), capacity());
  } else {
    gclog_or_tty->print(" "  SIZE_FORMAT "K"
                        "->" SIZE_FORMAT "K"
                        "("  SIZE_FORMAT "K)",
                        prev_used / K, used() / K, capacity() / K);
  }
}

size_t GenCollectedHeap::used() const {
  size_t res = 0;
  for (int i = 0; i < _n_gens; i++) {
    res += _gens[i]->used();
  }
  return res;
}

size_t DefNewGeneration::used() const {
  return eden()->used()
       + from()->used();      // to() is only used during scavenge
}

从上面代码我们知道,gc之后的内存情况是used()方法返回的,其中新生代的used方法返回的是eden+from的内存,同样的上面的prev_used也是这么计算的,只是发生在gc之前,这样一来,根据我上面提到的情况,在gc之后不管是否成功都会做一次from和to的swap,那么gc之前新生代的使用大小,其实是gc之前eden+from的使用大小,而gc之后的新生代的使用大小,其实是eden+原来的to现在是使用的大小,原来的to现在使用的大小其实就是在gc过程中将eden和from拷贝过来的对象所占的大小。

综上分析你应该知道为什么会出现这种情况了,其实是一种特殊情况,只有在出现promotion failed的情况下才会发生这样的情况,因为在这个情况下存在to里新增对象,而from和eden不会变化的情况

以上就是YGC前后新生代是否变大分析详解的详细内容,更多关于YGC前后新生代是否变的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java虚拟机GC日志分析

    本文研究的主要是Java虚拟机中gc日志的理解问题,具体如下. 一.日志分析 理解GC日志是处理Java虚拟机内存问题的基本技能. 通过在java命令种加入参数来指定对应的gc类型,打印gc日志信息并输出至文件等策略. 1.编写java代码 public class ReferenceCountingGC { public Object instance = null; private static final int ONE_MB = 1024 * 1024; private byte[] b

  • 图解JVM垃圾内存回收算法

    前言 首先,我们要讲的是JVM的垃圾回收机制,我默认准备阅读本篇的人都知道以下两点: JVM是做什么的 Java堆是什么 因为我们即将要讲的就是发生在JVM的Java堆上的垃圾回收,为了突出核心,其他的一些与本篇不太相关的东西我就一笔略过了 众所周知,Java堆上保存着对象的实例,而Java堆的大小是有限的,所以我们只能把一些已经用完的,无法再使用的垃圾对象从内存中释放掉,就像JVM帮助我们手动在代码中添加一条类似于C++的free语句的行为 然而这些垃圾对象是怎么回收的,现在不知道没关系,我们

  • 详解JVM 运行时内存使用情况监控

    java 语言, 开发者不能直接控制程序运行内存, 对象的创建都是由类加载器一步步解析, 执行与生成与内存区域中的; 并且jvm有自己的垃圾回收器对内存区域管理, 回收; 但是我们已经可以通过一些工具来在程序运行时查看对应的jvm内存使用情况, 帮助更好的分析与优化我们的代码; 注: 查看系统里java进程信息 // 查看当前机器上所有运行的java进程名称与pid(进程编号) jps -l // 显示指定的jvm进程所有的属性设置和配置参数 jinfo pid 1 . jmap : 内存占用情

  • YGC前后新生代是否变大分析详解

    问题描述 我们都知道gc是为了释放内存,但是你是否碰到过ygc前后新生代反增不减的情况呢?gc日志效果类似下面的: 2016-05-18T15:06:13.011+0800: [GC [ParNew (promotion failed): 636088K->690555K(707840K), 0.2958900 secs][CMS: 1019739K->1019733K(1310720K), 2.6208600 secs] 1655820K->1655820K(2018560K), [C

  • jvm垃圾回收之GC调优工具分析详解

    进行GC性能调优时, 需要明确了解, 当前的GC行为对系统和用户有多大的影响.有多种监控GC的工具和方法, 本章将逐一介绍常用的工具. JVM 在程序执行的过程中, 提供了GC行为的原生数据.那么, 我们就可以利用这些原生数据来生成各种报告.原生数据(raw data) 包括: 各个内存池的当前使用情况, 各个内存池的总容量, 每次GC暂停的持续时间, GC暂停在各个阶段的持续时间. 可以通过这些数据算出各种指标, 例如: 程序的内存分配率, 提升率等等.本章主要介绍如何获取原生数据. 后续的章

  • java面向对象设计原则之迪米特法则分析详解

    目录 概念 使用 拓展 概念 迪米特法则解决类与类之间耦合度问题,如果类A调用了B类的某一个方法,则这两个类就形成了一种紧耦合的方式,当B类这个方法发生变化时,一定会影响A类的执行结果.迪米特法则要求每一个类尽可能少的与其他类发生关系,也就是尽可能少的让其他类发生变化时,对其代码的执行结果产生的影响降到最低. 典型情况:A类调用B类的方法,B类和C类是一种关联关系,如果A类通过B类所持有的C类对象直接调用C类的方法,则A类和C类同时拥有强耦合的关系.代码如下: public class B {

  • Android 美食大转盘详解流程

    目录 效果视频 前言 美食大转盘 初始化SurfaceView 测量 绘制 绘制盘块 开始旋转转盘 停止旋转转盘 自定义转盘等份 控件引用 沉浸式体验 效果图 Reveal Animator 效果视频 自定义转盘代码 XML布局代码 Activity代码 代码下载地址 效果视频 前言 你还在为明天吃什么而烦恼嘛 美食大赏帮你解决选择困难症 帮你做出最佳的选择 做吃货,我们是认真的 美食大转盘 本示例使用SurfaceView绘制而成,接下来逐步分析, 文末会贴出全部代码``文末会贴出全部代码``

  • Java逃逸分析详解及代码示例

    概念引入 我们都知道,Java 创建的对象都是被分配到堆内存上,但是事实并不是这么绝对,通过对Java对象分配的过程分析,可以知道有两个地方会导致Java中创建出来的对象并一定分别在所认为的堆上.这两个点分别是Java中的逃逸分析和TLAB(Thread Local Allocation Buffer)线程私有的缓存区. 基本概念介绍 逃逸分析,是一种可以有效减少Java程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法.通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的

  • Tornado 多进程实现分析详解

    引子 Tornado 是一个网络异步的的web开发框架, 并且可以利用多进程进行提高效率, 下面是创建一个多进程 tornado 程序的例子. #!/usr/bin/env python # -*- coding:utf-8 -*- import os import time import tornado.web import tornado.httpserver import tornado.ioloop import tornado.netutil import tornado.proces

  • Android WindowManger的层级分析详解

    目录 一. Window 分类 二. Window层级 (1)应用程序窗口: (2)子窗口: (3)系统窗口: (三)如何真正查看 Window 的优先级 (四) 层级高低具体分析(对比Toast以及软键盘) (五)如何定制系统层级 一. Window 分类 应用 Window(ApplicationWindow: 对应一个 Acitivity) 子 Window    (SubWindow:不能单独存在,需要依附在特定的父 Window 中,比如常见的一些 Dialog 就是一个子 Windo

  • 汇编语言教程文件后缀大小写S区别分析详解

    目录 一.大小写后缀的区别 二.编译的相关流程 1.预处理器 2.编译阶段 3.汇编阶段 4.链接阶段 一.大小写后缀的区别 .s     汇编语言源程序;汇编 .S     汇编语言源程序;预处理,汇编 小写的s文件,在后期阶段不在进行预处理操作,所以我们不能在这里面写预处理的语句在里面 大写的S文件,还会进行预处理.汇编等操作,所以我们可以在这里面加入预处理的命令 二.编译的相关流程 预处理(Pre-Processing)-->编译(Compiling)-->汇编(Assembling)-

  • python机器学习算法与数据降维分析详解

    目录 一.数据降维 1.特征选择 2.主成分分析(PCA) 3.降维方法使用流程 二.机器学习开发流程 1.机器学习算法分类 2.机器学习开发流程 三.转换器与估计器 1.转换器 2.估计器 一.数据降维 机器学习中的维度就是特征的数量,降维即减少特征数量.降维方式有:特征选择.主成分分析. 1.特征选择 当出现以下情况时,可选择该方式降维: ①冗余:部分特征的相关度高,容易消耗计算性能 ②噪声:部分特征对预测结果有影响 特征选择主要方法:过滤式(VarianceThreshold).嵌入式(正

  • MySql存储过程循环的使用分析详解

    目录 简介 场景描述 解决方案 案例 总结 简介 每一门数据库语言语法都基本相似,但是对于他们各自的一些特性(函数.存储过程等)的用法就不大相同了,就好比Oracle与Mysql存储过程写起来就很多不同的地方,在这里主要是跟大家分享一下MySql存储过程中使用游标循环的处理方法. 场景描述 我们举一个简单的场景,首先我们可能会有这样一种情况,考试成绩表(t_achievement)有一堆的sql脚本处理,需要依赖另一个学生表(t_student)数据对部分学生做考试成绩汇总记录到成绩汇总表(t_

随机推荐