【JVM】HotSpot JVM内存管理和GC策略总结
JVM的相关知识是学习java高级特性必须要去深入学习的。平时也有一些学习和实践,不过总结比较少。
今天有时间总结一下最基础的内存模型和GC策略的知识,在此记录一下。
hotspot jvm内存模型
1.内存模型
hotspot的内存模型很多地方都有类似总结,我也简单总结了一下,大概可以用下图表示:
关于几个分区的描述定义
1.线程栈:线程创建是会为每个线程创建一个线程栈,线程栈里面会为每个方法调用创建一个栈帧。主要用于保存线程的当前运行状态。
2.堆:用于存放运行时中生成的新对像。会划分成新生代和老年代。新生代里面又划分成了eden区、存活1区和存活2区。
3.永久区:方法和常量区,用于存放方法字节码元数据和各种常量。
为什么堆会划分为新生代和老年代?
基本原理:对于大部分应用,常驻对象不多。因为大部分存活寿命不长,新生代和老年代的划分有利于区分对待和缩小垃圾回收范围。(Most allocated objects are not referenced (considered live) for long, that is, they die young. Few references from older to younger objects exist.)
2.内存相关启动参数
参数 | 含义 |
-Xms | 最小堆空间 |
-Xmx | 最大堆空间 |
-Xmn | 新生代空间 |
-Xss | 线程栈空间 |
-XX:PermSize=xxx | 永久代空间 |
-XX:MaxPermSize=xxx | 最大永久代空间 |
-XX:SurviorRatio=xxx |
代表eden:s0的比例 |
-XX:NewRatio=xx | 新生代和旧生代的比例. |
-XX:MaxTenuringThreshold。 | 在新生代最大存活次数 |
hotspot 内存垃圾回收策略总结
1.内存回收策略和常见概念
常见内存回收策略可以从以下几个维度来理解:
1.1 串行&并行
串行:单线程执行内存回收工作。十分简单,无需考虑同步等问题,但耗时较长,不适合多cpu。
并行:多线程并发进行回收工作。适合多CPU,效率高。
1.2 并发& stop the world
stop the world:jvm里的应用线程会挂起,只有垃圾回收线程在工作进行垃圾清理工作。简单,无需考虑回收不干净等问题。
并发:在垃圾回收的同时,应用也在跑。保证应用的响应时间。会存在回收不干净需要二次回收的情况。
1.3 压缩&非压缩©
压缩:在进行垃圾回收后,会通过滑动,把存活对象滑动到连续的空间里,清理碎片,保证剩余的空间是连续的。
非压缩:保留碎片,不进行压缩。
copy:将存活对象移到新空间,老空间全部释放。(需要较大的内存。)
一个垃圾回收算法,可以从上面几个维度来考虑和设计,而最终产生拥有不同特性适合不同场景的垃圾回收器。
2.HotSpot JVM的YGC&FGC
YGC :对新生代堆进行GC。频率比较高,因为大部分对象的存活寿命较短,在新生代里被回收。性能耗费较小。
FGC :全堆范围的GC。默认堆空间使用到达80%(可调整)的时候会触发FGC。以我们生产环境为例,一般比较少会触发FGC,有时10天或一周左右会有一次。
3.常见GC算法和jvm参数
3.1.串行垃圾收集器
新生代和老生代因为结构划分不一样,其串行收集器算法也不一样
新生代串行收集器
采用stop the world策略,步骤大概是:先从eden区扫描,把存活的对象拷贝到to区,如果to区放不下的对象直接拷贝到old区。再从from区扫描存活对象,如果对象存活次数超过阀值的就移到老年区,其他的移到to区。做完之后from和to区概念互换(from和to只是运行时的概念,其实就对应存活1区和存活2区)。
图形的表示如下:
回收前:
回收后:
老生代串行收集器
老生代垃圾回收主要分为三个阶段 Mark-sweep-compact
Mark
:识别哪些是存活的
Sweep
: 识别垃圾,并回收
Compact
:滑动活动对象并压缩到连续空间,碎片整理 。
串行垃圾回收器在jvm client模式下是默认启动的。参数 -XX:+UseSerialGC 可以设置垃圾回收策略为串行。
3.2并行垃圾回收器
主要以下特点:
充分利用CPU
吞吐量优先
和串行一样,不过是多线程执行,缩短了stop-the-world时间。
-server模式下默认的回收器。参数 -XX:+UseParallelGC 可以设置垃圾回收策略为并行。
3.3并行压缩收集器(Parallel Compacting Collector)
只对老生代适用,新生代仍旧和并行垃圾回收器一样。
其过程大概如下:
标记阶段
,使用多线程对存在引用的对象进行并行标记。
分析阶段
,GC对各个区域进行分析,GC认为,在经过上次GC后,越左边的区域,有引用的对象密度要远远大于右边的区域。所以就从左往右分析,当某个区域的密度达到一个值的时候,就认为这是一个临界区域,所以这个临界区域左边的区域,将不会进行压缩,而右边的区域,则会进行压缩。
压缩阶段
,多各个需要压缩的区域进行并行压缩
参数-XX:+UseParallelOldGC 可以设置老生代垃圾回收策略为并行压缩。
3.4 Concurrent Mark-Sweep (CMS) Collector
主要特点
仍旧是老生代适用。
减少停顿,以响应时间为优先。
只有标记和清除,不会进行会压缩。
初始标记和清除支持和应用程序并发执行,中间还是会有一re-mark需要stop the world。
参数-XX:+UseConcMarkSweepGC 可以设置老生代垃圾回收策略为CMS。
3.5 G1垃圾收集器
是在JDK7里支持的,用于取代CMS。具体具体见: http://docs.oracle.com/javase/7/docs/technotes/guides/vm/G1.html
总结
本文的内容只是仅限于基础层面的的一些知识总结,更加深入的知识点还需要后续深入学习。
以下提供一些学习参考:
memory management whitepaper :
http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf
JVM option: http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
淘宝的blue davy的一个jmm分享: http://blog.bluedavy.com/?p=200
已有 0 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐