1、如何定位垃圾?
引用计数算法
问题:循环引用
根可达性分析算法
2、谈谈你对GCRoots的理解?
虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。
方法区中的类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中(Native方法)引用的对象。
3、强、软、弱、虚四大引用类型的特点和适用场景?
Reference
特点:
当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。
SoftReference
特点:
对于只有软引用的对象来说,当系统内存充足时它不会被回收,当系统内存不足时它会被回收。【够不够用指的是发生GC后,内存仍然不够用的情况】
适用场景:
缓存
WeakReference
特点:
对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管内存空问是否足够,都会回收该对象占用的内存。
适用场景:
WeakHashMap【ThreadLocalMap】如果key没有其他引用,一旦发生GC此时key会被回收。
PhantomReference
特点:
PhantomReference的get方法总是返回nul,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入finalization阶段,可以被gc回收,用来实现比finalization机制更灵活的回收操作。不能单独使用,必须配合ReferenceQueue使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添进一步的处理。
4、OOM
线上发生OOM问题如何排查?
首先,查看GC日志找到原因
然后,定位代码分析优化
然后,灰度观察
最后,压测观察
OOM的类型有哪些?
java.lang.StackOverflowError【方法递归调用次数过多】
java.lang.OutOfMemoryError:Java heap space【堆区溢出】
java.lang.OutOfMemoryError:GC overhead limit exceeded【GC的时间比例太大效率低】
java.lang.OutOfMemoryError:Direct buffer memory【ByteBuffer.allocteDirect(capability)】-XX:MaxDirectMemorysize=5m
java.lang.OutOfMemoryError:unable to create new native thread【线程创建过多超过系统】
java.lang.OutOfMemoryError:Metaspace【操作系统本地内存】-XX:Metaspacesize=8m -XX:MaxMetaspacesize=8m
虚拟机加载的类信息
常量池
静态变量
即时编译后的代码
5、垃圾收集器分类
新生代/老年代
搭配关系
DefNew(Default New Generation)
Tenured(Old)
ParNew(Parallel New Generation)
PSYoungGen(Parallel Scavenge)
ParOldGen(Parallel Old Generation)如何选择收集器呢?
如何查看默认垃圾收集器?
java -XX:+PrintCommandLineFlags -version
jps
jinfo -flag UseParallelGC pid
7、常用垃圾回收期的工作过程
新生代
Serial串行收集器(Serial + Serial Old)
-XX:+UseSerialGC
Serial使用复制算法
Serial Old适用标记整理算法
ParNew并行收集器(ParNew+ CMS)
-XX:+UseParNewGC 该参数只会影响新生代的垃圾收集器,老年代默认还是Serial Old
-XX:ParallelGCThreads限制线程数量,默认开启和CPU数目相同的线程数
ParNew使用复制算法
Serial Old适用标记整理算法
Parallel Scavenge并行收集器(Parallel Scavenge+ Parallel Old)1.8后的默认组合
Parallel Scavenge吞吐量优先的垃圾收集。
可控制的吞吐量(Thoughput=运行用户代码时间/(运行用户代码时间+垃圾收集时间),也即比如程序运行100分钟,垃圾收集时间1分钟,吞吐量就是99%)。高吞吐量意味着高效利用CPU的时间,它多用于在后台运算而不需要太多交互的任务,
自适应调节策略也是ParallelScavenge收集器与ParNew收集器的一个重要区别。(自适应调节策略:虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间(-X:MaxGCPauseM训is)或最大的吞吐量。-XX:+UseParallelGC或-X:+UseParallelOldGC(可互相激活)使用arallel Scanvenge收集器
-XX:ParallelGCThreads=N限制线程数量,默认开启和CPU数目相同的线程数
ParallelScavenge使用复制算法
Parallel Old使用标记整理算法
老年代
Parallel Old
-X:+UseParallelOldGC 自动激活(Parallel Scavenge+ Parallel Old)1.8后的组合。
CMS垃圾收集器(低停顿时间优先的垃圾收集器)
CMS收集器(Concurrent Mark Sweep:并发标记清除)是一种以获取最短回收停顿时间为目标的收集器。
开启该收集器的JVM参数:-X:+UseConcMarkSweepGC开启该参数后会自动将-XX:+UseParNewGC打开
开启该参数后,使用ParNew(Youngl区用)+CMS(Old区用)+Serial Old的收集器组合,Serial Old将作为CMS出错的后备收集器过程
初始标记
并发标记
重新标记
并发清除
优缺点
动态年龄判定
内存担保机制
内存碎片
CMS也提供了参数-XX:CMSFullGCsBeForeCompaction(默认0,即每次都进行内存整理)来指定多少次CMS收集之后,进行一次压缩的Full GC。
Serial Old
万能老年代收集器,可以搭配所有新生代收集器。
使用标记整理算法。
-XX:+UseserialoldGC
G1垃圾收集器
-XX:+UseG1GC
G1(Garbage-First)收集器,是一款面向服务端应用的收集器。更高的内存。
主要改变是Eden,Survivor和Tenured等内区域不再是连续的了,而是变成了一个个大小一样的region,每个region从1M到32M不等。一个region有可能属于Eden,Survivor或者Tenured内存区域。
特点
1.G1能充分利用多CPU、多核环境硬件优势,尽量缩短STW。
2.G1整体上采用标记-整理算法,局部是通过复制算法,不会产生内存碎片。
3.宏观上看G1之中不再区分年轻代和老年代。把内存划分成多个独立的子区域(Regior),可以近似理解为一个围棋的棋盘。
4.G1收集器里面讲整个的内存区都混合在一起了,但其本身依然在小范围内要进行年轻代和老年代的区分,保留了新生代和老年代,但它们不再是物理隔离的,而是一部分Region的集合且不需要Region是连续的,也就是说依然会采用不同的GC方式米处理不同的区域。
5.G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换:回收过程或底层原理
区域化内存划片Region,整体编为了一系列不连续的内存区域,避免了全内存区的GC操作。
核心思想是将整个堆内存区域分成大小相同的子区域(Region),在JVM启动时会自动设置这些子区域的大小,
在堆的使用上,G1并不要求对象的存储一定是物理上连续的只要逻辑上连续即可,每个分区也不会固定地为某个代服务,可以按需在年轻代和老年代之间切换。启动时可以通过参数-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划
分为2048个分区。大小范围在1MB~32MB,最多能设置2048个区域,也即能够支持的最大内存为:32MB·2048=65536MB=64G内存。区域划分
针对Eden区进行收集,Eden区耗尽后会被触发,主要是小区域收集+形成连续的内存块,避免内存碎片
1.Eden区的数据移动到Survivor区,假如出现Survivor区空间不够,Eden区数据会部会晋升到OId区
2.Survivor区的数据移动到新的Survivorl区,部会数据晋升到Old区
3.最后Eden区收拾干净了,GC结束,用户的应用程序继续执行。过程
初始标记:只标记GC Roots能直接关联到的对象
并发标记:进行GC Roots Tracingl的过程
最终标记:修正并发标记期间,因程序运行导致标记发生变化的那一部分对象
筛选回收:根据时间来进行价值最大化的回收常用参数
XX:+UseG1GC
XX:G1HeapRegionSize=n:设置的G1区域的大小。值是2的幂,范围是1MB到32MB。
XX:MaxGCPauseMillis=n:最大GC停顿时间,这是个软目标,JVM将尽可能(但不保证)停顿小于这个时间
XX:InitiatingHeapOccupancyPercent=n:堆占用了多少的时候就触发GC,默认为45
XX:ConcGCThreads=n:并发GC使用的线程数
XX:G1ReservePercenta=n:设置作为空闲空间的预留内存百分比,以降低目标空间溢出的风险,默认值是10%重点
G1与CMS的区别
G1是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。
G1的Stop The World(STW)更可控,G1在停顿时间上添加了预测机制,用户可以指定期望停顿时间。
6、GC调优经验
4大垃圾回收算法
复制算法
标记清除
标记整理