Java应用程序中是否完全没有内存泄漏?

Java应用程序中是否完全没有内存泄漏?,java,memory,garbage-collection,Java,Memory,Garbage Collection,可能重复: Java中有一个“垃圾收集器”,但这是否意味着Java应用程序中完全不存在内存泄漏?如果没有,它们是如何发生的以及为什么发生的 我对使用JavaSE的应用程序中的场景更感兴趣。无-Java中仍然存在内存泄漏。它们只是“不同的种类” 在计算机科学中,当计算机程序消耗内存但无法将其[内存]释放回操作系统时,就会发生内存泄漏(在本文中称为泄漏) 在Java的情况下,它(通常)是指一个未使用/不需要的对象永远没有资格回收。例如,一个对象可能隐藏在一个全局列表中,并且永远不会删除,即使以后

可能重复:

Java中有一个“垃圾收集器”,但这是否意味着Java应用程序中完全不存在内存泄漏?如果没有,它们是如何发生的以及为什么发生的


我对使用JavaSE的应用程序中的场景更感兴趣。

无-Java中仍然存在内存泄漏。它们只是“不同的种类”

在计算机科学中,当计算机程序消耗内存但无法将其[内存]释放回操作系统时,就会发生内存泄漏(在本文中称为泄漏)

在Java的情况下,它(通常)是指一个未使用/不需要的对象永远没有资格回收。例如,一个对象可能隐藏在一个全局列表中,并且永远不会删除,即使以后再也不会访问该对象。在这种情况下,JVM不会释放对象/内存-它不能-因为以后可能需要该对象,即使它从来都不需要

(另一方面,一些对象(如直接分配的ByteBuffers)也会消耗“JVM堆外”内存,由于终结器的性质和内存压力,这些内存可能无法及时回收。)

就Java而言,“内存泄漏”是一个语义问题,而不是“在任何情况下都无法释放”的问题。当然,对于有缺陷的JNI/JNA代码,所有的赌注都没有了;-)


愉快的编码。

java中很可能存在内存泄漏。从根本上说,当垃圾收集器无法回收对象时,java中会发生内存泄漏,因为应用程序持有一个不会释放的对象引用,即使对象本身可能不再被使用。在java中创建内存泄漏的最简单方法是让应用程序保存对某个对象的引用,但不要使用它


在本例中,未使用的对象是一个静态列表,向该列表添加内容最终会导致JVM内存不足。静态集合是“泄漏”的一个非常常见的来源,因为它们通常是长期存在且可变的。

取决于您如何定义内存泄漏

如果您明确表示已分配的内存不再被某个内存根引用,则不会,垃圾收集器最终将清除所有这些内存


如果您的意思是让内存占用不受限制地增长,那么这很容易实现。只要有一些集合被静态字段引用并不断添加到中即可。

到目前为止,有一些很好的响应。我不想重新创建那些帖子,所以我只想补充一点,大多数人在这个主题上没有想到的是,通过JNI运行的本机代码中存在漏洞。通过JNI运行的本机代码使用JVM的堆空间来分配内存。因此,如果您的应用程序使用通过JNI运行的本机代码存在漏洞,则您的应用程序存在漏洞。

任何具有一个或多个活动引用的对象都不会被垃圾收集。因此,只要某个变量(静态、堆中或堆栈中)引用某个对象,该对象就会继续占用不可回收的内存空间


未关闭的资源(如套接字、JDBC连接等)和不断增长的静态收集是一些更知名的泄漏产生者。

作为后续措施,没有垃圾收集器可以始终回收所有未使用的内存。可以证明,不可能构建一个GC来检测某个内存块是否永远不会被再次使用,因此大多数GC使用该内存是否可以访问作为代理。感谢快速响应pst。你提到的问题是正确的,但更多的是因为(糟糕的)编程实践,对吗?假设内存中有一些对象“确实”符合回收条件,JVM肯定会回收它们吗?确定吗?@10101010可回收对象,即那些从根目录中无法很好地访问的对象,将在“某个时候”被回收,是的。然而,在终结器中释放“本机”内存的对象的情况下,“本机”内存的释放速度可能不够快(即使可以),因此可能会导致[过早]OOM。一个小问题:在一个完美的JVM中,GC将始终回收任何不再可访问的对象。但是,由于JVM的缺陷和GC计算可达性的能力的限制,有一些方法可以将大量数据(例如类加载器)保持根目录以用于GC目的,同时仍然无法“可达”从普通Java代码能够解引用和读取相应的对象值的意义上讲,我已经用一个糟糕的实现观察者模式来证明这一点。内存泄漏,肯定存在。有一个线程讨论如何在java中创建内存泄漏。