为什么unix和Java RunTime显示的统计数据存在差异
我的应用程序存在一些内存问题,需要帮助理解这些统计信息。
Unix“top”为我的流程显示了这些统计数据 –
VSZ: 37.4g RSS: 20.0g
因此,这意味着目前交换20g用于该过程和使用中。
但是,当我使用Runtime类从我的应用程序中打印统计信息时,我得到:
Runtime.totalMemory() : 9.8G Runtime.freeMemory() : 3.6G Runtime.maxMemory() : 14.3G
为什么[Runtime.totalMemory() – Runtime.freeMemory()]与RSS不匹配? 这是该进程当前使用的内存。 这两个数字之间存在巨大差异。
此外,运行时是否将未使用的内存(Runtime.freeMemory())返回给OS以供其他进程使用?
请注意,我的应用程序运行在使用共享和复制缓存设置的对等GemFire缓存系统中。 我需要优化应用程序以减少内存占用。
Runtime.totalMemory显示当前可用的内存。 Java懒惰地分配内存。
此外,运行时是否将未使用的内存(Runtime.freeMemory())返回给OS以供其他进程使用?
不。如果Java分配了内存(totalMemory),它现在就在java进程中。
RSS:20.0g 14.3G
如前所述,Java除了堆之外还使用内存。 Gemfire也使用了堆内存( 检查一下 )。 尝试在VisualVM-Buffer Monitor中查看它们。
您的基础设施(操作系统,虚拟机)是什么?
如果您不能使用标准工具,您可能应该使用JMX编写自己的可维护性代理( 例如 )
UPDATE
根据doc,默认情况下Gemfire使用JVM堆。
好
为什么RSS始终显示20G用于仅使用~10G堆内存的进程。
如果你仍然问,我会提供更多细节。 什么是java内存使用?
- 堆内存( Xmx );
- 堆栈内存(每个线程都有自己的堆栈ThreadStackSize , VMThreadStackSize );
- MaxPermSize或MaxMetaspaceSize( MaxPermGenSize , MaxMetaspaceSize );
- 直接字节缓冲区( MaxDirectMemorySize );
- 内存池(Par Eden Space,Par Survivor Space,CMS Old Gen,Metaspace / PermGen,Code Cache,Compressed Class Space( CompressedClassSpaceSize ));
- 字符串表(所有String.intern()将在其中, StringTableSize );
- PerfDataMemorySize ;
- MarkStackSize ;
- CompilerThreadStackSize ;
- 恒定池;
- 我可能错过了什么 ;
要查看默认值,您可以运行:
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version
要查看特定进程的哪些选项,您可以运行:
jps -lvm
unix中是否有命令行工具来确定其余用法?
对于其中一些是的。 对于他们中的一些没有。
对于直接内存,您可以尝试sun.misc.SharedSecrets.getJavaNioAccess()。getDirectBufferPool()。getMemoryUsed()。
使用cmd,例如:
jcmd VM.native_memory baseline
但这取决于运行设置( NativeMemoryTracking )。 您可以在此处阅读如何启用本机内存跟踪。
在linux中你也可以使用:
pmap -x
总之,这可能无关紧要,因为你的任务:
请注意,我的应用程序运行在使用共享和复制缓存设置的对等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,那将非常有用。