Мониторинг нативной памяти Java
Мы следим за метриками jvm, такими как куча, мета-пространство, потоки и счетчик gc, и мы можем отправить эти метрики на сервер мониторинга, например, через prometheus. Точно так же мы хотели отслеживать метрики собственной памяти Java (вывод jcmd VM.sumary). Мой вопрос: возможно ли получить эти метрики, вызывая какие-либо классы времени выполнения jvm?
4 ответа
Да, можно получить сводку NativeMemoryTracking непосредственно из приложения Java:
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);
}
}
Вы должны будете проанализировать вывод текста, хотя.
Обратите внимание, что наиболее важные части отчета NMT могут отслеживаться отдельно с помощью обозначенных MBeans, включая
- Java Heap
- Кэш кода
- Метапространство
- Сжатый Класс Пространства
- Прямые байтовые буферы и отображенные байтовые буферы
См. MemoryPoolMXBean и BufferPoolMXBean.
Как я сказал в комментариях, мониторинг вывода NMT не всегда полезен на практике, так как он не отражает непосредственно физическую память, используемую процессом. NMT может сообщать намного меньше памяти, чем фактическое использование, или он также может сообщать больше памяти, чем процесс потребляет с точки зрения ОС.
Поскольку NMT может пропустить большой объем памяти ОС, потребляемой процессом Java, также полезно отслеживать размер резидентного набора процесса (RSS). В Linux это можно сделать, проанализировав /proc/[pid]/stat
или же /proc/[pid]/status
,
Вы можете найти много вещей, которые вы хотите в JMX. Один из ответов на вопрос "Зачем использовать технологию JMX?" это "Мониторинг и управление Java VM". В Oracle doc:
Виртуальная машина 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
Я хотел бы указать на небольшую библиотеку поддержки, которую я написал для получения информации о procfs, например Resident Set Size (RSS). Возможно, вы сможете извлечь из него какой-нибудь полезный код. На самом деле код procfs не имеет отношения к микрометру (хотя и не считается публичным API). Вот оно: https://github.com/mweirauch/micrometer-jvm-extras