在大型Java项目中处理内存泄漏的最佳实践?

在大型Java项目中处理内存泄漏的最佳实践?,java,performance,tomcat,Java,Performance,Tomcat,在我参与的几乎所有大型Java项目中,我都注意到应用程序的服务质量随着容器的正常运行时间而降低。这很可能是由于代码中的内存泄漏 解决此问题的正确方法显然是追溯问题的根本原因并修复代码中的漏洞。解决这个问题的快捷方法是简单地重新启动Tomcat(或者您正在使用的任何servlet容器) 以下是我的三个问题: 假设您选择通过跟踪问题的根本原因(内存泄漏)来解决问题,您将如何收集数据以放大问题 假设您通过简单地重新启动容器来选择快速而肮脏的加速方式,您将如何收集数据以选择最佳的重新启动周期 您是否能

在我参与的几乎所有大型Java项目中,我都注意到应用程序的服务质量随着容器的正常运行时间而降低。这很可能是由于代码中的内存泄漏

解决此问题的正确方法显然是追溯问题的根本原因并修复代码中的漏洞。解决这个问题的快捷方法是简单地重新启动Tomcat(或者您正在使用的任何servlet容器)

以下是我的三个问题:

  • 假设您选择通过跟踪问题的根本原因(内存泄漏)来解决问题,您将如何收集数据以放大问题

  • 假设您通过简单地重新启动容器来选择快速而肮脏的加速方式,您将如何收集数据以选择最佳的重新启动周期

  • 您是否能够在长时间内部署和运行项目,而无需重新启动servlet容器来恢复快速性?或者偶尔重启一个servlet是必须接受的吗


    • 理想情况下,您不需要重新启动程序或servlet

      我的经验是,造成内存问题的大多数原因通常都是由于一小部分类的分配或池的问题

      像VisualVM这样的工具非常适合这样做,因为您可以找出对象分配的主要部分在哪里

      使用tomcat可能有点棘手,因为您还将监视框架,但只要足够小心和耐心,您通常可以识别逻辑中的热点

      假设您选择通过跟踪问题的根本原因(内存泄漏)来解决问题,您将如何收集数据以放大问题

      使用获取堆转储并使用加载转储。从那里,您可以分析哪些对象消耗的内存最多,哪些“根”阻止收集其他对象,等等

      还有其他堆分析程序,例如,但我发现EMA是最快和最好(免费)的解决方案

      假设您通过简单地重新启动容器来选择快速而肮脏的加速方式,您将如何收集数据以选择最佳的重新启动周期

      使用JMX监视堆大小以及其他堆和GC统计信息

      您是否能够在长时间内部署和运行项目,而无需重新启动servlet容器来恢复快速性


      对。通过避免/修复内存泄漏。

      有一些很棒的分析工具。学习定期使用,了解内存分配输出

      对于应用程序的每个重要功能,基本上都遵循以下流程:

      • 将流程运行一次
      • GC两次
      • 标记所有对象的当前分配计数
      • 再次运行您的流程
      • GC两次
      • 再次标记
      • 区分这两个标记
      如果他们不是非常接近,你可能有泄漏


      如果任何对象计数在该过程的每次迭代中都以给定的数量增长,则绝对存在泄漏。

      即使您的代码没有实际问题,如果您使用apache,也可能存在一些内存泄漏。
      查看提示和建议

      +1,获取简单、无意义的答案。重新启动容器是一个简单的解决方法,但不是一个长期的解决方案。自动化容器重启是一个自动化的解决方案,它有解决方案的一些优点,但也有很多缺点。