Java 线上服务查看 Direct 及 Mapped 堆外内存
Java JVM About 7,958 words需求
需要查看线上服务占用堆外内存的情况。
困难
jcmd
等命令行工具,无法查看堆外内存的情况。
NMT
也没有追踪堆外内存。
在Kubernetes
中部署,无法再映射JMX
端口提供给jconsole
使用。
解决方法一
在代码中提前使用MXBean
,定时轮训获取。
List<BufferPoolMXBean> bufferPoolMXBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
for (BufferPoolMXBean bufferPoolMXBean : bufferPoolMXBeans) {
System.out.println(bufferPoolMXBean.getObjectName().toString() + ", " + bufferPoolMXBean.getName() + ", " + bufferPoolMXBean.getCount() + ", " + bufferPoolMXBean.getMemoryUsed() + ", " + bufferPoolMXBean.getTotalCapacity());
}
输出
java.nio:type=BufferPool,name=mapped, mapped, 0, 0, 0
java.nio:type=BufferPool,name=direct, direct, 1, 16383, 16383
解决方法二
查看 JMX 状态
jcmd 1 ManagementAgent.status
禁用状态时输出
bash-4.4$ jcmd 1 ManagementAgent.status
1:
Agent: disabled
JMX
已启动时输出
❯ jcmd 1 ManagementAgent.status
1:
Agent: enabled
Connection Type: local
Protocol : rmi
Host : 127.0.0.1
URL : service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc2AAtVbmljYXN0UmVmMgAACzEwLjg4Ljk0Ljg0AADgM29dCMHwZ+DOU7Ho2AAAAYlD4VYkgAEAeA==
Properties :
com.sun.management.jmxremote.ssl = true [default]
com.sun.management.config.file = management.properties [default]
com.sun.management.jmxremote.local.only = true [default]
com.sun.management.jmxremote.access.file = jmxremote.access [default]
com.sun.management.jmxremote.port = 0 [default]
com.sun.management.jmxremote.registry.ssl = false [default]
com.sun.management.jmxremote.authenticate = true [default]
com.sun.management.jmxremote.ssl.need.client.auth = false [default]
com.sun.management.jmxremote.password.file = jmxremote.password [default]
开启本地 JMX
jcmd 1 ManagementAgent.start_local
输出
❯ jcmd 1 ManagementAgent.start_local
1:
Command executed successfully
jshell
使用jshell
打开Java
自动的脚本执行引擎。
/exit
命令退出jshell
。
❯ jshell
| 欢迎使用 JShell -- 版本 11.0.17
| 要大致了解该版本, 请键入: /help intro
jshell> /exit
| 再见
脚本代码
import javax.management.*;
import javax.management.remote.*;
import javax.management.openmbean.*;
String serviceUrl = "service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc2AAtVbmljYXN0UmVmMgAACzEwLjg4Ljk0Ljg0AADgM29dCMHwZ+DOU7Ho2AAAAYlD4VYkgAEAeA==";
JMXServiceURL url = new JMXServiceURL(serviceUrl);
try (JMXConnector connect = JMXConnectorFactory.connect(url)) {
MBeanServerConnection connection = connect.getMBeanServerConnection();
ObjectName memoryObjectName = ObjectName.getInstance("java.lang:type=Memory");
CompositeDataSupport heapMemoryUsage = (CompositeDataSupport) connection.getAttribute(memoryObjectName, "HeapMemoryUsage");
CompositeDataSupport nonHeapMemoryUsage = (CompositeDataSupport) connection.getAttribute(memoryObjectName, "NonHeapMemoryUsage");
System.out.println("heap committed: " + heapMemoryUsage.get("committed"));
System.out.println("heap init: " + heapMemoryUsage.get("init"));
System.out.println("heap max: " + heapMemoryUsage.get("max"));
System.out.println("heap used: " + heapMemoryUsage.get("used"));
System.out.println("non-heap committed: " + nonHeapMemoryUsage.get("committed"));
System.out.println("non-heap init: " + nonHeapMemoryUsage.get("init"));
System.out.println("non-heap max: " + nonHeapMemoryUsage.get("max"));
System.out.println("non-heap used: " + nonHeapMemoryUsage.get("used"));
ObjectName mappedObjectName = ObjectName.getInstance("java.nio:name=mapped,type=BufferPool");
Object mappedTotalCapacity = connection.getAttribute(mappedObjectName, "TotalCapacity");
Object mappedMemoryUsed = connection.getAttribute(mappedObjectName, "MemoryUsed");
System.out.println("buffer pool mapped total capacity: " + mappedTotalCapacity);
System.out.println("buffer pool mapped memory used: " + mappedMemoryUsed);
ObjectName directObjectName = ObjectName.getInstance("java.nio:name=direct,type=BufferPool");
Object directTotalCapacity = connection.getAttribute(directObjectName, "TotalCapacity");
Object directMemoryUsed = connection.getAttribute(directObjectName, "MemoryUsed");
System.out.println("buffer pool direct total capacity: " + directTotalCapacity);
System.out.println("buffer pool direct memory used: " + directMemoryUsed);
}
输出
❯ jshell
| 欢迎使用 JShell -- 版本 11.0.17
| 要大致了解该版本, 请键入: /help intro
jshell> import javax.management.*;
...> import javax.management.remote.*;
...> import javax.management.openmbean.*;
...>
...> String serviceUrl = "service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc2AAtVbmljYXN0UmVmMgAACzEwLjg4Ljk0Ljg0AADgM29dCMHwZ+DOU7Ho2AAAAYlD4VYkgAEAeA==";
...> JMXServiceURL url = new JMXServiceURL(serviceUrl);
...> try (JMXConnector connect = JMXConnectorFactory.connect(url)) {
...> MBeanServerConnection connection = connect.getMBeanServerConnection();
...> ObjectName memoryObjectName = ObjectName.getInstance("java.lang:type=Memory");
...> CompositeDataSupport heapMemoryUsage = (CompositeDataSupport) connection.getAttribute(memoryObjectName, "HeapMemoryUsage");
...> CompositeDataSupport nonHeapMemoryUsage = (CompositeDataSupport) connection.getAttribute(memoryObjectName, "NonHeapMemoryUsage");
...> System.out.println("heap committed: " + heapMemoryUsage.get("committed"));
...> System.out.println("heap init: " + heapMemoryUsage.get("init"));
...> System.out.println("heap max: " + heapMemoryUsage.get("max"));
...> System.out.println("heap used: " + heapMemoryUsage.get("used"));
...> System.out.println("non-heap committed: " + nonHeapMemoryUsage.get("committed"));
...> System.out.println("non-heap init: " + nonHeapMemoryUsage.get("init"));
...> System.out.println("non-heap max: " + nonHeapMemoryUsage.get("max"));
...> System.out.println("non-heap used: " + nonHeapMemoryUsage.get("used"));
...>
...> ObjectName mappedObjectName = ObjectName.getInstance("java.nio:name=mapped,type=BufferPool");
...> Object mappedTotalCapacity = connection.getAttribute(mappedObjectName, "TotalCapacity");
...> Object mappedMemoryUsed = connection.getAttribute(mappedObjectName, "MemoryUsed");
...> System.out.println("buffer pool mapped total capacity: " + mappedTotalCapacity);
...> System.out.println("buffer pool mapped memory used: " + mappedMemoryUsed);
...>
...> ObjectName directObjectName = ObjectName.getInstance("java.nio:name=direct,type=BufferPool");
...> Object directTotalCapacity = connection.getAttribute(directObjectName, "TotalCapacity");
...> Object directMemoryUsed = connection.getAttribute(directObjectName, "MemoryUsed");
...> System.out.println("buffer pool direct total capacity: " + directTotalCapacity);
...> System.out.println("buffer pool direct memory used: " + directMemoryUsed);
...> }
serviceUrl ==> "service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZ ... OU7Ho2AAAAYlD4VYkgAEAeA=="
url ==> service:jmx:rmi://127.0.0.1/stub/rO0ABXNyAC5qYXZh ... DOU7Ho2AAAAYlD4VYkgAEAeA==
heap committed: 536870912
heap init: 536870912
heap max: 8589934592
heap used: 245366784
non-heap committed: 35586048
non-heap init: 7667712
non-heap max: -1
non-heap used: 32305288
buffer pool mapped total capacity: 0
buffer pool mapped memory used: 0
buffer pool direct total capacity: 16383
buffer pool direct memory used: 16383
jshell> /exit
| 再见
Views: 830 · Posted: 2023-12-21
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...