jvm gc
2019-12-16 10:23:46 0 举报
AI智能生成
对gc各方面的知识及使用,调优做了一个整理,方便大家认识jvm,gc及gc各种算法,jvm调优
作者其他创作
大纲/内容
jvm gc
调优方案汇总
调优目的
减少gc频率和fullGC的次数
导致FullGC的原因
老年代被写满
持久带空间不足
System.gc显示调用
内存泄漏
内存泄漏是指程序申请到了内存之后,没有办法释放已经申请的内存(比如大对象,死循环锁等),即被分配的对象可达但无用。
调优工具
jstat
jmap
mat
virstual vm
调优步骤
监控GC状态
监控GC时间
每次垃圾回收时间越来越长
FullGC次数越来越多
老年代的内存越来越大并且每次FullGC后没有太大变化,内存没有被整个释放(出现内存泄漏)
生成dump文件
大小为3G的hprof文件
down机前的dump
down机后的dump
分享dump文件
Visual VM
IBM HeapAnalyzer
JDK自带的Hprof工具
MAT
分析结果释放需要优化
检查是否有系统超时日志出现
GC频率是否高
GC耗时
那些情况可以考虑不优化GC配置
Minor GC执行时间不到50ms
MinorGC执行不频繁,约10秒一次
FullGC执行执行不到1s
FullGC执行频率不算频繁,不低于10分钟1次
调整GC类型和内存大小
增加永久带大小
增加jvm分配内存大小
细化分析和测试
调优参数
生产观察gc时间参数
PrintGCTimeStamps
PrintGCDetails
loggc
gc算法
标记-清理算法
介绍
优点
缺点
使用场景
复制算法
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块内存用完了,就将还存活的对象复制到另外的一块上面,然后再把已使用过的内存空间一次清理掉
不用考虑内存碎片的情况
移动堆顶指针,按顺序分配内存即可
实现简单,运行高效
效率问题
对象的内存存活率较高时,复制操作次数多,效率降低
空间问题
内存缩小一半,需要额外的空间做分配担保(老年代)
ParelOld收集器中使用
Serial收集器中使用
标记-整理算法
标记过程和标记-清除算法一样,只是在清除阶段不是直接可回收对象进行对象清理,而是将所以存活对象想一端移动,然后直接清理掉端边界以外的内存
减少空间内存碎片
充分利用内存大小
在Serial Old收集器中使用
分代收集算法
GC分代的基本假设:绝大部分对象的生命周期非常短暂,存活时间短
把java的堆分为新生代,老年代,这样可以根据各各年代的特点采用最适当的收集算法,比如在新生代,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选择使用复制算法,只需要付出复制少量存活对象的成本即可完成。而老年代因为对象的存活率高,没有额外的空间对他进行分配做担保,所以使用标记-整理算法来进行回收
分代历练
根据各代对象存活时间及可分配空间进行算法选择
收集器
新生代
Serial
串行收集器——复制算法
特点
速度快
算法简单
串行执行
垃圾采集的时候,应用线程必须暂停
是单线程的垃圾收集
在client jvm模式下使用
gc的预热标记阶段使用(首次minor gc使用)
使用参数
-XX:+UseSerialGC
PraNew
多线程并发收集器-复制算法
serial的多线程版本
多线程垃圾收集
垃圾采集是,应用线程必须暂停
gc的线程
parNew是Server模式下jvm首选的jvm新生代收集器
-XX:+UseParNewGC
Parallel Scavenge
吞吐量优先收集器-复制算法
最高效使用cpu
追求高吞吐量
多核执行
目前服务端应用默认使用该模式
老年代
Serial Old
serial的老年代版本,和serial的特点相同
client模式下的jvm使用
在jdk1.5以及之前的版本中与Parallel Scavenge收集器搭配使用(server模式)
作为CMS收集器的后备预案,在并发收集发生Concurrent Model Failure的时候使用
Parallel Old
多线程—复制算法
Parallel Scavenge的特点一样
jdk1.6后提供
吞吐量优先
Jdk1.6后提供
在注重吞吐量和cpu大于1的情况下,可以优先考虑ParallelScavenge+ParallelOld收集器
Cms
Consurrent Mark Sweep 标记-清理算法
可以获得最短停顿时间
并发收集
低停顿
使用两次短暂的停顿来代替串行或并行标记整理算法时候的长暂停
对cpu资源非常敏感
需要更多的cpu资源
无法处理浮动垃圾-内存碎片多
因为使用标记-清理算法,导致空间中产生内存碎片。给了一个优化策略,提供一个未分配空间汇总表,但是遇到需要分配连续空间的时候,还是会导致FullGC操作
基于 标记-清除 算法实现收集器,在收集结束后,会产生大量的空间碎片
互联网应用服务端
B/S系统服务端
实现过程
初始标记(STW initial mark)
主要是年轻代在做首次MinorGc的时候使用
并发标记(ConCurrent marking)
在初始标记的基础上,在机械向下追溯标记
并发预清理(ConCurrent precleaning)
并发的执行应用线程,同时jvm查找正在执行的 并发标记阶段进入老年代的对象。通过重新扫描,减少在一个阶段 重新标记的工作
重新标记(STW remark)
再次暂停正在执行的应用线程,重新从根对象开始查找并标记并发阶段遗漏的对象
并发清除(Concurrent sweeping)
这个阶段依然是并发的,应用线程和GC清除线程可以一起执行
并发重置(Concurrent Reset)
仍然并发执行,重置CMS收集器数据结构,等待下一次垃圾回收
-XX:UseConcMarkSweepGC
Garabge First
被oracle收购后,这块功能是收费版本,在实际工作中没有使用到。主要是通过重新划分内存区,同时注重吞吐量和响应时间
G1收集器(回收整个新生代和老年代)
永久带
metaspace(1.8以后替换了永久带)
存储空间
方法区
方法区是可供各线程共享的运行时内存区域
类的元数据信息
静态变量
即使编译器编译后的代码(spring使用ioc或者aop创建bean,或者使用cglib,反射的形式动态生产的calss信息
运行时常量池(1.6以前)
栈区
虚拟机栈
本地方法栈
程序计数器
堆空间
Eden
SurvivorFrom
SurvivorTo
永久代(jdk1.8以前)
调优
评估类的量基
常量存储大小
常量池(jdk1.7及以后)
metaspace
java1.8提出
没有使用堆内存
使用与对不相链的本地内存区域,理论上系统可以使用的内存多大,元空间就有多大,所以不会出现内存溢出问题,但是会导致机器内存用光而down机
TLAB
主要在新生代的Eden中,标记一个对象被分配的空间
对象在进行new关键字时候分配了一个缓存空间,是线程私有的
分start,end,size
内存溢出和内存泄漏
内存溢出
内存溢出是指程序申请内存的时候,没有足够的空间给程序申请内存
并行和并发的却别
在gc收集器中通常用并行和并发的概念,两者有哪些却别呢
并行-Parallel
多条垃圾收集线程并行工作,但是此时的用户线程处于等待状态
并发-Concurrent
指用户线程和GC收集线程同时执行(这个情况下不一定是并行执行,可能是交替执行),用户的程序正常运行,而垃圾收集器程序运行在另外一个cpu上
MinorGC和FullGC
MinorGC
主要是在新生代进行垃圾收集工作,执行时间短,实现分配频繁,通常是对于存活时间短的对象进行回收
MajorGC
在老年代发生的垃圾回收工作,执行时间长,同时会伴随一些MinorGC
Full GC
对新生代,老年代和永久带都进行垃圾回收
0 条评论
回复 删除
下一页