2017-05-23 52 views
0

我正在運行java web應用程序(Play Framework)的多個實例。 Web應用程序運行的時間越長,重新啓動Web應用程序之前可用的內存就越少。有時我會遇到OutOfMemory異常。 我試圖找到問題,但我得到了很多矛盾的信息,所以我無法找到源代碼。Java內存使用情況,許多矛盾的數字

這是相關信息:

  • 的Ubuntu 14.04.5 LTS與GB的12 RAM
  • OpenJDK的運行時環境(建立1.8.0_111-8u111-B14-3〜14.04.1-B14)
  • OpenJDK的64位服務器VM(建立25.111-B14,混合模式)

編輯: 這裏是JVM設置:

  • -Xms64m
  • -Xmx128m
  • -server
  • (我不是100%肯定,因爲我使用的/etc/init.d腳本start-stop-daemon這將啓動,如果這些參數正確地傳遞給JVM該劇劇本的框架,這將啓動JVM)

這是,我如何使用它:

start() { 
    echo -n "Starting MyApp" 
    sudo start-stop-daemon --background --start \ 
     --pidfile ${APPLICATION_PATH}/RUNNING_PID \ 
     --chdir ${APPLICATION_PATH} \ 
     --exec ${APPLICATION_PATH}/bin/myapp \ 
     -- \ 
     -Dinstance.name=${NAME} \ 
     -Ddatabase.name=${DATABASE} \ 
     -Dfile.encoding=utf-8 \ 
     -Dsun.jnu.encoding=utf-8 \ 
     -Duser.country=DE \ 
     -Duser.language=de \ 
     -Dhttp.port=${PORT} \ 
     -J-Xms64M \ 
     -J-Xmx128m \ 
     -J-server \ 
     -J-XX:+HeapDumpOnOutOfMemoryError \ 
     >> \ 
     $LOGFILE 2>&1 

我撿在網絡應用的實例中:

htop顯示4615M的VIRT和338M的RES

當我使用jmap -dump:live,format=b,file=mydump.dump <mypid>創建堆轉儲時,該文件只有大約50MB。

當我在Eclipse MAT中打開它時,總覽顯示已使用內存「20.1MB」(將「Keep unreachable objects」選項設置爲ON)。

那麼在Eclipse MAT中,如何將htop中顯示的338MB縮小到20.1MB?

我不認爲這是與GC有關的,因爲無論等待多久都無所謂,htop總是顯示這個數量的內存,它永遠不會下降。

事實上,我會假設我的簡單應用程序不超過20MB,mabye 30MB。

我比較堆與年齡差異與Eclipse MAT 4小時的堆轉儲,我沒有看到對象的任何顯着增加。注:我添加了-XX:+HeapDumpOnOutOfMemoryError選項,但我必須等待5-7天,直到它再次發生。我希望在你幫助我解釋我的電話號碼時儘早找到問題。

謝謝 schube

+3

將JVM的參數添加到問題中。堆棧內存分配(-Xss),初始堆大小(-Xms),最大堆大小(-Xmx)等。請記住,Java進程的總內存不僅僅是其堆大小。此外,您不必等待幾天JVM就會在OutOfMemoryError上崩潰 - 只需減小堆大小,並且它應該發生得更快。然後查看堆棧跟蹤,因爲它可能會提供有關代碼中分配失敗的線索。 – vempo

+0

您是否嘗試使用像JVisualVM這樣的工具來觀看實時更改?虛擬機內部的哪部分內存不斷增加? – cyberbrain

+0

謝謝!我添加了JVM參數。是的,我可以在之前引發OutOfMemory錯誤,你是對的。但如果可能的話,我想在發生問題之前找到問題。由於這是一臺遠程機器,因此我無法使用JVisualVM。感謝所有的投入!! – schube

回答

4

堆是包含Java對象的內存。 htop當然不知道堆。其中,有助於使用的內存,所報告的VIRT

  • 的JVM自己的代碼,並且所需的庫
  • 字節代碼和加載的類
  • 的JIT的元信息的整理的東西經常使用的方法的代碼
  • I/O緩衝區
  • 線程堆棧分配堆
  • 內存,但目前不含有活的對象

當您轉儲堆時,它將包含實時Java對象,以及允許瞭解內容的元信息,例如類和字段名稱。當工具計算使用的堆時,它將只包含對象。所以它自然會小於堆轉儲文件的大小。此外,由於填充/對齊,這種使用的內存通常不包含不可用的內存,而且,由於相關信息(32位體系結構與64位體系結構與壓縮的Oops)在該空間中不可用,所以該工具有時會假定指針大小錯誤堆轉儲。這些錯誤可能總結。

請注意,對於OutOfMemoryError,堆中可能存在其他原因。例如。由於內存泄漏與動態類加載或太多本地I/O緩衝區相結合,可能會有太多元信息...

+0

你說得對,JVM也加載了東西。但他們在Play Framework網站的某個地方寫道,他們的網站在內存很少的服務器上運行(據我記憶,這是64MB到72MB,目前我找不到鏈接)。我的應用程序更小,需要更多的內存。我想找到一些問題! – schube

+0

他們是否真的聲稱擁有一臺運行着這臺小內存*的服務器,或者是否說過他們使用*堆大小*來運行服務器?試圖運行最近的只有72MB RAM的Java虛擬機將需要大量的調整,即使是一個helloworld,然後,下面有一個操作系統必須以某種方式運行... – Holger