2017-08-30 38 views
1

我的應用程序存在一些內存問題,需要幫助瞭解這些統計信息。爲什麼unix和Java RunTime顯示的統計信息有差異

Unix的「頂」顯示這些統計數據對我的過程 -

VSZ: 37.4g 
RSS: 20.0g 

所以,這意味着20克目前在交換的過程,並在使用中。

然而,當我使用Runtime類打印統計數據從我的應用程序中,我得到這個:

Runtime.totalMemory() : 9.8G 
Runtime.freeMemory() : 3.6G 
Runtime.maxMemory() : 14.3G 

爲什麼不[Runtime.totalMemory() - Runtime.freeMemory()]匹配RSS?這是進程正在使用的內存。這兩個數字之間存在巨大差異。

此外,運行時是否將未使用的內存(Runtime.freeMemory())回送給操作系統供其他進程使用?

請注意,我的應用程序正在使用共享和複製高速緩存設置的對等GemFire高速緩存系統中運行。我需要優化應用程序以減少內存佔用。

+0

什麼'Runtime.maxMemory()'顯示? – Andremoniy

+0

14.3 G.我在java運行時將最大內存限制爲15G – user236215

+0

你看過:https://stackoverflow.com/questions/38597965/difference-between-resident-set-size-rss-and-java-total-committed -memory-nmt? – Andremoniy

回答

2

Runtime.totalMemory顯示當前可用的內存。 Java懶散地分配內存。

另外,運行時是否會將未使用的內存(Runtime.freeMemory())回送給操作系統供其他進程使用?

否。如果Java分配了內存(totalMemory),它現在在java進程中。

RSS:20.0克 14.3克

如前所述Java使用的內存除了堆。 此外,Gemfire使用堆內存(check this)。 嘗試在VisualVM-Buffer Monitor中查看它們。

你的基礎設施(OS,VMs)是什麼?

如果您無法使用標準工具,你應該使用JMX(for example

UPDATE

按照Doc寫自己的可維護性代理,缺省情況下使用的GemFire JVM堆。

確定

爲什麼RSS始終表示正在使用堆存儲器的唯一〜10G的工序20G。

如果你仍然問,我會提供更多的細節。什麼是Java內存使用情況?

  • 堆內存(Xmx);
  • 堆棧存儲器(每個線程有自己的堆棧ThreadStackSizeVMThreadStackSize);
  • MaxPermSize參數或MaxMetaspaceSize(MaxPermGenSizeMaxMetaspaceSize);
  • 直接字節緩衝區(MaxDirectMemorySize);內存池(Par Eden Space,Par Survivor Space,CMS Old Gen,Metaspace/PermGen,Code Cache,Compressed Class Space)(CompressedClassSpaceSize));
  • 字符串表(其中所有String.intern()將是,StringTableSize);
  • PerfDataMemorySize;
  • MarkStackSize;
  • CompilerThreadStackSize;
  • 恆池;
  • 我可能錯過了something;

要查看默認值,你可以運行:

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version 

要查看您的特定進程的選項,你可以運行:

jps -lvm 

是否有一個命令行工具在unix中確定剩餘的用法?

對於其中一些是的。對於他們中的一些人沒有。

對於直接內存,您可以嘗試sun.misc.SharedSecrets.getJavaNioAccess()。getDirectBufferPool()。getMemoryUsed()。

用CMD,例如:

jcmd <pid> VM.native_memory baseline 

但是這取決於運行設置(NativeMemoryTracking)。您可以閱讀如何啓用本機內存跟蹤here

在linux下你也可以使用:

pmap -x <pid> 

總之這可能是不管的,因爲你的任務:

注意,我的應用程序在對運行同行的GemFire緩存系統設置共享和複製緩存。我需要優化應用程序以減少內存佔用。

而且您不能影響本地內存使用情況。我想看看jmap util,它可以顯示你的直方圖。您應該檢查GemFire中的大小,並檢查這些對象,可能您存儲在緩存數據中,而這些數據不應該存在。我的意思是在我的優化緩存的練習中,我檢查對象和字段,看看哪些字段真的很頻繁,哪些不是。另一種方法是檢查你的序列化機制和對象佈局。

正如我提到的,你可以使用可維護性代理:

import com.sun.tools.attach.VirtualMachine; 
import sun.tools.attach.HotSpotVirtualMachine; 

import java.io.InputStream; 

public class JMemoryMain { 

    public static void main(String[] args) throws Exception { 
     final int pid = JMemoryMainUtils.getPid(args); 
     final HotSpotVirtualMachine vm = (HotSpotVirtualMachine) VirtualMachine.attach(String.valueOf(pid)); 
     final byte[] buffer = new byte[1024]; 
     try (InputStream is = vm.heapHisto()) { 
      for (int read; (read = is.read(buffer)) > 0;) { 
       System.out.write(buffer, 0, read); 
      } 
     } 
     vm.detach(); 
    } 

} 

您需要依賴從JDK的tools.jar運行此。它也可以打印類直方圖,但有時可以運行,而jmap不會。 此外,當您需要等待很長時間,並計算直方圖時,您可以使用VM.getSystemDictionary()並僅查找您的類。 而且,如果由於開銷導致無法啓用NMT,那將是有用的。

+0

根據文檔,默認情況下,Gemfire使用JVM堆。我沒有做任何改變,使它堆積如山。爲什麼RSS一直在使用20G來表示僅使用〜10G堆內存的進程。在unix中是否有命令行工具來確定其餘用法? – user236215

+0

我更新了信息。 – egorlitvinenko

相關問題