我们正在监控 jvm 指标,如堆、元空间、线程和 gc 计数,我们能够将这些指标推送到监控服务器,如 prometheus。同样,我们想跟踪 Java 本机内存指标(jcmd VM.sumary 的输出)。我的问题是,是否可以通过调用任何 jvm 运行时类来获取这些指标?
4 回答
是的,可以直接从 Java 应用程序获取 NativeMemoryTracking 总结:
import javax.management.JMException;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
public class DiagnosticCommand {
public static String execute(String command, String... args) throws JMException {
return (String) ManagementFactory.getPlatformMBeanServer().invoke(
new ObjectName("com.sun.management:type=DiagnosticCommand"),
command,
new Object[]{args},
new String[]{"[Ljava.lang.String;"});
}
public static void main(String[] args) throws Exception {
String summary = DiagnosticCommand.execute("vmNativeMemory", "summary");
System.out.println(summary);
}
}
不过,您必须解析文本输出。
请注意,可以使用指定的 MBean 单独跟踪 NMT 报告中最重要的部分,包括
- Java 堆
- 代码缓存
- 元空间
- 压缩类空间
- 直接字节缓冲区和映射字节缓冲区
请参阅MemoryPoolMXBean和BufferPoolMXBean。
正如我在评论中所说,监控 NMT 输出在实践中并不总是有帮助,因为它不能直接反映进程使用的实际物理内存。NMT 可以报告比实际使用量少得多的内存,或者它也可以从操作系统的角度报告比进程消耗更多的内存。
由于 NMT 可能会错过 Java 进程消耗的大量操作系统内存,因此监视进程的驻留集大小 (RSS) 也很有用。在 Linux 上,这可以通过解析/proc/[pid]/stat
或/proc/[pid]/status
.
你可以在JMX中找到很多你想要的东西。问题“为什么使用 JMX 技术?”的答案之一 是“监视和管理 Java VM”。在Oracle 文档中:
Java 虚拟机 (Java VM) 使用 JMX 技术进行了高度检测。您可以启动 JMX 代理来访问内置的 Java VM 工具,从而远程监控和管理Java VM。
//Metaspace
for (MemoryPoolMXBean memoryMXBean : ManagementFactory.getMemoryPoolMXBeans()) {
if ("Metaspace".equals(memoryMXBean.getName())) {
System.out.println(memoryMXBean.getUsage().getUsed());
System.out.println(memoryMXBean.getUsage().getCommitted());
System.out.println(memoryMXBean.getUsage().getMax());
System.out.println(memoryMXBean.getUsage().getInit());
}
}
//current number of live threads including both daemon and non-daemon threads
int threadCount = ManagementFactory.getThreadMXBean().getThreadCount();
//Returns the current memory usage of the heap and non-heap
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapMemory = memoryMXBean.getHeapMemoryUsage();
MemoryUsage nonHeapMemory = memoryMXBean.getNonHeapMemoryUsage();
//GarbageCollector total number of collections
List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
long totalCollectionCount = garbageCollectorMXBeans.stream().mapToLong(x -> x.getCollectionCount()).sum();
我认为没有Java API。您最好的选择可能是调用该jcmd <PID> VM.native_memory
命令并解析其输出。当然,您需要首先为您的进程启用本机内存跟踪。
尽管您没有提及Micrometer
,但我想指出我编写的一个小支持库,用于获取诸如 Resident Set Size (RSS) 之类的 procfs 信息。也许您可以从中提取一些有用的代码。实际上,procfs 代码与 Micrometer 无关(尽管不被视为公共 API)。这是:https ://github.com/mweirauch/micrometer-jvm-extras