1,jvm内存模型
年轻代(young generation)
1,年轻代是所有新对象产生的地方,当年轻代内存空间被用完时,就会触发垃圾回收,这个叫做minor gc .年轻代划分为3个部分
Eden survivor0 survivor1 (Hotspot 中 Eden:survivor比例8:1)
老年代(old generation)
1,年老代内存包含长期存活的对象和进过多次minor gc 后依然存活下来的对象。老年代内存被占满时进行垃圾回收 叫做major gc
永久代(perm generation)
1,永久代包含了jvm需要的应用元数据,这些元数据描述了在应用里使用的类和方法,注意永久代不是Java堆内存的一部分
方法区是永久代空间的一部分,用来存储类型信息 运行时常量,静态变量,方法和构造函数代码
判断对象是否存活
1.引用计数法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
jvm 没有使用计数器算法来管理内存,其中主要原因是它很难解决对象之间相互循环引用的问题。
2.可达性分析
从GC ROOTS 开始向下搜索,搜索所走过的路径称为应用链。当一个对象到gc roots 没有任何应用链相连时,则证明此对象是不可用的。
gc 算法
1.标记-清除(Mark sweep)
首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
要点:效率不高、产生大量不连续的内存碎片
2.复制(copying)
将内存按容量划分大小相等的两块,每次只是用其中一块。当这一块的内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
要点: 效率高、 代价将内存缩小为原来的一半,持续复制存活率高的对象则导致效率降低。现在大部分虚拟机都采用这个算法进行新生代的回收。
3.标记-整理(mark compact)
标记-整理与标记-清除类似,只是后续部分不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界意外的内存。
4.分代收集算法(generational collection)
分代收集只是根据对象存活周期的不同将内存划分几块。 把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适合的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高,没有额外空间进行对它进行分配担保,就必须使用标记-清理 或者 标记-整理算法进行回收。
gc 垃圾收集器(基于Hotspot)
两个概念:
并行:指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
并发:指用户线程与垃圾收集线程同时执行,用户程序在继续运行,而垃圾收集程序运行于另一个cpu上。
Serial 收集器
参数 -XX:+UseSerialGC 它的“单线程” 不仅仅说明它只会使用一个cpu 或一条收集线程去完成垃圾收集工作,更重要的是它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。
ParNew 收集器
其实就是serial 收集器的多线程版本。新生代收集的首选 目前只有它能与cms收集器配合使用。ParNew 收集器也是使用-XX:+UseConcMarkSweepGC选项后的默认新生代收集器,也可以使用-XX:+UseParNewGC选项来强制指定。默认开启的收集线程数与CPU的数量相同,也可以使用 -XX:+ParallelGCThreads参数来限制。
Parallel 收集器
使用复制算法的收集器,并行多线程收集器,但它的目标则是达到一个可控制的吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间))
Serial old 收集器
Serial收集器的老年代版本,单线程使用“标记-整理”算法。
parallel old 收集器
是Parallel Scavenge收集器的老年代版本,使用多线程 标记-整理 算法, 吞吐量优先使用 采用 新生代 Parallel Scavenge 老年代采用parallel old。
cms 收集器
该收集器是一种以获得最短回收停顿时间为目标的收集器。基于标记-清除实现的 分4个步骤 初始标记-》并发标记-》重新标记-》并发清除
对CPU资源比较敏感,无法处理浮动垃圾,还会产生大量空间碎片
常伴随着 -XX:CMSInitiatingOccupancyFraction 参数老年代百分比时进行回收
-XX:+UseCompactAtFullCollection (默认开启)进行FullGC时开启内存碎片合并整理
-XX:CMSFullGCsBeforeCompaction 参数用于设置执行多少次不压缩的FUll GC后 跟随来一次带压缩Full GC
g1收集器
使用g1收集器时,Java堆的内存布局就与其他收集器有很大区别,他将整个Java堆划分为多个大小相等的独立区域,没怎么使用过。后续用了再来补充。
gc 异常排查
以后再补充吧
gc 常用命令
jps 显示指定系统内所有的Hotspot虚拟机进程
jinfo 显示虚拟机配置信息
jstat 用于收集Hotspot虚拟机各方面运行数据
jmap 生产虚拟机的内存转存快照
jhat 用于分析转存快照
jstack 显示虚拟机的线程快照
gc日志分析
53.092: [GC53.092: [ParNew: 838912K->50004K(943744K), 0.0831020 secs] 838912K->50004K(4089472K), 0.0832400 secs] [Times: user=0.34 sys=0.02, real=0.09 secs]
7204.738: [Full GC7204.739: [CMS: 329067K->317488K(3145728K), 1.9303260 secs] 1074227K->317488K(4089472K), [CMS Perm : 37058K->37043K(262144K)], 1.9305540 secs] [Times: user=1.93 sys=0.00, real=1.93 secs]
53.092 7204.738 指从Java虚拟机启动以来经过的秒数。
[GC 、[Full GC 说明了这次垃圾收集的停顿类型,full 说明这次GC发生了stop-the-world
[ParNew [CMS GC发生的区域与垃圾收集器有关
838912K->50004K(943744K) 表示 GC前该内存区域已使用容量->GC后该内存区域已使用的容量(该内存区域总容量)
方括号外的 838912K->50004K(4089472K) 表示 GC 前Java堆内存已使用容量->GC后Java堆已使用容量(Java堆总容量)
0.0832400 secs 表示该内存区域GC所占用的时间单位秒。