OutOfMemoryError:PermGen Space - 在Tomcat上运行Spring的Jasper报告

Dre*_*mer 8 java spring tomcat jstl jasper-reports

我们的Web应用程序遇到了复杂的情况

它是由STS /开发的Spring应用程序Tomcat 7.应用程序集成后Jasper report 4.6.0,它总是抛出`OutOfMemoryError:PermGen Space.然后,让它工作的唯一方法是重新启动应用程序.但过了一段时间它又发生了.这是异常之前的日志:

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
Run Code Online (Sandbox Code Playgroud)

这是异常中我发现的一些内容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)
Run Code Online (Sandbox Code Playgroud)

当情况发生时,以下是一些调查结果:

  1. 问题可能发生在页面上,没有任何Jasper Report组件.似乎Jasper Report bean一直试图找到一个标记库a request is processed by the back end and responded to the front end.通常从日志文件中我可以看到,在所有后端操作(JPA管理)完成之前,异常不会抛出

  2. 在调试模式下运行log4J时,我看到大量信息显示解析/呈现Jasper模板中的所有组件(文本字段,笔,框...),从巨大的日志中有一小部分:

    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, creationFactory=net.sf.jasperreports.engine.xml.JRTextElementFactory@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()
    
    Run Code Online (Sandbox Code Playgroud)

    但是,当对页面的请求不包含任何Jasper组件时,会生成此日志.

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

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

  2. 同样来自异常消息至少有一个JAR被扫描用于尚未包含TLD的TLD.在org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:442)

    应该来自Tomcat,Tomcat never contains any JSTL jar然后我认为它无法找到匹配TLD来解析jasper报告,因此对所有jar进行全面扫描.如果是这样,那么为什么大量的调试日志org.apache.commons.digester.Digester实际上似乎正忙于解析jasper模板呢?

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

如果过于冗长,请道歉,并感谢任何提示.

Dre*_*mer 9

谢谢大家为这个问题提供解决方案,我已经根据我的情况确定了问题,这是解决方案:

使用.jasper而不是.jrxml作为模板!

我们知道的.jasper是一个编译模板以及模板的.jrxmlASCII源代码,所以如果我们在当前的spring应用程序中使用原始源代码文件(jrxml)作为模板,那么至少spring框架工作必须编译源代码文件.这是一个留给Spring框架的效率问题,因为它是处理编译的jasper bean,并且不能保证编译只执行一次并且只在应用程序启动时才会发生.

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


sha*_*ltc 7

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

这篇文章清楚地解释了java.lang.OutOfMemoryError:PermGen空间错误,以下帖子提供了有关如何修复它的建议.在SO上问了一个类似的(但不完全相同的)问题,如果你错过了它就会告诉你.我希望它有所帮助.

正如jakub提到设置-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled或设置更高的值XX:MaxPermSize可能适合你.但据我所知,它似乎不是一个永久的解决方案.(我不是这里的主人:)).