与Java堆大小作斗争,Java本地和Java web start之间的巨大差异

与Java堆大小作斗争,Java本地和Java web start之间的巨大差异,java,memory,memory-leaks,heap-memory,Java,Memory,Memory Leaks,Heap Memory,上周末我接到一位客户的电话,告诉我他们的Java程序在导入数据时没有响应。数据是一个简单的Excel工作簿,包含4个工作表。所有数据都将从列中读取并添加到数据库中 所以我开始调查,结果有些奇怪 使用运行在Netbeans中测试导入。这使用Java 64位实例: 首轮 第二轮 使用Java Web start测试导入。这是通过打开JNLP文件并使用Java 32位实例启动的: 首轮 在本例中,我遇到了与客户报告的问题相同的问题,程序在执行导入过程一段时间后停止响应。这是因为我正在达到最大堆大

上周末我接到一位客户的电话,告诉我他们的Java程序在导入数据时没有响应。数据是一个简单的Excel工作簿,包含4个工作表。所有数据都将从列中读取并添加到数据库中

所以我开始调查,结果有些奇怪

  • 使用运行在Netbeans中测试导入。这使用Java 64位实例:
  • 首轮

    第二轮

  • 使用Java Web start测试导入。这是通过打开JNLP文件并使用Java 32位实例启动的:
  • 首轮

    在本例中,我遇到了与客户报告的问题相同的问题,程序在执行导入过程一段时间后停止响应。这是因为我正在达到最大堆大小(红色圆圈)

    第二轮

    因此,我决定通过在JNLP文件中添加以下内容来增加初始堆大小和最大堆大小:
    initial heap size=“512m”max heap size=“1024m”
    。当我再次测试导入时,它似乎正常工作,但我注意到与前两种情况相比,使用的内存要多得多:

    • 为什么与案例4相比,案例1和案例2的内存使用量有300mb的差异
    • 这种高内存使用率是由于编程错误还是内存泄漏造成的?或者拥有如此高的价值是正常的吗
    • 添加
      initial heap size=“512m”max heap size=“1024m”
      是否是此问题的有效解决方案

    好吧,明显的区别在于,您的第一次运行是使用
    64位服务器VM
    完成的,后一次运行是使用
    32位客户端VM
    完成的

    据推测,客户机虚拟机是为了在桌面型应用程序中获得更好的可用性而优化的,而服务器虚拟机是为了“服务器”工作而优化的。我并没有一个完整的差异列表(或者它是否真的在实际用例中运行良好)。不要引用我的话,但我确实相信客户端虚拟机比服务器虚拟机更能避免GC,因为它至少有一点被认为是缓慢的。这可以解释为什么客户机VM使用了更多的内存,而不是主动释放内存


    摆弄GC参数有时是正确的做法,在这种情况下,这几乎是唯一可以做的事情,除非您发现任何严重的内存泄漏。无论如何,熟悉GC运行的原因并不是一个坏主意。

    @stackflow我对此表示怀疑。非常感谢您的回答,我通过查看Eden&Old gen space进一步检查了我的应用程序的内存泄漏问题,但没有看到任何惊人的结果。目前,它是固定的初始堆大小和最大堆大小,但我会看看我是否可以优化我的代码更多。我认为内存峰值是由显示/隐藏控件引起的。尽管我猜它应该保留引用,而不是在内存中创建新的引用?是的,如果你只是隐藏一个组件,它就不符合GC的条件。您应该运行内存采样器一段时间,看看是否可以识别任何其他热点。我更改了代码。我做了很多基于用户输入创建实体的数据库请求,总是创建一个客户端对象来处理该请求。似乎这是导致内存问题的原因。现在,我将要创建的所有实体放入包装器中,并在单个请求中创建它们。