Java 可能的内存泄漏?

Java 可能的内存泄漏?,java,memory-management,memory-leaks,profiling,Java,Memory Management,Memory Leaks,Profiling,我有一个正在运行的java webapp,我正在用visualVM监控它 下面是堆的图表: 测试了两组请求,一组在3:20,另一组在4:40(它们在图中表示为仅有的两个峰值) 我的问题是:这是否意味着我有内存泄漏?我担心的是中间部分,虽然GC在运行,但堆始终保持在250MB 非常感谢您的见解。您是说在3:20之前没有请求吗?如果是这样,我会说我没有看到任何泄漏的证据 我不知道你的应用程序,但在JVM的生命周期中,当应用程序第一次使用时,一些对象会被初始化,这是典型的(基于架构/设计)。你在使

我有一个正在运行的java webapp,我正在用visualVM监控它

下面是堆的图表:

测试了两组请求,一组在3:20,另一组在4:40(它们在图中表示为仅有的两个峰值)

我的问题是:这是否意味着我有内存泄漏?我担心的是中间部分,虽然GC在运行,但堆始终保持在250MB


非常感谢您的见解。

您是说在3:20之前没有请求吗?如果是这样,我会说我没有看到任何泄漏的证据


我不知道你的应用程序,但在JVM的生命周期中,当应用程序第一次使用时,一些对象会被初始化,这是典型的(基于架构/设计)。

你在使用什么JRE?哪些堆/GC相关参数被传递给应用程序

峰值并不坏(如果服务器有更多的任务要做,那么峰值增加是有道理的)。但是看起来不太好的是,4:40之后的水位(当负荷再次降低时)与负荷上升之前的水位一样高。但它不需要是

现在您应该了解更多细节,哪些对象或对象图保存在堆中。因此,再次执行相同的测试运行,包括(使用探查器):

  • 在负载上升之前拍摄堆快照
  • 在负载下降后拍摄堆快照(确保执行手动GC触发器)

现在,您应该分析差异,以及是否看到本应被丢弃的奇怪对象。

3:20的第一个请求导致一些内存被保留,但请注意,第二个请求后的GCs回收了大部分内存。而且我认为主要的GC是在4:40第二次请求之后才执行的

看起来没有漏水。我的理论是,3:20的请求导致年轻一代填满了,由此产生的次要GC将一些对象提升到了老一代。由4:40的请求引起的下一个主要GC清除了大部分


您可以通过使用探查器在发出与3:20时发出的请求相同的请求之前标记堆来验证这一点,强制执行完整GC,然后检查哪些对象处于延迟状态。我不确定VisualVM是否允许您(1)标记堆和(2)强制执行完整GC,但它用于执行此操作。

JvisualVM允许您强制执行垃圾收集


试着用它看看会发生什么。

这里的内存泄漏是什么意思?我不认为像SUN这样的好JVM实现会有如此疯狂的bug。当您没有对内存位置的引用(僵尸)或者您没有任何可能回收它时,内存泄漏字是理想的使用方法。如果您有错误的编程实践,您持有对不再使用的对象的引用,并且这些对象的作用域(寿命)更大,那么您会消耗更多的内存,而不给GC重新收集它的选项。

样本大小为2并不能真正提供足够的信息来声明泄漏。是的,一个可能隐藏在该图中:最右边的分配大小大于最左边的分配大小。或者,正如比尼尔所提到的,可能只是一些对象被提升到了终身生成中,而您没有一个主要的GC。实际上,确定是否存在泄漏的唯一方法是比较随时间保留的活动对象的数量。我在这里发表了一篇文章()讨论了如何分析堆转储。非常感谢binil。你能给我一份很好的参考文档,让我了解所有这些概念吗?(年轻一代、老一代、不同类型的GC运行等等)确实,对
visualGC
插件的进一步检查表明,对象被提升到了堆的另一部分。它实际上是强制的,还是调用System.GC()?我相信它强制的。也许它只是Sun JVM。它实际上调用
System.gc()
它不强制执行任何操作。