简单类 – 它是一个内存泄漏?

我有一个非常简单的类,它有一个整数变量。 我只是将变量’i’的值打印到屏幕上并递增它,并使线程hibernate1秒钟。 当我针对此方法运行探查器时,即使我没有创建任何新变量,内存使用量也会缓慢增加。 执行此代码大约16个小时后,我发现内存使用量已增加到4 MB(当我启动程序时,最初为1 MB)。 我是Java的新手。 有没有人可以帮助解释我哪里出错了,或者为什么即使没有创建新变量,内存使用量也会逐渐增加? 提前致谢。

我正在使用netbeans 7.1及其分析器来查看内存使用情况。

public static void main(String[] args) { try { int i = 1; while(true) { System.out.println(i); i++; Thread.sleep(1000); } } catch(InterruptedException ex) { System.out.print(ex.toString()); } } 

程序启动时的初始内存使用情况:1569852字节。

执行循环16小时后的内存使用情况:4095829字节

我在这篇文章中遇到的问题的屏幕截图

它不一定是内存泄漏。 当GC运行时, System.out.println(i);中分配的对象(我假设System.out.println(i); 声明将被收集。 Java中的内存泄漏是当内存填满无法通过GC回收的无用对象时。

println(i)使用Integer.toString(int)int转换为String,并且每次都分配一个新的String 。 这不是泄漏,因为一旦将String复制到输出缓冲区,String将变得无法访问并成为GC的候选者。

其他可能的内存分配来源:

  • Thread.sleep可以分配封面下的对象。

  • 一些私有JVM线程可能导致这种情况。

  • 探查器用于监视JVM状态的“java代理”代码可能导致此问题。 它必须通过套接字将数据汇编并发送到探查器应用程序,这很可能涉及分配Java对象。 它也可能在JVM的堆或非堆内存中累积内容。

但是,只要在GC运行时可以回收空间,这并不重要。 如果它不能,那么您可能在您正在使用的探查器中发现了JVM错误或错误。 (尝试用一个非常长的睡眠来替换循环并查看“泄漏”是否仍然存在。)并且如果这是由分析引起的缓慢泄漏可能无关紧要…因为您通常不运行生产代码启用了那么长的分析。


注意:不保证调用System.gc()会导致GC运行。 阅读javadoc。

我在这段代码中没有看到任何内存泄漏。 您应该看到Java中的垃圾收集器是如何工作的以及它的策略。 基本上讲GC在需要之前不会清理 – 如特定策略所示。

您也可以尝试调用System.gc()

可能在两个Java Core函数中创建对象。

这是由于控制台中显示的文本和整数的大小(一点点)。

Java打印function使用8位ASCII,因此有56000个打印数字,每个字符8个字节很快就会占用内存。

按照本教程查找内存泄漏: 使用VisualVM分析Java应用程序中的内存泄漏 。 您必须在开始时制作应用程序的快照,并在一段时间后制作另一个应用程序的快照。 使用VisualVM,您可以执行此操作并将这些快照与快照进行比较。

尝试将JVM上限内存设置得如此之低,以至于可能的泄漏会导致内存不足。

如果使用的内存达到了这个限制并继续快乐地工作,那么垃圾收集正在完成它的工作。

如果相反它是炸弹,那么你有一个真正的问题……

这似乎并没有泄漏,因为剖析器的图表也说明了这一点。 在某些间隔后,即执行GC时,图形会急剧下降。 如果图表稳定攀升,那将是一次泄漏。 之后剩余的堆空间必须由thread.sleep()使用,并且也可以从探查器的某些代码中使用(如上面的一个答案中所述)。

您可以尝试运行位于%JAVA_HOME%/bin VisualVM并在其中分析您的应用程序。 它还为您提供了随意执行GC和更多选项的选项。

我注意到我使用了更多内存的VisualVM的更多function(高达10MB)。 所以这个增加,它必须来自你的探查器,但它仍然不是泄漏,因为GC上的空间被回收。

没有printlns会发生这种情况吗? 换句话说,可能保持控制台上显示的printlns正在消耗内存。