- 操作系统:Windows Server 2008 R2 SP1
- 网络服务器:IIS 7.5
- JSP/Servlet 引擎:Tomcat 5.5.28(32 位)
- PHP: 5.4.14
- Java:JRE SE 1.6.0_20(32 位)
- Apache Isapi 连接器从 IIS 挂钩到 Tomcat
- PHP-Java 桥 6.2.1
- BMC AR 系统 7.5 补丁 6
- Tomcat 初始和最大内存:1024 MB、1024 MB
我正在使用一个名为 AR System 的 Java Web 应用程序。安装 PHP-Java Bridge 后,我开始在 Tomcat 日志中看到java.lang.OutOfMemoryError: PermGen space 错误。(我在 Windows 任务管理器中看到有 6 个 PHP-CGI.exe 进程,在内存占用方面都相似,给或取 5 MB)。它会每隔一天左右发生一次,然后缩短为每天,有时一天两次。因此,应用程序挂起,我必须重新启动它。我添加了一个 Windows 任务以在非高峰时间重新启动 Tomcat,以给我一些缓冲。我怀疑内存泄漏并开始做一些研究。通常,Tomcat 的大小约为 300-350 MB。使用 PHP-Java Bridge,内存显着增加。事实上,错误发生在 450-600 MB 的任何地方。
我了解到默认 PermGen 是 64MB,PermGen 应该设置为 1/4,最多 Tomcat 内存的 1/3(抱歉,我不记得链接了)。此时 Tomcat 正在 Windows 服务下运行,我在其属性中添加了以下内容:
- -XX:+UseConcMarkSweepGC
- -XX:+CMSPermGenSweepingEnabled
- -XX:+CMSClassUnloadingEnabled
- -XX:PermSize=128M
- -XX:MaxPermSize=256M
我在 PermGen 内存上强制执行 GC,并将大小从默认的 64 MB 大小增加到 128-256 MB。内存一直缓慢上升到 800-850 MB,但在高峰时段并没有挂起,尽管我仍然通过 Windows 任务在非高峰时段故意重启 Tomcat。如果我重新启动,它最终可能会挂起,但我还没有尝试过。
我仍然怀疑内存泄漏。我安装了 AppDynamics 的试用版来监控应用程序、它的内存并运行泄漏检测。此外,为了使用 VisualVM 和 Memory Analyzer (MAT) 等工具,我禁用了 Tomcat Windows 服务,并通过 catalina.bat 从 Windows 命令行运行 Tomcat。我在文件中附加了 Java 选项;我确保 Tomcat 内存为 1024 MB,Perm Gen 为 128/256 MB,并确保 PHP-Java Bridge 和 AppDynamics 正在运行。截至目前,PermGen 的使用量保持在 163 MB,并且 AppDynamic 的自动泄漏检测没有检测到任何 Java 集合的任何泄漏。
我启动了 MAT,创建了一个堆转储并分析了泄漏。当我昨天运行它时,它发现了三个可能的嫌疑人:
- net.sf.ehcache.Cache
- net.sf.ehcache.store.DiskStore
- org.apache.catalina.loader.WebappClassLoader
当我今天运行它时,它发现了 2 个可能的嫌疑人:
- java.util.HashMap
- org.apache.jasper.servlet.JasperLoader
因此,对于 MAT 和 AppDynamics,似乎没有检测到与 PHP-Java Bridge JAR 文件直接相关的类的内存泄漏。我没有尝试使用 Plumbr,但我找不到免费的 beta 版本。免费版本检测泄漏,但您必须付费才能看到它。
同样,我此时没有源链接,但我记得读过 Tomcat 5.x可能存在性能和内存泄漏问题。当然,这并不意味着每个人都会遇到这些问题,只是一个选定的数字。我知道 Tomcat 6 和 Tomcat 7 重新设计了它们的内存管理或它们如何构造内存。我也确实与来自 BMC(AR System 的制造商)的人进行了交谈,他们说我正在使用的当前版本的 AR System 可能会遇到性能和内存问题。但是,在 PHP-Java Bridge 出现之前,这一切都不是问题。只有在我安装它之后,这个 PermGen 内存问题才开始。
由于上述工具没有报告任何泄漏,这是否意味着没有泄漏并且 PHP-Java Bridge 只需要 64 MB 以上的 PermGen 内存?或者,我的 Tomcat 版本是否存在继承问题并且安装 PHP-Java 桥只是打破了众所周知的骆驼背?
升级到更新版本的 AR System 和 Tomcat 不是一种选择。如果有泄漏,我可以卸载 PHP-Java Bridge 或继续尝试查找泄漏并修复它。
任何帮助,将不胜感激。
谢谢你。
更新 1
使用 MAT,我查看了线程概述和堆栈,您可以在下面看到 PHP-Java 桥贡献了 Tomcat 总堆内存的大约 2/3。那是很多记忆!我认为有泄漏,我有。我找不到有关具有继承内存泄漏问题的 PHP-Java 桥的任何信息。但是,对我来说,问题似乎不在于 Tomcat 正在泄漏。想法?
即使我手动添加了 MAT 中怀疑的类,AppDynamics 也找不到任何泄漏。我想知道的是 PermGen 错误可能是程序没有泄漏并且需要分配更多 PermGen 内存的情况的症状。了解 PHP-Java 桥是否被设计为消耗大量内存,这么多内存会很有帮助;也许它针对 64 位进行了优化,因为当前设置是 32 位 Java Web 应用程序。如果我知道这座桥需要大量内存,我会说好的,好的,然后从那里开始。但它肯定看起来好像在链中的某个地方存在内存泄漏。
更新 2
我现在已经运行 Plumbr 2 小时将近 10 分钟。我看到 Tomcat 内存正在飙升至 960 MB,并且可能会继续攀升。对于熟悉程序的人,Java Web 应用程序已经分析了 3 次。到目前为止,尚未报告任何泄漏。如果它保持这种状态,那么我得出的两个结论是 a) 没有泄漏或 b) 有泄漏,不知何故,AppDynamics 和 Plumbr 都错过了它。如果这组应用程序一起工作确实没有泄漏,那么一定是 Bridge 使用了大量内存并且需要比 Tomcat 的默认值 64 MB 更多的 PermGen 内存——至少对于 32 位 Java web应用程序。