2012-10-17 33 views
8

运行我们的web应用程序遇到复杂的情况的OutOfMemoryError:PermGen的空间 - 同春碧玉报告的Tomcat

它是由STS/Tomcat 7开发的Spring应用程序。应用程序与Jasper report 4.6.0集成后,它总是抛出`OutOfMemoryError:PermGen空间。那么让它工作的唯一方法就是重新启动应用程序。但过了一段时间它又发生了。 这里是登录异常之前:

Oct 17, 2012 3:42:27 PM org.apache.jasper.compiler.TldLocationsCache tldScanJar 
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 
Oct 17, 2012 3:42:30 PM org.apache.catalina.core.ApplicationDispatcher invoke 
SEVERE: Servlet.service() for servlet jsp threw exception 

这里是例外中的一个部分,在那里我发现了一些关于Jasper

at org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:442) 
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:378) 
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:353) 
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:340) 
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:646) 
at org.apache.jasper.servlet.JspServletWrapper.loadTagFile(JspServletWrapper.java:240) 
at org.apache.jasper.compiler.TagFileProcessor.loadTagFile(TagFileProcessor.java:578) 
at org.apache.jasper.compiler.TagFileProcessor.access$000(TagFileProcessor.java:49) 
at org.apache.jasper.compiler.TagFileProcessor$TagFileLoaderVisitor.visit(TagFileProcessor.java:655) 

这里有几个发现时的情况发生:

  1. 该问题可能发生在没有任何Jasper Report组件的页面上。看起来Jasper Report bean在a request is processed by the back end and responded to the front end的时候总是试图找到一个标签库lib。通常从日志文件我可以看到上述异常不会抛出,直到所有后端操作(JPA管理)完成

  2. 当在调试模式下运行log4J时,我看到大量的信息显示类似解析/渲染所有组件碧玉模板(文本框,笔,中...),还有从巨大的日志一小截:

    2012-10-17 15:29:12,025 -- DEBUG -- org.apache.commons.digester.Digester.sax -- startElement(http://jasperreports.sourceforge.net/jasperreports,textElement,textElement) 
    2012-10-17 15:29:12,025 -- DEBUG -- org.apache.commons.digester.Digester -- Pushing body text '' 
    2012-10-17 15:29:12,025 -- DEBUG -- org.apache.commons.digester.Digester -- New match='jasperReport/summary/band/textField/textElement' 
    2012-10-17 15:29:12,025 -- DEBUG -- org.apache.commons.digester.Digester -- Fire begin() for FactoryCreateRule[className=net.sf.jasperreports.engine.xml.JRTextElementFactory, attributeName=null, creat[email protected]12dc6007] 
    2012-10-17 15:29:12,025 -- DEBUG -- org.apache.commons.digester.Digester -- [FactoryCreateRule]{jasperReport/summary/band/textField/textElement} New net.sf.jasperreports.engine.design.JRDesignTextField 
    2012-10-17 15:29:12,025 -- DEBUG -- org.apache.commons.digester.Digester.sax -- ignorableWhitespace() 
    

    然而,当到不网页请求包含任何碧玉组件生成此日志。

我做了一些研究,但仍然找不到解决这个问题的方法。

  1. 的第一个问题是,即使存在时,它甚至没有与当前服务自动连接(这意味着当前页面没有任何碧玉分量)为什么它总是在运行应用程序jasperreport bean。有没有解决方案/这种情况的答案?

  2. 同样来自例外消息 至少有一个JAR针对TLD进行扫描,但尚未包含任何TLD。 (JDTCompiler.java:442) 在org.apache.jasper.compiler.JDTCompiler.generateClass

    应该来自Tomcat和Tomcat never contains any JSTL jar,那么我想也不能找到匹配的TLD解析碧玉报告,因此做一个完整的扫描所有的罐子。如果是这样,那么来自org.apache.commons.digester.Digester的大量调试日志怎么会在解析碧玉模板时看起来很忙呢?

一般情况下,让这个线程只是试图找出一个解决万阿英,蒋达清,也找到一个答案,为什么碧玉是如此活跃的地方并不需要它,以及我们如何能够让tomcat正确地解析了模板?

道歉,如果太详细,并感谢任何提示。

+0

那么,你有没有尝试增加PermGen的大小?这不像其他方式。 –

+0

@Frank Pavageau是我试过了,把它放到512M,但仍然得到同样的问题......它在'catalina.sh'和JAVA_OPTS =“...- XX:MaxPermSize = 512m ...”? – Dreamer

+1

@FrankPavageau看起来jasper报告在某些配置中存在这些问题,因此在jasper报告中对根本原因进行故障排除可能是非常可行的。 – eis

回答

8

谢谢大家给了这个问题的解决方案,我已经明确指出的问题,我的情况和这里是解决方案:

使用.jasper代替.jrxml作为模板!

我们知道.jasper是编译模板以及.jrxml是模板ASCII代码,所以如果我们使用原始源代码文件(JRXML)为模板,在当前弹簧的应用则至少弹性框架的工作要编译源代码文件。这是Spring框架的效率问题,因为它是用来处理编译的jasper bean,并且不保证只编译一次并且只在应用程序启动时发生。

简而言之,在用.jasper文件替换所有模板之后,日志大小已经大大减小,并且还没有看到内存不足的问题。我猜Spring容器可能会消耗大量的资源在运行时将jrxml编译为jasper。所以这可能是Jasper或Spring应该改进的东西......

+0

这正是我需要的感谢.. – Youddh

2

尝试在虚拟机中设置这些参数。这些应该使GC能够清洁您的烫发器。

-XX:+UseConcMarkSweepGC 
-XX:+CMSPermGenSweepingEnabled 
-XX:+CMSClassUnloadingEnabled 
+0

谢谢。你确定我们这样做到JVM而不是Tomcat吗?这种变化是否会对性能产生影响? – Dreamer

+0

PermGen OOM通常发生,因为GC运行但不能释放记忆,不是因为GC没有照顾PermGen。 –

+1

以实际诊断问题所在,您还应该添加'-XX:+ HeapDumpOnOutOfMemoryError',以便获得堆转储。不确定它是否适用于permgen错误,但我建议尝试。堆转储应该通过MAT或类似的方式运行。 – eis

0

由于PermGen的主要包含类的元数据,并不断与实习字符串,你可以在两个方向进行搜索:

  • 检查Web应用程序不包含(太多)无用的罐子,其中由于可能会加载到扫描

  • 使用堆转储看到,如果你有很多常量字符串的(很多大的JSP,例如),或者如果你的代码使用中的String.intern()


实际上,你没有指定你使用的Java版本:在Java 7中,字符串可能不是问题。

你可以做的是用JVisualVM观察应用程序,使用VisualGC插件来查看代的状态,加载的类的数量以及OOM时是否有浪涌,或者如果这是一个缓慢的积累。

7

当JVM中的permgen空间中有太多的.class文件时,由于其对AppClassLoader外部的对象的引用而无法进行垃圾回收,因此发生异常。它通常指出一些内存泄漏你的应用程序。

This后有一个java.lang.OutOfMemoryError的清晰解释:PermGen空间错误和以下post有如何解决它的建议。 在SO上询问了一个类似(但不完全一样)的question,让你知道你是否错过了它。我希望它有帮助。

正如jakub提到的设置-XX:+CMSClassUnloadingEnabled-XX:+CMSPermGenSweepingEnabled或设置更高的值XX:MaxPermSize可能适合你。但从我所读到的看来,这似乎并不是一个永久的解决方案。 (我不是这方面的主人:))。

+0

链接上的好帖子。如果有人需要更好地了解正在发生的事情,请阅读这些帖子。谢谢。 –

2

我已经开发出使用JasperReports的4.5.1

我使用Tomcat 6.0.26作为容器的Web应用程序。 (Win7的,JDK 1.6.0_25)

当关闭Tomcat的,它扔:

web应用创建一个ThreadLocal类型的键[net.sf.jasperreports.engine.util.JRFontUtil $ 1](值[[email protected]])和一个类型为[java.util.HashSet](值为[[]]的值),但是当Web应用程序停止时无法删除它。 这很可能会造成内存泄漏。

,请访问网站:

http://community.jaspersoft.com/questions/534340/memory-leak-jr-373