OutOfMemoryError: PermGen Space - Jasper report with Spring runs on Tomcat

Our web application is facing a difficult situation

This is a Spring application developed by STS / Tomcat 7 . After the application has been integrated with Jasper report 4.6.0 , it always throws `OutOfMemoryError: PermGen Space. Then the only way to make it work is to restart the application. But after a while this will happen again. Here is the log before the exception:

 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 

Here is a section within the exception where I found something about 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) 

Here are a few conclusions when a situation arises:

  • A problem can occur on the page without any Jasper Report components. It seems the Jasper Report bean is trying to find the lib tag all the time when a request is processed by the back end and responded to the front end . Usually, from the log file that I see above, an exception will not be thrown until all final operations (JPA control) are completed

  • When I start log4J in debug mode, I see a lot of information displaying something like parsing / rendering of all components from the Jasper template (text fields, pen, field ...), there is a small section from a huge log

     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() 

    However, this log is generated when a page is requested that does not contain a Jasper component.

I have done some research, but still can not find a solution to this problem.

  • The first question is that there is a jasperreport bean in the application, why it always works when it is not even autovexed with the current service (which means that there is no jasper component on the current page). Is there a solution / answer to this situation?

  • Also from the exception message At least one JAR was scanned for a TLD but did not contain a TLD. at org.apache.jasper.compiler.JDTCompiler.generateClass (JDTCompiler.java:442)

    should come from Tomcat and Tomcat never contains any JSTL jar , then I assume that it cannot find a matching TLD to parse the jasper report, so do a full scan of all the jars. If so, how did it happen that the sheer amount of debug logs from org.apache.commons.digester.Digester really seems busy when parsing the jasper template?

In general, make this thread just try to find a solution to the problem, and also find the answer to why Jasper is so active in place, does not require it, and how can we let tomcat parse the templates correctly?

Sorry if too verbose and thanks for any tips.

+8
java spring tomcat jasper-reports jstl
source share
5 answers

Thanks to everyone for giving a solution to this problem, I specifically pointed out the problem to my situation, and here is the solution:

Use .jasper instead of .jrxml as a template!

As we know, .jasper is a compiled template, and .jrxml is the ASCII source code for the template, so if we use the source code (jrxml) as the template in the current spring application, then at least spring frame work should compile the file source code. This is a matter of efficiency, left up to the spring framework, since it is a jasper bean for compilation processing, and it is not guaranteed that compilation is performed only once and only happens when the application starts.

In short, after replacing all the templates with a .jasper file, the log size was significantly reduced and no longer saw a memory problem. I think a spring container can consume a lot of resources to compile jrxml into jasper at runtime. So maybe something should improve Jasper or Spring ....

+8
source share

An exception occurs when there are too many .class files in the permgen space in the JVM that cannot be garbage collected because of its references to an object outside of AppClassLoader. This usually indicates that some kind of memory leak is related to your application.

This post has a clear explanation of java.lang.OutOfMemoryError: a PermGen space error and the following contains suggestions for fixing it. A similar (but not quite the same) question was asked so that you know if you missed it. Hope this helps.

As jakub said, setting -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled or setting a higher value for XX:MaxPermSize may work for you. But from what I read, this is not a permanent solution. (I'm not a master at this :)).

+7
source share

Try to configure these settings on your virtual machine. They should include the GC cleanup of your permanent.

 -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled 
+2
source share

I developed a web application that uses JasperReports 4.5.1

I am using Tomcat 6.0.26 as a container. (Win7, JDK 1.6.0_25)

When turning off tomcat, it throws:

The web application created ThreadLocal with a key of type [net.sf.jasperreports.engine.util.JRFontUtil $ 1] (value [net.sf.jasperreports.engine.util.JRFontUtil$1@7892f1]) and type value [java.util.HashSet ] (value [[]]), but could not delete it when the web application was stopped. This will probably lead to a memory leak.

Visit website:

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

+2
source share

Since PermGen mainly contains class metadata, as well as constant and interned strings, you can search in two directions:

  • check that the webapp does not contain (too many) useless cans that can be downloaded due to scanning

  • see if you have a lot of persistent strings (like a lot of big JSPs) using a dump heap or if String.intern () is used in your code


In fact, you did not indicate which version of Java you used: with Java 7, the string may not be a problem.

What you can do is observe the application using JVisualVM using the VisualGC plugin to see the status of the generations, the number of classes loaded and the presence of a spike either during OOM or if it is a slow build.

0
source share

All Articles