JVM学习笔记——垃圾回收篇( 八 )

JDK 8u40 并发标记类卸载当所有的类都经过并发标记后,就会直到哪些类不再被使用
这时如果一个类加载器的所有类都不再使用时,我们就可以卸载它所加载的所有类
JDK 8u60 回收巨型对象首先我们介绍一下巨型对象的定义:

  • 一个对象大于 region 的一半时,称之为巨型对象
    然后我们再来介绍G1对巨型对象的处理方法:
  • 回收时被优先考虑
  • G1 不会对巨型对象进行拷贝
  • G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为0 的巨型对象就可以在新生代垃圾回收时处理掉
垃圾回收调优本小节将会介绍垃圾回收的调优机制
基本调优概念我们进行调优需要掌握的基本知识:
  • 掌握相关工具使用
  • 掌握基本的空间调整
  • 掌握GC相关的VM参数
  • 明白调优并非固定公式,而是需要结合应用,环境
我们调优的领域并非只有垃圾回收,但是这个部分的调优确实会给项目带来很大的速率优化,此外还有其他方法的调优:
  • IO调优
  • 锁竞争调优
  • CPU占用调优
此外我们需要确定调优的目标:
  • 是为了保证低延迟还是为了保证高吞吐量
最快的GC是不发生GC首先我们需要明白GC是花费时间的,如果我们能够控制好内存保证不发生GC,那么才是最快的
如果我们频繁发生GC操作,那么我们就需要先进行自我反思:
  1. 存放的数据是否过多?
/*例如我们是否设置了相同元素筛选?错误账号禁止缓存?*/
  1. 数据表示是否臃肿?
/*例如我们调取数据时是否只调取了我们所需数据还是全盘托出?例如我们选择数据类型时是否是以最低标准为要求,数据库能采用tiny不要使用int*/
  1. 是否存在内存泄露?
/*例如我们是否设置缓存数据时采用了Static形式的Map并不断存储数据?*/新生代调优首先我们先来回顾一下新生代的优点:
  • 所有的new操作的内存分配十分廉价:直接new出来存放在伊甸区即可
  • 死亡对象的回收代价为零:我们直接采用复制将幸存内存复制出来即可,其他垃圾回收部分不用过问
  • 大部分对象都是垃圾:我们实际上幸存下来的内存数据是小部分数据,所以大部分都是垃圾
  • 垃圾回收时间相对短:Minor GC的时间远低于Full GC
那么我们该怎么进行调优呢:
  • 最简单的方法就是适当扩大新生代空间即可
  • 新生代不易太小:如果新生代过小就会导致不断发生minor GC浪费时间,且幸存区过小导致无用数据都存入老年代
  • 新生代不易太大:如果新生代过大相对老年代空间变小,容易发生Full GC,Full GC的运行时间过长
那么官方认可的新生代大小为多少:
  • 新生代能容纳所有[并发量*(请求-响应)]的数据
新生代幸存区调优首先我们需要直到新生代幸存区存放的数据主要分为两部分:
  • 当前活跃对象:并不应该晋级到老年代,只是目前阶段需要使用的内存数据
  • 需要晋升对象:我们一直使用的内存数据,需要传递到老年代
首先我们需要保证具有一定的幸存区大小:
  • 如果幸存区过小,就会导致幸存区数据提前进入到老年代
  • 但如果是当前活跃对象进入到老年代,既不能发挥作用,并且也难以排出老年代
其次我们需要控制晋升标准:
  • 设置一定规格的晋升标准,防止部分当前活跃对象进入到老年代,理由同上
老年代调优最后我们介绍一下老年代调优,我们这里以CMS为例:

经验总结扩展阅读