常见的内存溢出和内存泄漏解决方案

175 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

前言

JVM运行时首先需要类加载器(classLoader)加载所需类的字节码文件。加载完毕交由执行引擎执行,在执行过程中需要一段空间来存储数据(类比CPU与主存)。这段内存空间的分配和释放过程正是我们需要关心的运行时数据区。内存溢出的情况就是从类加载器加载的时候开始出现的,内存溢出分为两大类:OutOfMemoryError和StackOverflowError

什么是内存溢出?

内存溢出: (out of memory)通俗理解就是内存不够,指程序要求的内存超出了系统所能分配的范围。 这个其实很好理解.

内存泄漏

什么是内存泄漏?

内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

为什么会内存泄漏?

Java和c/c++不同不需要我们显示的释放和申请内存,而是交给JVM的垃圾回收器统一的管理和回收的。怎么判断是不是垃圾,什么时候去做垃圾回收?可以参考前面JVM垃圾回收的知识点。垃圾回收算法计数器和可达性分析算法,本质都是判断一个对象是否存在引用,但是我们写代码时候,会存在一些考虑不全的情况会导致垃圾无法回收,最终导致,内存泄漏问题(让JVM误以为此对象还在引用中,无法回收,造成内存泄漏)。

image.png

根据 JVM8 规范,JVM 运行时内存共分为虚拟机栈、堆、元空间、程序计数器、本地方法栈五个部分。还有一部分内存叫直接内存,属于操作系统的本地内存,也是可以直接操作的。

常见内存泄漏的场景

1、静态集合类

比如HashMap、LinkedList,这些集合类你定位为静态类和Spring 容器的生命周期一致,而且在运行过程中集合的大小还在不断地增长,从而导致内存泄漏。

2、各种连接

在对数据库进行操作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用close方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。这个其实很多时候是被我们忽略的,我们可以用try-with-resources 方法进行资源的管理

3、