深入理解内存泄露与内存溢出:概念、原因与益处
原始链接:

1。为什么我们应该了解内存泄漏和内存溢出?
1。内存泄漏通常是由代码设计缺陷引起的。通过了解内存泄漏的情况,可以避免不必要的内存溢出,并且可以提高您自己的代码编写级别。
2。通过了解内存溢出的几种常见情况,您可以在内存溢出时快速找到问题的位置,从而缩短解决故障的时间。
2。基本概念
了解这两个概念非常重要。
内存泄漏:是指动态分配内存到程序中的某些临时对象,但是该对象不会被GC回收,并且始终占据内存。也就是说,可以达到分配的对象,但没有用。
内存溢出:是指由于程序操作期间无法申请足够的内存而造成的错误。内存溢出通常发生在垃圾收集旧或pers段之后,并且仍然没有内存空间来容纳新的Java对象。
从定义可以看出,内存泄漏是内存溢出的原因,而不是唯一的因素。
3。内存泄漏的几种情况
1。长寿周期的对象,持有寿命短的对象
这是内存泄漏的最常见情况,也是代码设计中常见的问题。例如:随着时间的流逝,在全局静态映射中缓存本地变量,而无需清除操作,此地图将变得越来越大,从而导致内存泄漏。
2。在哈希集中修改对象的参数值,并且参数是计算哈希值的字段。
当对象存储在主题集合中时,该对象中参与计算哈希值的字段无法修改。否则,当对象最初存储在主题集合中时,对象的修改后的哈希值将与哈希值不同。 ,在这种情况下,即使包含方法使用对象的当前引用作为参数来搜索主题集合中的对象,也将返回未找到对象的结果,这也将导致删除当前对象从主题集合中,导致内存泄漏。
3。机器连接号码的设置和关闭时间
很长一段时间以来,打开一个非常耗资的连接也会导致内存泄漏。
4。内存溢出的几种情况
1。堆内存溢出(OutofMemoryError:Javaheap空间)
在JVM规范中,堆中的内存用于生成对象实例和数组。如果细分,堆的记忆也可以分为年轻一代和年长一代,年轻一代包括一个伊甸园和两个幸存者地区。
生成新对象时,内存应用程序过程如下:
一个。 JVM首先尝试分配伊甸园区域中新对象所需的内存;
b。如果存储器大小足够,则将完成应用程序,否则下一步是下一步;
c。 JVM启动Younggc,并试图在伊甸园地区释放非活动对象。释放后,如果伊甸园空间仍然不足以放置新物体,请尝试将一些活跃的物体放入幸存者区域。
d。幸存者区域用作伊甸园和老之间的中间交换区。如果旧区域的空间足够,幸存者区域的对象将被移至旧区域,否则将保留在幸存者地区;
e。当旧区域中的空间不足时,JVM将在旧区域执行完整的GC。
在F和Full GC之后,如果幸存者和旧区域仍然无法存储从伊甸园复制的某些对象,从而导致JVM无法为伊甸园区域的新对象创建内存区域,则会出现“淘汰记忆错误”:
OutofMemoryError:Java堆空间
示例代码:
2。方法区域内存溢出(OutofMemoryError:Permgem空间)
在JVM规范中,该方法区域主要存储类信息,常数,静态变量等。 。通常,该区域内存溢出时的错误消息是:
OutofMemoryError:Permgem空间
示例代码:
3。线程堆栈溢出(java.lang.stackoverflowerror)
线程堆栈唯一的内存结构,因此问题堆栈必须是线程运行时产生的错误的问题。通常,线程堆栈溢出是由太深的递归或方法过多引起的。
堆栈溢出发生的错误消息是:
java.lang.stackoverflowerror
示例代码:
5。为了避免内存泄漏,您可以在代码编写过程中参考以下建议。
1。尽快发布无用对象的参考
2。使用字符串处理避免使用字符串。大量使用StringBuffer。每个字符串对象必须独立占据内存区域。
3。尝试尽可能少地使用静态变量,因为静态变量存储在永久生成(方法区域)中,并且永久生成基本上不参与垃圾收集。
4。避免在循环中创建对象
5.打开大文件或一次从数据库中获取太多数据可能会很容易导致内存溢出,因此您需要大致计算这些位置中的最大数据量,并设置所需的最小和最大存储空间。
艺术编辑/Zhu Jiaqi