其他分享
首页 > 其他分享> > 二、深究JVM垃圾回收(保姆式讲解,内附大量图解!!!)

二、深究JVM垃圾回收(保姆式讲解,内附大量图解!!!)

作者:互联网

一、内存泄露与内存溢出

1.内存泄漏memory leak :

     是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

2、内存溢出 out of memory :

     指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。

3、二者的关系

   内存泄漏的堆积最终会导致内存溢出   内存溢出就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误。

内存溢出:栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那我就报错,

4、内存泄漏的分类(按发生方式来分类)

常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。

一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。

隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

5、内存溢出的原因及解决方法:

内存溢出原因:

内存溢出的解决方案:

6.重点排查以下几点:

1.检查对数据库查询中,是否有一次获得全部数据的查询。

    一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

2.检查代码中是否有死循环或递归调用。

3.检查是否有大循环重复产生新对象实体。

5.检查List、MAP等集合对象是否有使用完后,未清除的问题。

      List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

7.如何判断对象可以回收

1、引用计数法

如果一个对象被其他对象引用了,就让它的引用计数+1,又被其他对象引用的时候计数 再加1,没结束一个引用,引用计数就-1;当引用计数为0的时候,它就可以被回收了。 缺点: 

第一阶段新生代垃圾回收过程:

G1把堆内存划分为若干个区域,每个区域都可做为:伊甸园,幸存区,老年代

第二阶段:新生代的回收和并发标记的阶段

第三阶段:混合回收阶段

G1_REMAKE 更新标记

G1_字符串去重

G1_类卸载

所有对象都经过并发标记后,就能知道那些类不在被使用,当一个类加载器的加载的所有类都不在使用,则卸载它所加载的所有类

G1_巨型对象

六、垃圾回收调优

调优领域

确定目标

     追求是高吞吐量还是追求低延迟来选择合适的垃圾回收器

   互联网:低延迟

             采用:CMS(很少使用)、G1(适合超大内存,集合了CMS与ParallelGC的优点)、ZGC 科学运算

   追求高吞吐量  

            采用:ParallelGC 6.3尽量减少发生GC的概率 查看FullGC前后的内存占用,考虑下面几个问题

          数据是不是太多? 例 resultSet=satement.executeQuery("select * from 大表"),这时会将大量数据加载到堆内存中,占用内存资源 解决方法,加上一些限定条件,筛选有用的数据。

         是否存在内存泄漏? 内存泄漏导致有些无用的对象所占用的内存无法被回收,久之就会导致内存不足。

         对象大小 选择合适的对象的类型 Integer 占用24字节 int占用 4个字节

         使用第三方缓存实现 例如:使用redis缓存 6.4新生代调优

新生代的特点

幸存区调优

  • 幸存区大到能保留[当前活跃对象+需要晋升对象]
    • 晋升阈值配置得当,让长时间存货对象尽快晋升
  • 老年代调优 以CMS为例 - 以CMS的老年代内存越大越好 - 先尝试不做调优,如果没有FUll GC,那么说明老年代内存还可 以 - 观察发生FUll gc 时老年代内存占用,将老年代内存预设调大1/4~1/3

上一篇:一、Java虚拟机与跨平台原理讲解(硬怼面试官再也不怂!!!)

下一篇:

标签:泄漏,对象,内附,引用,回收,内存,JVM,溢出,保姆式
来源: https://blog.csdn.net/weixin_44205087/article/details/118654656