简述java垃圾回收机制
在java中我们不需要去释放一个对象的内存,这个由jvm去做。jvm中有个垃圾回收线程,它是低优先级的,当虚拟机空闲时或者堆内存不足时,它才会执行回收没用的对象。
内存区域中的程序计数器,虚拟机栈,本地栈是随线程而生随线程而死,每个栈帧的大小在类被加载时就已经确定下来了,无需过多考虑回收问题。主要是回收堆和方法区的对象。
GC是怎样判断对象是否能被回收的
早期GC判断对象是否能被回收时用的引用计数法,后来改进成了可达性分析法。
引用计数法:比如A引用了B它就会记录下一个1 ,同理B也去引用A。引用计数法只有在为0的时候才回收对象,像这种“相互引用,循环引用”的对象其中一个没回收都是回收不了的。
可达性分析法:通过GCRoot去引用该对象,若不为空则不回收,为空则回收。
那什么样的对象才能作为gcroot对象呢?
答:线程在运行状态中不允许被回收的对象。 例如:局部变量,静态变量,常量,成员变量。
Minor GC与Full GC分别在什么时候发生?
新生代内存不够用时候发生MGC也叫YGC,JVM内存不够的时候发生FGC
Minor gc在新生代内存不够的时候触发
Major gc在老年代内存不够的时候触发
Full gc 在JVM内存不够的时候触发,它会清理新生代和老年代的空间。
垃圾收集器有哪些?
(1)串行收集器,只使用一个线程去做,是最稳定以及高效的收集器,可能产生较长的停顿。新生代、老年代使用串行回收;新生代复制算法、老年代标记-压缩;
(2)并行收集器,多线程去做.新生代并行,老年代串行;新生代复制算法、老年代标记-压缩
(3)CMS收集器:是一种以获取最短回收停顿时间为目标的收集器,CMS收集器是基于“标记-清除”算法实现。
四个步骤:1.初始标记 2.并发标记,3.重新标记,4.标记清除。初始标记和重新标记需要停顿,这段时间较短, 并发标记和并发清除时间长,cms并发执行。
(4)G1收集器:1.并行与并发 2.分代收集 3.空间整合 4.可预测停顿。
(5)吞吐量收集器
Java对象在内存中的状态:
可 达: 对象创建之后,能被变量引用就是可达的。
可恢复: 对象没有引用指向时就成了可恢复状态,回收该对象之前调用finalize()进行清理,若在finalize()方法中重新被引用就会变成可达状态,反之就成为不可达状态。
不可达: 不被引用且finalize清理时也不能重新被引用就成了不可达状态。
强引用、软引用、弱引用、虚引用以及他们之间和gc的关系
强引用:指向通过new得到的内存空间的引用叫强引用,只要强引用还在,它宁愿out of memory内存溢出也不会回收。
弱引用:通过weakReference类来实现,不管内存是否充足都会回收.
软引用:通过SoftReference类来实现,内存溢出之前,回收
虚引用:虚引用通过PhantomRefence类实现,如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。
什么是内存泄漏及如何避免
内存泄漏即:对象可达但不可用,一个对象不再需要使用本该回收时,另一个正在使用的对象却持有它的引用,导致无法回收停留在堆内中。
防止内存泄露:
1.尽早释放无用对象的引用, 将不需要使用的对象设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄漏。
2.程序进行字符串处理时,尽量避免使用String,而应该使用StringBuffer。
3.尽量少用静态变量
4.尽量运用对象池技术以提高系统性能
Jvm常见异常处理方案
内存泄漏: java.lang.OutOfMemory Error:Java heap space
解决思路: 1. 先查看是不是内存泄漏,如果是通过GC Root的路径来排查
2. 查看堆内存是否有对象没释放。
3. 加大物理内存 –Xms, -Xmx,最好-Xms = -Xmx,减少内存扩展的开销。
控制参数: -Xms (starting 堆的起始大小) -Xmx (max 堆的最大大小) -Xmn (new 堆的新生代大小)
内存溢出: java.OutOfMemory Error:PermGen space
解决思路: 增加参数:-XX:PrintGCDetails,-XX:+PrintGCTimeStamps和-XX:+PrintGCDateStamps
线程请求的栈深度大于虚拟机所允许的最大深度:java.lang.StackOverflow Error
解决思路: 可以将栈的深度,理解为数组的长度。
控制参数: 1. 加大-Xss(每个线程的堆栈大小)参数。
2. 更换64位虚拟机。
3. 减少线程。
4. 减少最大堆(Xmx)。
java.lang.OutOfMemory Error,有allocate、Native字样
解决思路: 加大本地内存-MaxDirectMemorySize如不指定则与-Xmx一致。
以centos6.8 ,100G的内存,参考配置如下:
JAVA_OPTS="-Xms8g -Xmx8g
-XX:ParallelGCThreads=8
-XX:PermSize=2g
-XX:MaxPermSize=4g
-Xss512k -Xmn6g
-XX:-DisableExplicitGC
-XX:+UseCompressedOops
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled"
CATALINA_OPTS="-Xms8g -Xmx8g
-XX:ParallelGCThreads=8
-XX:PermSize=2g
-XX:MaxPermSize=4g
-Xss512k -Xmn6g
-XX:-DisableExplicitGC
-XX:+UseCompressedOops
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled"
三:GC回收机制