我写了一个与数据库一起使用的简单应用程序。我的程序有一个表来显示数据库中的数据。当我尝试扩展框架时,程序因OutOfMemory错误而失败,但是如果我不尝试这样做,它就可以正常工作。
我用-Xmx4m参数启动我的程序。是否真的需要超过4兆字节才能处于扩展状态?
另一个问题:如果我运行java visualVM,我会看到程序堆使用情况的锯齿图表,而其他使用java VM的程序(如netbeans)则有更多的直线图表。为什么我的程序的堆使用如此不稳定,即使它什么都不做(只等待用户按下按钮)?
答案 0 :(得分:1)
为什么要将最大堆大小设置为4兆字节? Java通常是内存密集型的,因此将其置于如此低得可怜的低水平是一种灾难。
它还取决于代码创建和销毁的对象数量,并且底层的Swing(我假设)组件使用组件来绘制元素,以及每次重新绘制组件时如何创建和销毁这些元素。 查看CellRenderer代码,这将显示为什么经常创建和销毁对象,以及为什么垃圾收集器做得非常好。
尝试使用Xmx设置,看看图表是如何变平的。我希望Xmx64m或Xmx128m是合适的(尽管数据库中出现的数据量显然是一个重要的因素。
答案 1 :(得分:1)
如果使用双缓冲区,则扩展屏幕的GUI可能需要4Mb以上。这将生成UI的多个图像。它这样做是为了在屏幕上快速显示它们。通常这是假设你有很多很多内存来完成的。
Sawtooth内存分配是由于某些事情已经完成,然后是垃圾收集。这可能是重绘操作或其他计时器。您的代码中是否有计时器来检查某些进程或值是否已更改。或者您是否已将代码添加到对象重绘或其他进程?
答案 2 :(得分:1)
您可能想尝试设置此值以生成详细的堆转储,以准确显示正在发生的事情。
-XX:+ HeapDumpOnOutOfMemoryError
2011年典型的“小型”Java桌面应用程序将运行~64-128MB。除非你有迫切需要,否则我会先把它设置为默认值(即没有设置)。
如果您尝试做一些不同的事情(例如在Android设备上运行),您将需要非常熟悉分析(并且您应该使用该标记发布)。
请记住,如果要存储字符数据(Java在内部使用UCS-16),那么100个记录缓存(~12个字节)可能(可能)是两倍。
RE:“不稳定”,JVM正在为你处理内存使用情况,并将根据它选择的任何算法执行垃圾收集(这些已经多年来发生了巨大的变化)。图形可能只是工具和样本周期的工件。桌面应用程序中的性能受巨大多个因素的影响。
作为一个例子,我们曾经有一个巨大的内存“泄漏”,只出现在一个自动化测试中,但从未出现在正常的现实世界中。原来测试让鼠标悬停在工具提示上,工具提示包含打开文件的名称,而后者又有一组引用回到整个(巨大的)项目。摆动鼠标几个像素摆脱了工具提示,这意味着所有引用都被清除,垃圾收集器取出了垃圾。
故事的道德?您需要在内存不足时捕获确切的堆转储,并仔细检查它。
答案 3 :(得分:0)
我认为4mb对于除了一个简单的程序之外的任何东西都太小了 - 例如,许多GUI库(包括Swing)将需要为图形分配临时工作空间,单独可能超过该数量。
如果您想避免内存不足错误但又想避免过度分配内存到JVM,我建议设置大的最大堆大小和小的初始堆大小强>