2012-12-10 73 views
2

试图检测在web应用程序内存泄漏。内存泄漏和GC根

  • 在崩溃时采取应用程序的堆转储。
  • 使用eclipse MAT来解析转储。

从解析整理信息导致这些结论2 -

  1. 对象占用更多的内存不具有GC根。基本上,每当GC发生时,他们都会被清理干净。
  2. GC根中的对象占用的内存要少得多。所以这些可能不是内存泄漏(?)的根本原因。

那么,这是否意味着没有泄漏发生?并且由于内存不足错误而发生崩溃?

编辑:添加ENV信息

  • 我在Tomcat上运行的Java web应用程序6.
  • web应用程序是基于openreports(报告工具)

添加的输入参考列表最大客体 -

http://imgur.com/lYrju

这里每个散列映射实例都有一个来自com.opensymphony.xwork2的引用,它不是GC收集的。这可能是问题的根源吗?由于Tomcat的日志说 -

SEVERE: The web application [/openreports] created a ThreadLocal with key of type [com.opensymphony.xwork2.ActionContext.ActionContextThreadLocal] (value [[email protected]c45901a]) and a value of type [com.opensymphony.xwork2.ActionContext] (value [[email protected]]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak. 
SEVERE: The web application [/openreports] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [[email protected]]) and a value of type [com.opensymphony.xwork2.inject.InternalContext[]] (value [[Lcom.opensymphony.xwork2.inject.InternalContext;@1484fc8d]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak. 

编辑:添加

java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOfRange(Arrays.java:3209) 
     at java.lang.String.<init>(String.java:215) 
     at java.lang.StringBuffer.toString(StringBuffer.java:585) 
     at java.io.StringWriter.toString(StringWriter.java:193) 
     at org.displaytag.tags.TableTag.writeExport(TableTag.java:1503) 
     at org.displaytag.tags.TableTag.doExport(TableTag.java:1454) 
     at org.displaytag.tags.TableTag.doEndTag(TableTag.java:1309) 
     at org.efs.openreports.engine.QueryReportEngine.generateReport(QueryReportEngine.java:198) 
     at org.efs.openreports.util.ScheduledReportJob.execute(ScheduledReportJob.java:173) 
     at org.quartz.core.JobRunShell.run(JobRunShell.java:202) 
     at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529) 
10:01:04,193 ERROR ErrorLogger - Job (90.70|1338960412084 threw an exception. 
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.OutOfMemoryError: Java heap space] 
     at org.quartz.core.JobRunShell.run(JobRunShell.java:213) 
     at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529) 
Caused by: java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOfRange(Arrays.java:3209) 
     at java.lang.String.<init>(String.java:215) 
     at java.lang.StringBuffer.toString(StringBuffer.java:585) 
     at java.io.StringWriter.toString(StringWriter.java:193) 
     at org.displaytag.tags.TableTag.writeExport(TableTag.java:1503) 
     at org.displaytag.tags.TableTag.doExport(TableTag.java:1454) 
     at org.displaytag.tags.TableTag.doEndTag(TableTag.java:1309) 
     at org.efs.openreports.engine.QueryReportEngine.generateReport(QueryReportEngine.java:198) 
     at org.efs.openreports.util.ScheduledReportJob.execute(ScheduledReportJob.java:173) 
     at org.quartz.core.JobRunShell.run(JobRunShell.java:202) 
+0

你是否有你的OOM错误的堆栈跟踪? –

+0

添加了oom – amrk7

回答

0

你运行ASP.NET的WebForms(不MVC)应用OOM错误的堆栈跟踪?我们在应用程序中遇到类似的问题,这是我们遇到的问题。首先,我应该说明我们的网络农场由许多应用程序池组成,当然每个客户端都有一个应用程序池。每个应用程序池都有特定的内存限制,以确保客户端不会失去控制并影响其他工作进程。

1)即使对象不扎根,如果他们是在85K它们将被放置在大对象堆,其.NET的GC不紧凑。这意味着如果你有一个100K的对象,它会坐在LOH上。当物体被清理后,你会得到你的100K,GC可能会决定把其他东西放在那个洞里。由于它没有压缩,你永远不能保证空间完全被填满。这会在未完全填满的空间留下空洞,并导致内存碎片化。解决这个问题的唯一方法是检查你的转储文件,看看哪些对象占据了最大的空间,并确定可以削减的类/集合。您可能会看到很多对象数组和字符串,因为这些对象在缓存管理器等中通常很大。

2)你处置情况的?等到终结器线程进入清理实例不应该是默认情况,因为这会导致糟糕的GC性能。确保你正在处理所有在其继承中实现IDisposable接口的类。提前调用Dispose意味着资源以确定性方式发布,而取决于终结器意味着清理可能会发生得太久(如果有的话)。 3)如果发生OutOfMemoryExceptions,可能是由于两个原因:您用完托管内存(对于设置了限制的工作进程很少使用,因为它将被回收),或者用尽了虚拟内存,因为如果您在32位IIS应用程序中运行,则限制为2GB的虚拟内存会更糟糕。在生产中,我们也看到了这个问题,其中GC分配了64MB大块堆(工作站模式下为32GB),一旦接近2GB限制并且无法分配更多空间,则抛出异常(请参阅:Should we use "workstation" garbage collection or "server" garbage collection?)。如果是这种情况,那么您可能会泄漏一个托管资源,它根植于某个静态项目,或者您没有使用 - =运算符删除它们来清理事件处理程序。

如果您可以发布您的转储文件或至少它的相关部分,它会更容易看到问题的所在。但从你的简短描述来看,这些都是我会看到的项目。

+0

*的堆栈跟踪。所以在这种情况下,LOH不应该成为问题,因为这个应用程序会频繁发生gc。 *您的第二点是wat在应用程序中发生的原因tomcat表示其中一个线程已启动但从未停止(com.opensymphony.xwork2 ..) – amrk7

+1

道歉,因为您的原始问题未标记为Java应用程序,我是在假设它是一个.NET的。您几乎可以放心地忽略上述所有内容。至于你的问题,它看起来像你存储在线程本地存储(TLS)的一些数据?当您的应用程序被拆除时,您是否将其移除并清理?如果这只是在应用程序拆卸时发生的,它不应该引起任何问题,因为整个过程应该被拆除。但是,你应该仍然是一个好公民并将其移除。你是否清除该HashMap或它所属的东西? – Mike

+0

您还应该标记您正在使用哪种语言,以便其他人可以发现此问题。 – Mike