1、G1 垃圾回收器

  G1 能更少的 "Stop the World" ,能同时对新生代老年代进行垃圾回收。

  G1 将 Java 堆内存拆分为多个大小相等的 Region,并且新生代和老年代只是逻辑上的概念。

  最大的特点:设置一个垃圾回收的预期停顿时间。可以让 G1 垃圾回收器保证达到开发人员手动设置的 "Stop the World" 的时间。

  G1 对垃圾回收导致的系统停顿可控:追踪每个 Region 里的回收价值。就是清楚每个 Region 里的对象多少是垃圾,如果对该 Region 进行垃圾回收,需要耗费多少时间,回收多少垃圾对象。

  停顿时间参数: -XX:MaxGCPauseMills,默认200ms。

  核心思想:设定了垃圾回收的预期停顿时间后,G1 尽量控制在设置的时间范围内,最少回收时间,回收更多的垃圾。

  JVM 最多有2048个 Region,Region 的大小必须是2的倍数。Region 新生代和老年代占比其实是动态变化的,新生代初始默认5%,最大默认60%。

  触发垃圾回收,还是 Eden 区占满了对象。除了停顿时间是预设的,其垃圾回收过程是和新生代垃圾回收过程 PerNew一样。

  对象从新生代进入老年代,也是和 CMS 垃圾回收器的机制相同,除了大对象。因为会专门分配 Region 来存大对象。(一个对象的大小超过一个 Region 内存的50%)

  混合回收:前三步操作和 CMS 回收相似。只有最后一步是混合回收,多次停顿回收,复制 region,并且清除对象。Full GC 失败也和 CMS 回收相相似,变为单线程回收,并Stop the World。

  在老年代占内存的45%开始混合回收 MixedGC,并且也会回收大对象。

  小总结:一些负载很低的系统,JVM 本身是没什么必要调优的。没有复杂度和高负载的系统,JVM 一般很少会出现问题。

  适合 G1 回收器的场景:追求低延迟的场景,或者大内存机器。(内存太大,如果常规垃圾回收器,就会一次性回收很多垃圾,停顿时间过长)

2、JVM 调优实战

  学会看 GC 日志,与分析 GC 日志。

  当 Survivor 区域存放不下 Eden 区存活的对象时,Eden 区存活的对象,一部分会移动到老年代,一部分会移动到 Survivor 区。

  通过 jstat -gc PID de 命令,可以分析出一些数据:

  新生代增长的速率(观察 eden 区的被占用内存的变化);

  YGC 触发的频率(多久触发一次 YGC);

  YGC 的耗时;

  每次 YGC 后有多少对象存活下来(发生YGC 后看 survivor 区新增对象的大小);

  每次 YGC 过后有多少对象进入老年代(发生 YGC 后看老年代新增对象的大小);

  老年代增长的速率;

  FGC 触发频率;

  FGC 的耗时。

3、极高QPS怎么优化 JVM

  思路:

  用 jstat 分析一下 JVM 运行情况,判断每次 YGC 后存活对象有多少,增加 Survivor 区的内存,避免对象快速进入老年代。

  但是老年代还是会发生 FullGC,这时就需要整理老年代的内存碎片。

  分析:

  1)、极高QPS,则会迅速产生对象,迅速占满 Eden 区,则进行 YGC。而进行 YGC 的时候,同时又有很多请求产生对象,则会有很多对象在 YGC 的时候存活。

  2)、如果存活的对象很多,则可能导致 Surivivor 区装不下存活对象,就会导致对象大量进入老年代。则会频繁出发 OGC。

  3)、在 OGC 的时候,因为回收算法是标记-清理算法,则会在老年代中产生大量内存碎片。

  解决:

  1)、参数:-XX:+UserCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=5 可以把5修改为0。含义是在发生几次 FullGC 后,对老年代的内存碎片进行整理,空出大量内存空间。

  因为内存碎片还会导致 FullGC 的频率,因为内存碎片会越来越多,能放下的对象越来越少。

  2)、参数:-XX:+CMSparallellnitialMarkEnabled,这个参数会在 CMS 垃圾回收器的 初始标记 阶段开启多线程并发执行。主要是减少 Stop the world 的时间。

  3)、参数:-XX:+CMSScavengeBeforeRemark,这个参数会在 CMS 的重新标记阶段前进行一次 YGC。回收一些年轻代里没有人引用的对象,减少 CMS 在重新标记阶段扫描的对象,减少耗时。

4、JVM 的一些参数整理

  -XX:CMSInitiatingOccupancyFraction=92 和 -XX:+UseCMSInitiatingOccupancyOnly 配套使用。如果仅设置前者,CMS 垃圾回收器第一次会采用内存占老年代 92% 但是后续会根据运行时采集的数据来进行 GC 周期。设置了后者,就会每次固定在内存占老年代 92% 时进行垃圾回收。

  -XX:CMSParallellnitialMarkEnabled 表示在初始标记阶段,多线程执行以减少 STW;

  -XX:CMSScavengeBeforeRemark 表示在重新标记阶段之前,执行 MinorGC 减少重新标记的时间;

  -XX:CMSParallelRemarkEnable 表示在重新标记阶段,多线程执行以减少 STW;

5、小总结

  频繁出发 FullGC de 三种可能:

  1)、内存分配不合理,导致对象频繁进入老年代;(Survivor 过小,或者新生代过小,并且未开启空间担保规则,开启了动态年龄判断)

  2)、存在内存泄露等问题,就是内存里驻留了大量的对象塞满了老年代,导致稍微有一些对象进入老年代就触发 FullGC;

  3)、永久代里的类太多,触发了 FullGC。

JVM 理解性学习(二)的更多相关文章

  1. JVM 理解性学习(一)

    重新学习,重新理解 1.类加载过程等 验证:.class 文件加载到 JVM 里的时候,会验证下该文件是否符合 JVM 规范. 准备:给实体类分配内存空间,以及给类变量(static 修饰)分配&qu ...

  2. Quartz学习--二 Hello Quartz! 和源码分析

    Quartz学习--二  Hello Quartz! 和源码分析 三.  Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...

  3. JVM实用参数(二)参数分类和即时(JIT)编译器诊断

    JVM实用参数(二)参数分类和即时(JIT)编译器诊断 作者: PATRICK PESCHLOW     原文地址    译者:赵峰 校对:许巧辉 在这个系列的第二部分,我来介绍一下HotSpot J ...

  4. 利用Theano理解深度学习——Multilayer Perceptron

    一.多层感知机MLP 1.MLP概述 对于含有单个隐含层的多层感知机(single-hidden-layer Multi-Layer Perceptron, MLP),可以将其看成是一个特殊的Logi ...

  5. ReactJS入门学习二

    ReactJS入门学习二 阅读目录 React的背景和基本原理 理解React.render() 什么是JSX? 为什么要使用JSX? JSX的语法 如何在JSX中如何使用事件 如何在JSX中如何使用 ...

  6. Hbase深入学习(二) 安装hbase

    Hbase深入学习(二) 安装hbase This guidedescribes setup of a standalone hbase instance that uses the local fi ...

  7. JVM类加载过程学习总结

    JVM类加载过程学习总结 先不说JVM类加载的原理,先看实例: NormalTest类,包含了一个静态代码块,执行的任务就是打印一句话. /** * 在正常类加载条件下,看静态代码块是否会执行 * @ ...

  8. JVM 字节码(二)方法表详解

    JVM 字节码(二)方法表和属性表 上一节中对 ClassFile 的整体进行了五个详细的说明, 本节围绕 ClassFile 最重要的一个内容 - 方法表的 Code 属性展开 ,更多 JVM Me ...

  9. JVM 内部原理(二)— 基本概念之字节码

    JVM 内部原理(二)- 基本概念之字节码 介绍 版本:Java SE 7 每位使用 Java 的程序员都知道 Java 字节码在 Java 运行时(JRE - Java Runtime Enviro ...

随机推荐

  1. css中:如何让一个图片(不知道宽高,宽高可能比父元素div大),在父元素div内部水平垂直居中,并且不溢出父元素div,且图片不拉伸变形(可等比例缩小)?

    欢迎进入:http://www.jscwwd.com/article/list/%E5%85%A8%E9%83%A8 效果图: 不管父元素的宽高怎么变化,图片都是水平垂直居中的,并且不溢出父元素. 注 ...

  2. 第一个android App, hello world

    自以为按照教程很快就会创建自己第一个android App,没想到还是用了很长时间,中间走了很多坑,记下来,这也算自己的一个成长吧 首先按照官方的教程,新建一个工程 https://developer ...

  3. 五分钟学Java:如何学习Java面试必考的网络编程

    原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 简介 Java作为一门后端语言,对于网络编程的支持是必不可少的,但是,作为一个经常CRUD的Java工程师,很多时候都不 ...

  4. webpack,Babel,babel-loader的关系

    本文将要介绍 webpack,Babel,babel-loader 的关系.理清楚他们各自做了什么事情. 通常我们新建一个项目,会先配置webpack,然后配置babel:babel是一个编译工具,实 ...

  5. Natas14 Writeup(sql注入、sql万能密码)

    Natas14: 是一个登录页面.源码如下. if(array_key_exists("username", $_REQUEST)) { $link = mysql_connect ...

  6. iOS/macOS推荐个高效苹果开发工具, JSON 转模型代码工具,不再为复杂JSON数据写模型而烦恼,支持Swift/Objective-C,极速转换

    CCJSON 是一款运行在macOS上 JSON 转模型代码工具,不再为复杂JSON数据写模型而烦恼,可识别嵌套模型,字典/数组,支持Swift/Objective-C,操作方便,极速转换.下载 效果 ...

  7. HBU-数据库第五周作业

    第五周数据库作业 注意 MySQL的数据库名.表名.列名.别名大小写规则是这样的: 1.数据库名与表名是严格区分大小写的: 2.表的别名是严格区分大小写的: 3.列名与列的别名在所有的情况下均是忽略大 ...

  8. 测试工程师需要了解的shell变量知识

    欢迎访问个人博客 什么是变量 本地变量:手动定义的,在当前系统的某个环境下才能生效,作用范围小 普通变量: 单引号:原字符输出,变量名='变量值' ➜ shell name='tom' ➜ shell ...

  9. 采用C++实现哈夫曼树的创建并输出哈夫曼编码

    一.这篇随笔来自一道信息论的作业题,因为手动编码过于复杂,所以想到了编程解决,原题目如下图所示: 二.源代码如下: #include <iostream> #include <str ...

  10. 洛谷 P3870 [TJOI2009]开关 题解

    原题链接 前置知识: 线段树的单点.区间的修改与查询. 一看,我们需要维护两个操作: 区间取反: 区间求和. (因为区间 \(1\) 的个数,就是区间的和) 典型的 线段树 . 如果你只会线段树的 区 ...