2017-08-30 84 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

相关问题