Top Banner
JAVA 圾收集原理 @gongyin [email protected]
42

Java垃圾收集原理

Jul 11, 2015

Download

Documents

Yin Gong
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java垃圾收集原理

JAVA 圾收集原理垃 @gongyin

[email protected]

Page 2: Java垃圾收集原理
Page 3: Java垃圾收集原理

“Garbage collection (GC) is a form of automatic memory management. The garbage collector, or just collector, attempts to reclaim garbage, or memory occupied by objects that are no 

longer in use by the program ”                  - Wikipedia

Page 4: Java垃圾收集原理

自动内存管理年代

还有必要学习和了解GC ?

Page 5: Java垃圾收集原理

垃圾收集器做什么?

•释放非存活对象占据的内存空间

•管理内存,决定了内存分配机制

Page 6: Java垃圾收集原理

垃圾收集器如何做?

• 检测出垃圾对象 直接方式:引用计数

间接方式 :   追踪对象引用图

• 回收垃圾对象所占用的内存空间 直接清除 压缩 拷贝

• 必须决定什么时候进行回收

Page 7: Java垃圾收集原理

垃圾算法的基本要求

• 必须是安全的,存活数据不能被错误回收

• 应该是全面的,垃圾对象会在固定的收集周期被回收

• 应该有合理的开销,时间 / 空间 / 运行频率

• 尽可能少的内存碎片

• 应该是可扩展的,不会成为可扩展瓶颈

Page 8: Java垃圾收集原理

常用的 GC 算法和策略

• 引用计数器(渐进式)

• 标记 - 清扫垃圾收集

• 节点复制垃圾收集

• 标记 - 缩并垃圾收集

• 分代垃圾收集

• 并发垃圾收集

• 分布式垃圾收集

• 自适应动态垃圾收集

Page 9: Java垃圾收集原理

引用计数器

Pros• 实现简单,能快速判断对象是否在使用

• 交织在程序中执行,不会挂起应用

Cons• 无法处理循环引用

• 给程序执行带来额外的开销

• 与用户程序紧密的耦合

Page 10: Java垃圾收集原理

标记 - 清扫算法

Pros• 非常自然的处理环形结构

• 操纵指针没有额外的 开销

Cons• 停止 - 启动 算法, STW 问题

• 内存碎片问题

渐进复杂度正比与堆的大小

Page 11: Java垃圾收集原理

节点复制算法

Scavenger 清道夫,从垃圾中捡起有价值的并带走

Pros• 所有存活的数据都缩并的排列在一起

• 无内存碎片,能够高效的分配对象

Cons• 使用两个半区,存储容量加倍

• 重复拷贝

性能随着内存占用率提高而下降,复杂度正比于存活数据结构的大小,而不是堆的大小

Page 12: Java垃圾收集原理

标记 - 缩并算法

缩并方式

任意的 / 线性的 / 滑动的

Pros• 不需要占用额外空间

Cons• 缩并带来性能损失

渐进复杂度类似与节点复制算法

Page 13: Java垃圾收集原理

分代式垃圾收集器

Weak generational hypothesis 理论• 大部分对象都是短暂的,生命周期很短

• 只有很少的长生命对象会引用短生命对象

• 把工作集中在回收最有可能是垃圾的对象上

Pros• 不同的分代可以使用不同的算法和不同的搜集频率,能减少垃圾收集的整体开销

Cons• 如果根集合巨大

• 分代间引用 以及占位垃圾 问题

Page 14: Java垃圾收集原理

分代式垃圾收集器

• 需要合理设置 提升策略 和提升阀值

• 提升太快

Major GC 占位垃圾 和 庇护现象 程序的局部性有负面影响,工作集稀疏 增大写拦截器的开销

• 自适应提升策略 在缩短中断时间和占位垃圾之间进行折衷

• 调度策略

•隐藏在用户最不注意到时刻

• 最多垃圾时触发

Page 15: Java垃圾收集原理

渐进式和并发收集器

三色标记 已访问 \ 需重访问 \未访问

Pros• 大幅缩短垃圾收集带来的中断时间

Cons• 吞吐量,垃圾收集总耗时上升

• “ 多个读,多个写”一致性问题,需要和用户程序同步,漂浮垃圾问题

• 需提前进行收集,可能并发收集失败

Page 16: Java垃圾收集原理

自适应垃圾收集算法

• 监视服务器和应用情况,自动调整和选择合适的收集算法

• JAVA 中的 Eronomic

Page 17: Java垃圾收集原理

Java

• 基于分代策略

• 每个分代可以使用不同的垃圾收集器

Page 18: Java垃圾收集原理

Java 基于分代垃圾收集策略

Page 19: Java垃圾收集原理

Java 中如何检测垃圾对象的?

找到 GC Root 集合

• 本地变量和局部变量引用的对象

• 方法区中类静态属性引用的对象

• 方法区中常量引用的对象

• 本地方法栈中 JNI 所引用的对象

• 跨分区引用的对象,分代间引用

• 引用对象被提升

• 被重新赋值指向新生分代对象

Page 20: Java垃圾收集原理

Java 中如何检测垃圾对象的?

• 写拦截器 Write-barrier Dirty Card

JVM维护一个 dirty cards 表 每 512 byte 内存页关联到一个 dirty card 内存页发生变化,则标记 dirty page GC完成,重设 dirty card

Snapshot-at-the-beginning (SATB)  G1

Page 21: Java垃圾收集原理

Java 中如何检测垃圾对象的?

根据对象存活状态( Reachable )标记出垃圾对象

• 强引用

• 软引用( SoftReference )

• -XX:SoftRefLRUPolicyMSPerMB

• 弱引用 (WeakReference)• 可复活对象

• 被 finalize 方法复活 ( 需两遍扫描 )

• 虚引用 (PhantomReference)• 对象被回收时得到系统通知  ReferenceQueue

• 不可达对象

Page 22: Java垃圾收集原理

垃圾清扫阶段

释放被占用的垃圾

非压缩,直接释放

清道夫复制

滑动缩并

Page 23: Java垃圾收集原理

新对象分配

• 直接分配在新生代 Eden或 TLAB• TLAB thread local allocation block

• -XX:+PrintTLAB 

• -XX:+UseTLAB  -XX:+ResizeTLAB 

• -XX:TLABSize=<size>  -XX:MinTLABSize=<size> 

• 大对象和大数组直接分派在旧生代• -XX:PretenureSizeThreshold=n 

• 如果对象大于 Eden 大小

• 堆外分配• DirectByteBuffer

• Unsafe.allocateMemory

• -XX:MaxDirectMemorySize=<value>

Page 24: Java垃圾收集原理

对象提升策略

• -XX:+AlwaysTenure ,直接从新生代到旧生代

• Survivor 区域满后,其他存活对象提升

• 对象已经存活一定次数的收集周期

• –XX:MaxTenuringThreshold  

• –XX:TargetSurvivorRatio 

Page 25: Java垃圾收集原理

垃圾收集器性能度量指标

• 吞吐量 throughput没有花在GC 上的时间百分比,比如GC花了 1%的时间,那么吞吐量是

99%

• GC负载GC Overhead• 停顿时间 pause Time

• 新生代暂停时间 = 栈扫描时间+DirtyCard 扫描时间+旧生代扫描时间+ 存活对象赋值时间

• 垃圾收集器执行的频率

• 内存大小 Footprint• 敏捷性 Promptness

对象变成垃圾和此块内存可以被利用的时间

Page 26: Java垃圾收集原理

Java 提供 4种类型的 GC

• Serial Collector –XX:+UseSerialGC

• Parallel Collector –XX:+UseParallelGC 

• Parallel Compacting Collector(1.5R6)–XX:+UseParallelOldGC

• CMS Collector–XX:+UseConcMarkSweepGC

Page 27: Java垃圾收集原理

串行收集器

• STW• –XX:+UseSerialGC• 新生代使用串行GC• 旧生代和持久代也使用串行GC• 适用于小内存客户端应用

Page 28: Java垃圾收集原理

并行收集器

• STW• –XX:+UseParallelGC Parallel

• 新生代使用并行复制收集算法

• 旧生代使用并行压缩mark-sweep-compacting

• –XX:+UseParallelOldGC• –XX:ParallelGCThreads=n

Page 29: Java垃圾收集原理

并发收集器

• 过程• Initial mark ,STW, 收集GC Roots

栈 新生代对象应用旧生代对象

速度依赖于新生代存活对象的多少 – XX:CMSWaitDuration= n

• Concurrent Mark ,标记存活对象

• Concurrent pre clean,统计被改变的引用

• Remark , STW ,重新标记被改变的引用  –XX:+CMSScavengeBeforeRemark //强制新生代GC

• Concurrent sweep

• Concurrent  reset

Page 30: Java垃圾收集原理

并发收集器

• –XX:+UseConcMarkSweepGC• 不会压缩堆,不同大小碎片有各自的 free memory list• –XX:+CMSIncrementalMode

• –XX:ParallelGCThreads=n

• 何时触发

• 最好在新生代GC之后• ‑XX:+UseCMSInitiatingOccupancyOnly =

• ‑XX:+ExplicitGCInvokesConcurrent 

• 导致 Full  GC• 并行模式问题 Concurrent mode failure

正在执行 CMS ,但是没有足够的空间分配给新对象

• 提升失败问题 Promotion failure提升的对象太多,旧生代放不下

Page 31: Java垃圾收集原理

并发收集器

• 针对多核优化参数

• ‑XX:+CMSConcurrentMTEnabled 并发阶段使用多核

• ‑XX:+ConcGCThreads= 

• ‑XX:+ParallelGCThreads= 

STW阶段并行线程数目,默认 CPU数目

• ‑XX:+UseParNewGC 新生代使用并行复制算法

• 限制

• 对 CPU资源敏感

• 漂浮垃圾问题

• 内存碎片问题

‑XX:+UseCMSCompactAtFullCollection ‑XX:+CMSFullGcsBeforeCompaction =

Page 32: Java垃圾收集原理

Garbge First

G1 ( jdk16.R14 )

• 基于 标记 - 压缩算法

• 可以精准的控制暂停时间

• 将 Heap 分为多个大小的独立区域

• G1维护优先列表,检测哪个区域内存使用最快,然后仅仅收集此区域

• 清除空区域代价很小

• 复制小数量的对象很快

Page 33: Java垃圾收集原理

Young collector Old collector JVM option

Serial (DefNew) Serial Mark-Sweep-Compact -XX:+UseSerialGC

Parallel scavenge (PSYoungGen)

Serial Mark-Sweep-Compact (PSOldGen)

-XX:+UseParallelGC

Parallel scavenge (PSYoungGen)

Parallel Mark-Sweep-Compact (ParOldGen)

-XX:+UseParallelOldGC

Serial (DefNew) Concurrent Mark Sweep -XX:+UseConcMarkSweepGC-XX:-UseParNewGC

Parallel (ParNew) Concurrent Mark Sweep -XX:+UseConcMarkSweepGC-XX:-UseParNewGC

G1 -XX:+UseG1GC

GC 组合

Page 34: Java垃圾收集原理

Ergonomics

• 基于平台和操作系统自动选择collertor、 heap size 和 hotspot client or server

• 目标是提供尽可能好的性能而不需要设置太多命令参数,自动化

Page 35: Java垃圾收集原理

Behavior-based parallel

• 最大停顿时间

• -XX :MaxGCPauseMillis=n

• 最大吞吐量

• -XX :GCTimeRatio=n

• Ratio = 1/ ( 1+N )

• Default value = 1%

• 缺省优先级:先满足停顿时间,然后吞吐量,最后 footprint

Page 36: Java垃圾收集原理

一些常用配置

• 单处理器系统或小内存, 100M左右内存-XX:+UseSerialGC

•   多处理器系统,需要最大吞吐量不关心暂停时间-XX:+UseParallelGc -XX:+UseParallelOldGC

• 最小停顿时间-XX:+UseConcMarkSweepGC

• -XX:+ParNewGC, 有内存碎片,内存越大越好

  

Page 37: Java垃圾收集原理

优化原则

• Do Nothing,让 JVM 自动选择

• 不存在一个简单而普适的原则,必须充分理解系统的需求和特征

• 先measure ,在 tune• 不要过度 tune• 需要在各个指标之间进行权衡

Page 38: Java垃圾收集原理

常用监控和分析工具

• GC参数• -XX :+PrintGCDetails

• -XX:  +PrintHeapAtGC 

• -XX :+PrintGCTimeStamps

• -XX:+HeapDumpAfterFullGC

• -XX:+HeapDumpBeforeFullGC

• -XX:+HeapDumpOnOutOfMemoryError

• Jmap –histo | -heap | -permstat• Jstat• Jconsole• VisualVM• HAT : Heap Analysis Tool

Page 39: Java垃圾收集原理

References• http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html• http://java.sun.com/performance/reference/whitepapers• http://www.oracle.com/technetwork/java/faq-140837.html• http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning• http://blogs.oracle.com/jonthecollector/entry/our_collectors• http://java.sun.com/docs/hotspot/VMOptions.html

Page 40: Java垃圾收集原理

Thank you

Page 41: Java垃圾收集原理
Page 42: Java垃圾收集原理