三:GC回收机制

简述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,allocateNative字样

     解决思路:  加大本地内存-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"

猜你喜欢

转载自www.cnblogs.com/wlwl/p/9463835.html