OutOfMemoryError: PermGen Space -- Jasper Report with Spring running on Tomcat
Solution 1
Thank you everyone for giving solution about this issue, I have identified the problem specifically to my situation and here is the solution:
Use .jasper instead of .jrxml as template !
As we know .jasper
is a compiled template as well as .jrxml
is ASCII source code for the template, so if we use raw source code file (jrxml) as template in current spring application then at least spring frame work has to compile the source code file. That's a question of efficiency left to Spring framework as it is the jasper bean to handle the compilation and it is not guaranteed the compilation executed only once and only happens when the application starting.
In short, after replace all templates with .jasper file, the log size has been significantly reduced and haven't seen the out of memory issue any more. I guess Spring container may be consume a lot of resource to compile jrxml to jasper at runtime. So it could be something should've improved by Jasper or Spring....
Solution 2
The exception occurs when there are too many .class files in the permgen space in the JVM which cannot be garbage collected due to its references to an object outside the AppClassLoader. It generally points out to some memory leak your applciation.
This post has a lucid explanation of java.lang.OutOfMemoryError: PermGen space error and a following post has suggestions on how to fix it. A similiar (but not exactly the same) question was asked on SO, letting you know if you missed it. I hope it helps.
As jakub has mentioned setting -XX:+CMSClassUnloadingEnabled
-XX:+CMSPermGenSweepingEnabled
or setting a higher value for XX:MaxPermSize
might work for you. But from what I have read, it isn't a permanent solution it seems. (I am not a master in this :)).
Solution 3
Try setting these parameters in your VM. These should enable GC cleaning your permGen.
-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
Solution 4
I have developed a web application which uses JasperReports 4.5.1
I use Tomcat 6.0.26 as a container. (Win7, JDK 1.6.0_25)
When shutdown the tomcat,it throw :
The web application created a ThreadLocal with key of type [net.sf.jasperreports.engine.util.JRFontUtil$1] (value [net.sf.jasperreports.engine.util.JRFontUtil$1@7892f1]) and a value of type [java.util.HashSet] (value [[]]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Please visit the website:
http://community.jaspersoft.com/questions/534340/memory-leak-jr-373
Dreamer
Updated on July 29, 2022Comments
-
Dreamer almost 2 years
Our web application encounter a complicated situation
It is a Spring application developed by STS/
Tomcat 7
. After the application been integrated withJasper report 4.6.0
, it always throw `OutOfMemoryError: PermGen Space. Then the only way to get it work is to restart the application. But after a while it happen again. Here is 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 findings when the situation occurs:
The issue can happen on page without any Jasper Report components. It seems the Jasper Report bean is trying to find a tag lib all the time when
a request is processed by the back end and responded to the front end
. Normally from log file I can see above exception will not throw until all back end operations(JPA management) are completeWhen run log4J on debug mode, I see tons of information showing something like parsing/rendering the all components from Jasper template(textfields, pen, box...), there is a small cut from the 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()
Still, this log is generated when a request to the page which does not contains any Jasper component.
I did some research but still cannot find the solution to this issue.
The first question is even there is a
jasperreport bean
in the application why it is always running when it is not even autowired with current service(meaning current page doesn't have any jasper component). Is there a solution/answer to this situation?Also from the exception message At least one JAR was scanned for TLDs yet contained no TLDs. at org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:442)
should comes from Tomcat, and
Tomcat never contains any JSTL jar
, then I assume it cannot find a match TLD to parse jasper report hence do a full scan of all jars. If so, then how come there is huge amount of debug logs fromorg.apache.commons.digester.Digester
actually seems busy on parsing the jasper template?
In general, make this thread is just try to figure out a solution to the probelm, and also find an answer to why Jasper is so active on a place doesn't require it, and how we can let tomcat properly parsed the templates?
Apologize if too verbose, and thanks for any hints.
-
Dreamer over 11 yearsThank you. Are you sure we do this to the JVM not Tomcat? Is there performance impact by this change?
-
Frank Pavageau over 11 yearsThe PermGen OOM usually occurs because the GC ran but could not free memory, not because the GC is not taking care of the PermGen.
-
eis over 11 yearsto actually diagnoze what is the problem, you should add also
-XX:+HeapDumpOnOutOfMemoryError
so you would get a heap dump. Unsure if it works on permgen error, but I would recommend to try. That heap dump should then be run through with MAT or similar. -
jakub.petr over 11 yearsYes, you should set these in Tomcat configuration, so when it starts VM for your apps than it starts with these parameters. We are using these with GlassFish and didn't notice any performance impact, just PermGen error stopped showing up.
-
Marouane Lakhal about 7 yearsNice posts on the links. If someone need some insight on what's going on better read those posts. Thank you.