我有一个Java应用程序,它将另一个jar作为库导入并调用其main方法,如下所示。但someApp
是一个非常大的过程,不断抛出OutOfMemoryError
。无论我将Java应用程序堆大小设置为什么,someApp
似乎都不共享已分配的内存。
try {
someApp.main(args);
} catch (Exception ex) {
}
如何让someApp
分配更多堆空间?我可以使用processBuilder
吗?我该怎么办?
感谢。
答案 0 :(得分:3)
目前,您只是在自己的Java进程中从另一个应用程序调用一个类。这与调用“库方法”完全相同(该术语没有技术差异,您只是在类的对象上调用可由类加载器解析的方法)。
现在,someApp
与您自己的应用程序在同一个JVM中运行,并将共享其最大堆大小。这可以通过JVM参数-Xmx
(例如-Xmx2048m
增加2GB最大堆)来增加,但听起来你已经这样做了,并且已经成功了。
可以在单独的Java进程中启动someApp
,这将允许您配置单独的JVM参数,从而为其提供单独的堆大小。
但是,我认为这不会有太大帮助。如果您无法让这个应用程序在同一个JVM中运行,那么无论您的堆限制如何,都没有任何迹象表明它可以在差异JVM中运行。例如,如果你运行2.5GB堆并且内存不足,运行自己的0.5GB堆应用程序并生成一个2GB堆的单独JVM将不解决问题,因为某些东西仍在耗尽内存。 (事实上,由于存在两个不同的可用空间块,因此单独的内存池使OOME更容易发生,而在前一种情况下,两个应用程序都可以从相同的可用空间池中受益)。
我建议您验证您的堆大小是否真正被拾取(使用JConsole或JVisualVM通过JMX连接将很快让您看到最大堆大小有多大)。如果你真的仍然没有大堆的内存,听起来someApp
有内存泄漏(或者需要甚至更大的堆)。在这种情况下使用JVM参数-XX:+HeapDumpOnOutOfMemoryError
捕获堆转储将允许您使用外部工具检查堆并确定填充内存的内容。
希望你只是无法正确地增加堆大小,就好像应用程序确实因大堆而失败而没有简单的解决方案。
答案 1 :(得分:1)
除非someApp
本身正在构建一个新进程,否则它将与您的调用代码处于同一进程中,因此应该受到您在设置时设置的任何堆配置的影响启动JVM。
您是否记录了该过程实际承受的内存量?
答案 2 :(得分:1)
这没有任何意义,除非您在OS上限制了可以为操作系统上的单个Java进程分配多少内存(参见Java maximum memory on Windows XP)
除此之外,您调用someApp的方式,它充当常规库。主要方法就像任何其他方法一样。
您是否尝试过调试OutOfMemoryError?应用程序可能不喜欢从您的应用程序中调用...
答案 3 :(得分:1)
如果您导入的jar是由您创作的并且可能更有效,那么请对其进行修改。听起来你遇到的问题是装在一个小装备中。如果这是第三方软件包并且您可以修改它,请在代码中查找并查找可能存在限制的位置,更改它并重新构建它。