代码改变世界

JVM内存分配和回收策略

2017-02-28 17:43  louistz  阅读(144)  评论(0编辑  收藏  举报

JVM内存
  1. 方法区(又叫非堆,运行时常量池属于方法区的一部分)
  2. 虚拟机栈
  3. 本地方法栈
  4. 程序计数器
  5. 直接内存(NIO)
PermGen to Meta Space
JDK8 HotSpot JVM中,PermGen将被完全移除,设置PermSize和MaxPermSize将会忽略并告警。类元信息将被存储在本地内存,这部分空间被称为“元空间(meta space)”. Metaspace默认不限制,可通过MaxMetaspaceSize参数设置大小。持续的元空间垃圾回收,说明存在类、类加载器导致的内存泄漏或者是大小不合适
 
 
垃圾回收
对象已死?
  1. 可达性分析(引用计数?循环引用?)
  2. GCRoots
  • 虚拟机栈引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象
  1. 引用标记次数
  2. 方法区中类的回收
  • 该类的实例都被回收
  • 加载该类的ClassLoader被回收
  • 该类对应的java.lang.Class对象没有被引用,无法再任何地方通过反射访问该类的方法
 
回收算法
  1. 标记-清除  (碎片问题)
  2. 复制算法    (回收新生代,98%朝生夕死)
  3. 标记-整理   (存活率大,复制的代价大)
  4. 分代收集     (存活少用复制,存活多用标记整理)
 
分代回收
Minor GC
  1. s1和eden区有幸存对象,s0清空
  2. s1和eden的幸存对象复制到s0, 完成后清空s1和eden
  3. 如果对象过大(-XX:PretenureSizeThreshold)或者对象存活次数(-XX:MaxTenuringThreshold)过多,直接分配到old区
  4. 或者S区中所有年龄相同的对象的大小总和超过S区空间大小的一半,那么年龄大于或者等于该年龄的对象就直接进入old区,而不用等到MaxTenuringThreshold的值

 

Major GC
    如果某次MajorGC 后,老年代无法为将要晋升到老年代的对象做担保,那么久需要执行一次MajorGC(FullGC). 一般一次MajorGC会伴生着一次MinorGC ,但这并不是必需的。(如ParallelScavenge收集器的收集策略就有直接进行MajorGC的策略选择过程)
 
 
垃圾回收器

 

 
  1. Serial  新生代,最古老最基本的,单线程。Client模式下的好选择
  2. ParNew 新生代,Serial的多线程版本。Server模式下的好选择,只有它能与CMS配合工作
  3. Parallel Scavenge 新生代,复制算法,并行多线程。目标是可控吞吐量(吞吐量=用户代码时间/(用户代码时间+GC时间))
  4. Serial Old 老年代,标记-整理算法,单线程。Client模式下使用。Server模式下:一是jdk1.5之前与Parallel Scavenge配合,二是CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。
  5. Parallel Old 老年代,Parallel scavenge的老年代版本。吞吐量优先和CPU资源敏感的场合: Parallel Scavenge + Parallel Old.
  6. CMS  老年代。目标是获取最短回收停顿时间。标记-清除算法。
 
CMS回收器介绍
运作过程
  • 初始标记 (stop the world)
  • 并发标记
  • 重新标记  (stop the world)
  • 并发清除
缺点
  • 对cpu资源敏感。 占用一部分线程,导致程序慢,总吞吐量降低。 默认 线程数= (cpu + 3)/4. 这样来看,在cpu超过4个时,占用不少于25%的cpu资源,并且随着cpu数的增加而下降。但当cpu少于4个,影响很大。 为了应付这种情况,提供了一种“增量式并发收集器 i-CMS”,但效果不好(gc和用户线程交替运行),不再提倡。
  • 无法处理浮动垃圾。可能出现“Concurrent Mode Failure” 失败而导致另一次FullGC的产生。
  • 标记-清除算法导致的空间碎片。 无法找到连续的大空间来分配对象,而出发FullGC. 参数 -XX:+UseCMSCompactAtFullCollection 参数默认开启。默认是0,只的是每次FullGC都进行碎片整理。
 
G1回收器
     暂留
 
常用垃圾回收器参数

 

 
java堆设置常用参数