处理可预见的Java堆空间不足错误的解决方法

4
我正在开发一个基于Java 6/Tomcat 6.0的Java Web应用程序,它是一个基于Web的文档管理系统。客户可以上传任何类型的文件到该Web应用程序中。上传文件后,将会生成一个新线程,在该线程中对上传的文件进行分析。分析是使用第三方库完成的。
这个第三方库在大约90%的分析工作中表现良好,但有时(取决于上传的文件),逻辑开始使用所有剩余内存,导致OutOfMemoryError。
由于整个应用程序在单个JVM中运行,OoM错误不仅影响分析工作,而且还影响其他功能。在最坏的情况下,应用程序完全崩溃或处于不一致状态。
我现在正在寻找一种相对快速(但安全)的方式来处理这些OoM错误。目前替换库不是一个选项(这就是为什么我既没有提到库的名称,也没有提到进行了什么样的分析)。有人有什么想法可以解决这个错误吗?
我考虑启动一个新进程(java.lang.ProcessBuilder)以获得一个新的JVM。如果第三方库在那里引起OoM错误,它将不会影响Web应用程序。另一方面,这会导致额外的工作来同步新进程和Web应用程序的分析部分。有人对这样的系统有任何经验吗(特别是关于系统稳定性方面)?
更多信息: 1)分析部分可以概括为一种文本提取。该模块接收文件引用作为输入,并将分析结果写入文本文件中。生成的文本文件在Web应用程序的业务逻辑中进一步处理。目前的工作流是同步的。业务逻辑等待第三方库完成其工作。没有排队或其他异步方法。
2)我相当确定第三方库会导致OoM错误。我已经使用不同大小的文件对分析部分进行了隔离测试。导致OoM错误的文件非常小(约4MB)。我已经对该特定文件进行了进一步的测试。在具有256MB堆的JVM中,分析由于OoM错误而崩溃。在具有512MB堆的JVM中进行相同的测试则通过。然而,增加堆大小只能短时间内帮助,因为较大的测试文件再次导致测试由于OoM错误而失败。
3)上传文件的大小限制已经存在;但是,您不能每个文件都有4MB的限制。操作系统和架构也是如此。该系统必须在32位和64位系统(Windows和Linux)上工作。
2个回答

2
这取决于客户端和服务器以及Web应用程序的设计。您需要回答几个问题:
- 分析的结果应该是什么?分析应该在什么时候进行? - 客户端是否等待分析结果? - 返回给客户端的内容是什么?
您还需要确定OOM的性质。
您可能希望将文件上传和文件分析分开处理。例如,您的Web应用程序可以将文件上传到文件系统中的某个位置,然后将分析部分推迟到Web服务,该服务将传递到文件位置的引用。 Web服务可能会异步调用,具体取决于上传文件的客户端在分析出现问题的情况下需要何时接收通知。
所有这些因素都会影响您的决策。
其他考虑因素包括:您使用的JVM是什么,操作系统如何配置系统内存?JVM是32位还是64位,允许上传的最大文件大小是多少,您尝试过哪种垃圾收集器。
从基础设施角度解决这个问题也是可能的,而不是更改代码。限制文件上传的最大大小,从32位转换为64位,更改垃圾收集器,在确定其中一个库中是否存在错误或内存泄漏之后升级库等。
还有一个明显的问题,即“生成了一个线程”。虽然这种做法是可能的,但在JEE世界中通常不被看好。自己生成线程可能会导致容器管理资源的问题。确保您没有自己引起问题,在已知会导致问题的文件上独立进行文件加载测试(如果可以确定)。这将帮助您确定问题是第三方库还是设计问题。

我在原帖中添加了一些关于这个主题的信息,感谢您想要解决“根”问题(OoM错误本身)。长期的解决方案当然是更新或替换有问题的库。 现在,我希望有机会将该库隔离,同时考虑到它会不时地引起OoM错误。 - giesemic

1
为何不针对每个第三方库都有一个(可能是集群的)应用程序来处理文件分析。这些应用程序从您的主应用程序中调用(可能是异步的)。它们传递一个URL,指向应该分析的文件,并返回其分析结果。
当文件上传完成后,分析作业被放入队列中。当分析应用程序再次启动并恢复消费队列中的消息时,它将重新开始。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接