java Jvm GC流程以及内存问题排查调优

作者:转载或者引用请注明出处!

首先梳理一下JVM虚拟机的内存布局:

    JDK版本<1.8 :

                拿线程是否可以共享作为分类:1. 被所有线程共享【 方法区(含运行时常量池),堆 】    2. 线程私有【 JVM虚拟机栈,本地方法栈,程序计数器 】

 

    JDK版本>=1.8  : 

                拿线程是否可以共享作为分类:1. 被所有线程共享【 堆(运行时常量池),元空间 】    2. 线程私有【 JVM虚拟机栈,本地方法栈,程序计数器 】

 

 

    再来梳理一下JVM的GC流程(以及gc需要知道的细节):

            JDK1.8 : 使用的虚拟机版本 Hotspot 

 

1. 对象是如何判断死亡还是继续生存?

              目前使用可达性分析方式,因为引用计数的方式解决不了对象相互引用的问题。
                        首先可以作为root根节点的对象为4类:静态对象,常量对象,当前栈帧对象,JNI对象 

            目前jvm判断对象是否可以被回收的方法是通过枚举GCroots的根节点,进行准确式GC(准确式内存管理 +GC回收)。判断当前对象到root根节点是否可达(root节点引用其他对象,其他对象引用当前对象), 则该对象不会回 收,继续生存。不可达 (当前对象到root节点找不到间接或者直接的引用关系),则回收

 

2.判断完成后如何进行回收?

        回收之前必须经过2次标记才能将对象内存彻底释放。

        1)第一次标记

             该对象没有到GCroot节点的引用关系,则进行标记

        2)第2次标记是判断finalize()方法是否执行?

              只有在被重写的情况下才有被执行资格,可以并且只执行依1次,重写过并没有执行过,则放入一个低优先级线程的队列中(该队列执行被放入的对象的finalize方法),对象逃逸/自救 未成功,则进行二次标记。

 

 3.什么叫做安全点?

         由于gc的时候对“一致性”要求比较敏感( 一致性:说的是stop the word的时候,对象状态在当前时间下的引用状态不 会轻易变化),而且同时也为了减少oopmap的空间成本。所以按照"当前代码段运行时间长,而且对象引用状态比较稳定"的条件,选取一些特定的点,这些点就是安全点。来告诉回收器,到代码运行到安全点的时候,对象状态什么的比较稳定,可以stop the word操作,有利于jvmGC。

      常用于安全点的地方:  异常,方法返回等时间相对对对象引用影响较少的运行时机

 

   4.什么叫做安全域?

      基于安全点的概念,在真实情况中,线程可以挂起,阻塞等异常状态出现,导致到达不了安全点。二stop theword 的规则就是等到所有线程都到了各自的安全点挂起才能进行GC。为了防止这种情况发生,就搞了一个域的概念,包裹的是代码块。在一些阻塞或者等待等方法前后包裹起来的代码块。叫做安全域。当代码进行安全域的时候,JVM 查询各线程状态的时候,这个线程会告诉jvm,我在安全域,不影响你GC。然后jvm就不再去理会 该线程,开始GC,当该线程代码准备出安全域的时候,回去询问jvm,你那边gc完事了没有,没有我再等一会。

 5.主动式中断和抢先式中断

      1) . 抢先式中断不需要线程代码主动配合,当GC发生时,首先把所有线程中断,如果发现线程中断的地方不在安全点  上,就恢复线程,让他跑到安全点上。现在几乎没有虚拟机实现采用抢先式中断来暂停线程来响应GC。 

     2). 主动式中断的思想是当GC需要中断线程的时候,不直接对线程操作,仅仅简单的设置一个标志,各个线程执行时    主动去轮询这个标志,发现中断标志为真时就自己中断挂起,轮询标志的地方和安全点是重合的另外再加上创建 对象需要分配的内存的地方。

 6 . gc枚举时oopmap的作用。

         oopmap在JIT编译器,类加载完成时候,会记录对象内什么偏移量是什么类型的数据。这样方便后面gc的                    时候可以快速定位对象的类型以及引用位置,提高枚举根结点的速度。jvm不会为每一条对象变化的指令生成oopmap,只有在安全点和安全域的时候。

 

                7.常用的GC算法有哪些?           

                        复制算法 (适用于大批量对象创建,使用完对象大部分清除的年轻代)

                        标记整理算法(分为两部分,整理内存空间碎片,优化标记清除算法)

                        标记清除算法 (先标记,再清除,但是会有内存碎片产生,空间浪费)

                       那么我们GC的算法最优的方式就是分代!通过堆内存中老年和年轻代各自的特性来进行选择算法!

    

DSAD

    SAD 

(())

                    

                        

                

 

 

 

服务架构采用的是多线程并行的master+多台worker集群。

任务内容是进行流数据的传输。所以涉及到很多byte[]的创建以及复制拼接。

报错但是未能在日志查询具体原因,经过排查,DirectMemory内存不足导致。发现自己原来在代码里面操作byte[]对象时候,采用的是System    相关操作字节对象的API。System使用的是本地内存。解决方式:改为Arrays相关的API进行操作,这样由原来直接内存的使用转换到了jvm内存上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值