我的应用程序存在一些内存问题,需要帮助了解这些统计信息。
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缓存系统中。我需要优化应用程序以减少内存占用。
答案 0 :(得分:2)
Runtime.totalMemory显示当前可用的内存。 Java懒洋洋地分配内存。
此外,运行时是否将未使用的内存(Runtime.freeMemory())返回给OS以供其他进程使用?
没有。如果Java分配了内存(totalMemory),那么它现在就在java进程中。
RSS:20.0g 14.3克
如前所述,Java除了堆之外还使用内存。 Gemfire也使用了堆内存(check this)。 尝试在VisualVM-Buffer Monitor中查看它们。
您的基础设施(操作系统,虚拟机)是什么?
如果您不能使用标准工具,您可能应该使用JMX编写自己的可维护性代理(for example)
<强>更新强>
根据doc,默认情况下Gemfire使用JVM堆。
确定
为什么RSS始终显示20G用于仅使用~10G堆内存的进程。
如果你仍然问,我会提供更多细节。什么是java内存使用?
要查看默认值,您可以运行:
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,那将非常有用。