JVM——产生内存溢出原因

1.产生内存溢出原因一 :代码中的内存泄漏

在这里插入图片描述

1.案例1:equals()和hashCode()导致的内存泄漏

问题:

⚫ 在定义新类时没有重写正确的equals()和hashCode()方法。在使用HashMap的场景下,如果使用这个类对象作为key,HashMap在判断key是否已经存在时会使用这些方法,如果重写方式不正确,会导致相同的数据被保存多份。


正常情况

1、以JDK8为例,首先调用hash方法计算key的哈希值,hash方法中会使用到key的hashcode方法。根据hash方法的结果决定存放的数组中位置。
2、如果没有元素,直接放入。如果有元素,先判断key是否相等,会用到equals方法,如果key相等,直接替换value;key不相等,走链表或者红黑树查找逻辑,其中也会使用equals比对是否相同。在这里插入图片描述

异常情况:

1、hashCode方法实现不正确,会导致相同id的学生对象计算出来的hash值不同,可能会被分到不同的槽中。在这里插入图片描述
2、equals方法实现不正确,会导致key在比对时,即便学生对象的id是相同的,也被认为是不同的key。在这里插入图片描述
3、长时间运行之后HashMap中会保存大量相同id的学生数据。在这里插入图片描述

解决方案:

1、在定义新实体时,始终重写equals()和hashCode()方法。
2、重写时一定要确定使用了唯一标识去区分不同的对象,比如用户的id等。
3、hashmap使用时尽量使用编号id等数据作为key,不要将整个实体类对象作为key存放

2.案例2:内部类引用外部类

问题:

⚫ 1、非静态的内部类默认会持有外部类,尽管代码上不再使用外部类,所以如果有地方引用了这个非静态内部类,会导致外部类也被引用,垃圾回收时无法回收这个外部类。
⚫ 2、匿名内部类对象如果在非静态方法中被创建,会持有调用者对象,垃圾回收时无法回收调用者

解决方案:

1、这个案例中,使用内部类的原因是可以直接获取到外部类中的成员变量值,简化开发。如果不想持有外部类
对象,应该使用静态内部类。
2、使用静态方法,可以避免匿名内部类持有调用者对象。

3.案例3:ThreadLocal的使用

问题:

如果仅仅使用手动创建的线程,就算没有调用ThreadLocal的remove方法清理数据,也不会产生内存泄漏。因为当线程被回收时,ThreadLocal也同样被回收。但是如果使用线程池就不一定了。

解决方案:

线程方法执行完,一定要调用ThreadLocal中的remove方法清理对象。

4.案例4:String的intern方法

问题:

JDK6中字符串常量池位于堆内存中的Perm Gen永久代中,如果不同字符串的intern方法被大量调用,字符串常量池会不停的变大超过永久代内存上限之后就会产生内存溢出问题。

解决方案:

1、注意代码中的逻辑,尽量不要将随机生成的字符串加入字符串常量池
2、增大永久代空间的大小,根据实际的测试/估算结果进行设置-XX:MaxPermSize=256M.

5案例5:通过静态字段保存对象

问题:

如果大量的数据在静态变量中被长期引用,数据就不会被释放,如果这些数据不再使用,就成为了内存泄漏。

解决方案:

1、尽量减少将对象长时间的保存在静态变量中,如果不再使用,必须将对象删除(比如在集合中)或者将静态变量设置为null。
2、使用单例模式时,尽量使用懒加载,而不是立即加载。
3、Spring的Bean中不要长期存放大对象,如果是缓存用于提升性能,尽量设置过期时间定期失效。

案例6:资源没有正常关闭

问题:

连接和流这些资源会占用内存,如果使用完之后没有关闭,这部分内存不一定会出现内存泄漏,但是会导致close方法不被执行。

解决方案:

1、为了防止出现这类的资源对象泄漏问题,必须在finally块中关闭不再使用的资源。
2、从 Java 7 开始,使用try-with-resources语法可以用于自动关闭资源。

2.产生内存溢出原因二 : 并发请求问题

⚫ 并发请求问题指的是用户通过发送请求向Java应用获取数据,正常情况下Java应用将数据返回之后,这部分数据就可以在内存中被释放掉。在这里插入图片描述
⚫ 并发请求问题指的是用户通过发送请求向Java应用获取数据,正常情况下Java应用将数据返回之后,这部分数据就可以在内存中被释放掉。但是由于用户的并发请求量有可能很大,同时处理数据的时间很长,导致大量的数据存在于内存中,最终超过了内存的上限,导致内存溢出。这类问题的处理思路和内存泄漏类似,首先要定位到对象产生的根源。
在这里插入图片描述

模拟并发请求

⚫ 使用Apache Jmeter软件可以进行并发请求测试。
⚫ Apache Jmeter是一款开源的测试软件,使用Java语言编写,最初是为了测试Web程序,目前已经发展成支
持数据库、消息队列、邮件协议等不同类型内容的测试工具。

相关推荐

  1. JVM内存溢出排查

    2023-12-07 19:46:02       43 阅读
  2. JVM实战(27)——内存溢出概述

    2023-12-07 19:46:02       61 阅读
  3. JVM实战(29)——模拟栈内存溢出

    2023-12-07 19:46:02       55 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-07 19:46:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-07 19:46:02       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-07 19:46:02       82 阅读
  4. Python语言-面向对象

    2023-12-07 19:46:02       91 阅读

热门阅读

  1. Node.js 的 os 模块介绍

    2023-12-07 19:46:02       51 阅读
  2. Django回顾5

    2023-12-07 19:46:02       38 阅读
  3. docker安装达梦数据库并挂在数据卷

    2023-12-07 19:46:02       64 阅读
  4. HTTPS:保护网络通信安全的关键

    2023-12-07 19:46:02       61 阅读
  5. linux中xarray结构简析

    2023-12-07 19:46:02       63 阅读
  6. Pod 存活探针 livenessProbe

    2023-12-07 19:46:02       58 阅读
  7. sklearn 笔记:neighbors.NearestNeighbors 自定义metric

    2023-12-07 19:46:02       56 阅读
  8. 当内核有内存泄漏的时候

    2023-12-07 19:46:02       44 阅读
  9. 【Spark基础】-- 宽窄依赖

    2023-12-07 19:46:02       49 阅读
  10. 拥有一台服务器可以做些什么

    2023-12-07 19:46:02       65 阅读
  11. Spark SQL百万级数据批量读写入MySQL

    2023-12-07 19:46:02       62 阅读
  12. 什么问题适合使用卡方检验?

    2023-12-07 19:46:02       44 阅读
  13. qt 链表QList,QLinkedList的常见使用

    2023-12-07 19:46:02       59 阅读
  14. 英伟达显卡系列与架构、代表产品

    2023-12-07 19:46:02       60 阅读
  15. Ubuntu 配置打开文件限制

    2023-12-07 19:46:02       64 阅读