当前位置: 代码迷 >> java >> Java应用程序内存使用
  详细解决方案

Java应用程序内存使用

热度:31   发布时间:2023-07-27 09:27:15.0

我一直在写一个小的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。 如果我发现其他任何有趣的东西,我将继续玩它,让大家都知道。

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

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

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

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

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

当你这样做时,内存使用量是否下降到相同的最低水平,或者是几分钟内总体最小值的增加? 如果最小使用量增加,则会出现内存泄漏。 如果它总是返回到相同的最低水平,那么你没事。

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

恭喜您的第一个Java应用程序!

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

这是正常的Java行为吗?

没有。

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

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

我注意到您正在使用Swing,请确保使用invokeLater(Runnable)方法在中启动JFrame

如果您正在使用任何类型的集合,请确保在完成后clear它们。

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

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


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

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

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

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

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

  相关解决方案