欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

内存泄漏和内存溢出

程序员文章站 2022-07-15 14:21:18
...


相关文章:
JVM内存模型
Java GC垃圾回收机制

一、内存泄漏

Memory Leak,内存泄漏,在 JAVA 语言中指的是申请的内存空间不能被正常回收,导致后续程序里这块内存被永远占用(不可达),当指向这块内存空间的指针不再存在时,这块内存也就永远不可达了,这块内存空间就被泄漏了。

一般情况下,少量的内存泄漏不会有什么影响,但是长期大量的内存泄漏可能会引起内存溢出。

借用别人的比喻就是:

比如有 10 张纸,本来一人一张,画完自己擦了还回去,别人可以继续画。
现在有个坏蛋要了纸不还,然后还跑了找不到人了,如此就只剩下 9 张纸给别人用了。

这种情况就相当于 "内存泄漏" 了。
这种不道德的人多了,最后纸都 "泄漏" 完了,再有人来要纸就没有了,就变成 "内存溢出" 了。

在 C/C++ 中,程序员动态申请的内存空间通常需要人为调用 free/delete 来释放,否则内存会一直被占用,不会自动释放,于是就很容易造成内存泄漏。

而在 Java 中,JVM GC 垃圾回收机制会自动回收不可达对象,不需要程序员手动释放空间,大大减少了内存泄漏的可能性。

二、内存溢出

内存溢出,其实就是内存越界,是指存储的数据超出了可分配的空间大小,这时程序就会出现内存溢出错误。

内存溢出通常是内存不足,内存泄漏通常是指内存空间没有正常回收或无法回收。

在 JAVA 语言中,内存溢出包括两类情况:

  • *Error:通常是栈深度不足导致的栈内存溢出
  • OutOfMemoryError:通常是内存空间不足导致的内存溢出

1、*

*,通常称为栈溢出。

先看一下之前的文章中讲过的 JVM 的内存模型,如下图所示:

内存泄漏和内存溢出

在 Java 中,栈是由许多栈帧(Stack frame)组成,一个栈帧包含一个 Java 方法的调用状态。

执行每个方法时都会在调用栈上分配一个栈帧 (Stack Frame),用于存储引用方法的参数、方法中定义的变量、操作数栈、方法的返回地址等信息。

栈帧随着方法调用而创建,随着方法结束而销毁。

如果在调用方法时,线程请求的栈深度大于 JVM 允许的深度,就会抛出 *Error 栈溢出错误。(最常见的可能耗光 Java 栈深度的场景是方法递归)

2、OutOfMemory

OutOfMemoryError,简称 OOM。

很多时候会认为内存溢出就是指 OOM,其实二者并不等价,只能说因为 OOM 引起内存溢出的情况比较多一些。

在 Java 中,
出现 OOM 最多的就是堆内存溢出,一般是类似下面这样的报错:

java.lang.OutOfMemoryError: Java heap space

当出现类似这样的报错信息后,就要进一步排查错误日志、参数配置、代码等方面。

更多 OOM 问题的分析和解决在后面详细讲解。