2012-10-17 28 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