Java应用程序内存使用

时间:2010-06-30 01:53:04

标签: java memory memory-leaks

我一直在编写一个小的java应用程序(我的第一个!),目前只做了一些事情。目前,它运行Main类,它启动一个gui类(我编写的一个扩展JFrame的类,只包含一个JTextArea),一个通过大约40kb的BufferedInputStream加载本地文件的类,以及一个从一个类加载一个条目的类。 Java属性文件。

一切都运行得非常好,然而,我正在看着Windows任务管理器,我注意到一些让我感到奇怪的东西。当我启动应用程序时,RAM使用量会在加载本地文件时跳转到大约40MB,并从中提取一些值以显示在JTextArea中,这对我来说是正常的,因为JVM,Java基类等等。但是,当应用程序完成加载文件时,它只是闲置,因为我目前还没有做任何其他事情。当它处于空闲状态时,只要窗口处于活动状态,应用程序的内存使用量就会每秒开始上升10-20kb。这让我很奇怪。如果我点击另一个程序使这个程序成为非活动窗口,内存仍会上升,但速度要慢得多(每3-5秒约10kb)。

我没有测试看它会走多远,但这让我觉得非常奇怪。这是正常的Java行为吗?我想我的代码可能会泄漏内存,但我不确定如何。我确实关闭了我正在使用的BufferedInputStream,我看不出还有什么会导致这种情况。

如果我的解释没有意义,我很抱歉,但我很感激任何人可能有的见解和/或指示。

更新:

根据建议,我基本上将我的应用程序剥离到Main类,它只调用gui类。 gui类只扩展JFrame并设置窗口大小,关闭操作和可见属性。随着这些变化,内存仍然以10-20kb的速度增长,但速度较慢。这与我收到的其他建议相结合,让我相信这只是Java。如果我发现其他任何有趣的东西,我将继续玩它并让大家知道。

5 个答案:

答案 0 :(得分:9)

尝试使用jconsole而不是Windows任务管理器监视堆使用情况:

  • 使用-Dcom.sun.management.jmxremote选项启动您的应用,例如

java -Dcom.sun.management.jmxremote -jar myapp.jar

  • 从命令行启动jconsole,并连接到您在上一步中启动的java进程的本地pid。
  • 点击内存并观看堆内存(默认显示)

如果你观看了一段时间,随着时间的推移,你可能会得到一个“锯齿”的模式,但是当垃圾收集器运行时,它会急剧下降。您可以尝试通过单击如此标记的按钮来“建议”垃圾收集。

执行此操作时,内存使用量是否会下降到相同的最低级别,还是几分钟内总体最小值会增加?如果最小使用量增加,则会出现内存泄漏。如果它总是返回到相同的最低水平,那么你没事。

答案 1 :(得分:2)

祝贺你的第一款应用!现在,有几件事要考虑。首先,Windows任务管理器不是了解vm增长速度的重要资源。相反,您应该在控制台中监视垃圾收集统计信息(使用-verbose:gc命令行参数)。其次,如果您担心潜在的泄漏和虚拟机的增长,那里有许多优秀的剖析器易于使用,可以帮助您诊断内存问题。查看这些two posts以查找某些分析器选项。

答案 2 :(得分:2)

祝贺您的第一个Java应用程序!

Java应用程序在虚拟机中运行。操作系统为虚拟机分配了固定数量的内存,通常为512 MB。只要应用程序使用少于512 MB,垃圾收集器就不会启动并开始搜索“死”内存块。可以在大多数操作系统中修改JVM内存限制。例如,尝试将内存限制切换为32 MB。

答案 3 :(得分:1)

  

这是正常的Java行为吗?

没有

  

我猜我的代码可能会泄漏内存

这绝对是原因。请发布您的源代码,否则无法进一步诊断。

我注意到您使用的是Swing,请确保使用JFrame方法在event dispatch thread中启动invokeLater(Runnable)

如果您使用的是任何类型的集合,请务必在完成后clear

由于您正在执行某些文件IO,因此请确保在完成IO操作后关闭所有涉及的类。

如果您正在使用任何事件侦听器,请记住在不再需要时显式删除事件侦听器。


你可以试试的一件事就是试验。拿你的应用程序并删除文件IO,看看会发生什么。内存使用量是否仍像以前一样攀升?现在将您的应用程序重新设置为正常,并删除文本区域 - 内存是否仍像以前一样爬升?等等。这将帮助您确定源是什么,并且您可以集中精力在那里。很可能你会通过这样做来揭示你的目标。

另一个有用的诊断工具是在特定时间点使用System.gc(),通常在之后繁重的代码块。这将告诉JVM在执行中的该点执行垃圾收集,而不是在内存消耗确定的另一个时间执行垃圾收集。这将有助于您考虑应用程序内存使用量的任何周期性波动。

如果失败,您可以随时使用内存分析器。如果您使用的是Netbeans IDE,那么它就是内置的。对于Eclipse,有几个插件可以执行分析。

答案 4 :(得分:1)

这是正常的。一些背景计算可能会留下死对象,JVM并不急于清理。当接近max mem时,最终它们将被垃圾收集。

让你的程序一夜之间运行,你的机器不会爆炸。