分析記憶體問題

瞭解如何找出Java應用程式記憶體問題的原因。 您可以自動並手動產生棧積傾印以及棧積長條圖,以識別原因。

說明 description

環境

Experience Manager

問題/症狀

JAVA應用程式執行速度會變慢且最後會用盡記憶體,或者您會在記錄檔或主控台輸出OutOfMemoryError: Java heap spaceOutOfMemoryError: gc overhead limit exceeded中看到錯誤。

解決方法 resolution

原因
這類問題可能有很多原因。

在我們的情況下,一個可能的原因是Java應用程式CRX / CQ是從命令列啟動,且具有Java的預設棧積記憶體設定。 這表示並未指定 jvm 參數 -Xmx。CRX 或 CQ 至少需要分配 256 MB 的堆積才能執行。如果這是問題所在,則從命令列開始,確保堆積記憶體已設定。範例:

java -Xmx512m -jar *.jar

如果不是這種情況,那麼您的應用程式可能會保留過多對象而沒有為垃圾收藏集釋出它們。這稱為記憶體外洩,請參閱此處以了解詳細資訊。請參閱以下有關如何分析Java應用程式中的記憶體問題的章節。
建立棧積傾印:

自動產生棧積傾印

若要在記憶體用完時自動建立棧積傾印,您可以新增jvm引數-XX:+HeapDumpOnOutOfMemoryError,以在應用程式擲回OutOfMemoryError時自動產生棧積傾印。 例如,

java -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -jar *.jar

當java處理序的記憶體不足時,這會在處理序的工作目錄中產生棧積傾印檔案(java_...hprof)。 產生堆積傾印後,該流程可以繼續執行。通常,一個堆積傾印檔案就足以分析問題。

注意: 如果您正在使用 crx-quickstart/server/start 指令碼來啟動您的 CRX 執行個體,則您可以將 -XX:+HeapDumpOnOutOfMemoryError 新增到 CQ_JVM_OPTS 變數 (也確保對變數取消註解)。例如:

CQ_JVM_OPTS='-XX:+HeapDumpOnOutOfMemoryError'

新增此參數並重新啟動 CRX 執行個體後,驗證是否設定了新的 jvm 選項。從命令列執行 ps -ef | grep java。然後檢查您是否看到-XX:+HeapDumpOnOutOfMemoryError作為CRX Java處理序的引數。

如果由於磁碟空間限制需要指定不同的目錄來產生堆積傾印,則可以新增 -XX:HeapDumpPath=/path/to/generate/heapdump 參數,以告知 jvm 將檔案放在哪裡。

請參閱這裡以取得偵錯相關jvm引數的參考資料。
手動產生棧積傾印
太陽/OracleJVM

若要手動產生推積傾印,請執行此命令 (jmap 和 jps 可以在您的 jdk 主目錄的 bin 資料夾中找到):

  1. 查詢您正在為其產生棧積傾印的java流程的pid。

    • 在Unix或Linux中,這可以透過ps -ef | grep javajps -l完成
    • 在Windows中,這可以透過開啟工作管理員來完成,按Ctrl+Shift+Esc,然後移至 檢視,然後移至 選取欄,然後移至 PID (處理序識別碼)jps -l
  2. 執行下面的 jmap 命令,將 /path/to/generate/heapdumpfile.hprof 以您要產生堆積傾印檔案的位置取代,然後將 1234 以您在上一步中查找的 pid 取代。

    code language-none
    jmap -dump:format=b,file=/path/to/generate/heapdumpfile.hprof 1234
    

IBM JVM

您首先必須變更有關傾印代理程式的預設 JVM 設定,以在使用者訊號上產生正確的傾印。有幾種傾印,但您通常需要完整的 系統傾印 以執行徹底的記憶體分析。 新增以下引數:

Xdump:heap:opts=PHD+CLASSIC:events=user -Xdump:system:events=user

當JVM收到來自作業系統的SIGQUIT (Linux、AIX®、z/OS®和i5/OS™)或SIGBREAK (Windows)訊號時,就會發生此「使用者」事件。

如需詳細資訊,請參閱此處供應商的文件。

警告: 棧積傾印檔案很大,最大並可能達到和您最大棧積 — Xmx jvm參陣列態相同的磁碟大小。 請確定您有足夠的磁碟空間分配給產生傾印檔案的目錄。
分析棧積傾印
分析棧積傾印的適合工具是EclipseMAT (Eclipse記憶體分析器)

此工具無法分析 IBM JVM 已產生的傾印。對於上述情況,有幾種可能性。 IBM HeapAnalyzer將適用於PHD或傳統格式的棧積傾印。
[br>若要進行完整的系統傾印分析,請使用IBM支援助理工作台,並將IBM Java的監控和診斷工具 — 記憶體分析器安裝在頂端。 棧積長條圖是按Java類別使用的即時物件與記憶體數的簡單測量。 不幸的是,視Java安裝而定,所需的工具可能無法取得或可能並不一定有效。 若要建立棧積長條圖,您首先需要Java流程的流程ID。 若要取得,請執行ps or (if available), run:<b](br>若要進行完整的系統傾印分析,請使用IBM支援助理工作台,並將IBM Java的監控和診斷工具 — 記憶體分析器安裝在頂端。 棧積長條圖是按Java類別使用的即時物件與記憶體數的簡單測量。 不幸的是,視Java安裝而定,所需的工具可能無法取得或可能並不一定有效。 若要建立棧積長條圖,您首先需要Java流程的流程ID。 若要取得,請執行ps or (if available), run:<b)棧積長條圖
棧積長條圖是按Java類別使用的即時物件與記憶體數的簡單測量。 不幸的是,視Java安裝而定,所需的工具可能無法取得或可能並不一定有效。 若要建立棧積長條圖,您首先需要Java流程的流程ID。 若要取得,請執行 ps 或 (如果有) 執行:

jps -l

此Java工具會取得所有正在執行Java流程的流程ID。 範例:

327
3332 sun.tools.jps.Jps
3313 crx-quickstart-....jar

現在執行以下命令:

jmap -histo 3313

該清單會按所需的總記憶體排序 (淺:不包括參照的物件)。輸出的前 20 行是最有趣的。輸出範例:

JVM version is 1.5.0_20-141
Iterating over heap. This may take a while...
Warning: skipping invalid TLAB for thread t@62211
Warning: skipping invalid TLAB for thread t@62467
...
SizeCountClass description
-------------------------------------------------------
1059290412916byte`[` `]`
1028584075255* ConstMethodKlass
628317658388char`[` `]`
604230414928int`[` `]`
4995752116201* SymbolKlass
422089675255* MethodKlass
41965126969* ConstantPoolKlass
29285606969* InstanceKlassKlass
26310086066* ConstantPoolCacheKlass
2395872149742org.apache.jackrabbit.core.query.lucene.DocId$PlainDocId
14760087003java.util.HashMap$Entry`[` `]`
139612858172java.lang.String
107023244593java.util.HashMap$Entry
75398410036short`[` `]`
73546454org.apache.jackrabbit.core.query.lucene.DocId`[` `]`
7201927502java.lang.Class
64070413348com.day.crx.persistence.tar.index.IndexEntry
...

其他資訊

為了協助分析問題,我們還需要了解以下資訊:

  • CRX 或 CQ 版本,包括所有已安裝的 Hot Fix 版本編號清單。
  • 作業系統、JVM 供應商和版本。

參考資料

[ 1] HotSpot VM的Oracle說明中心>疑難排解指南
[ 2]  Oracle.com > Java > DebuggingOptions

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f