如何通过JMX编程方式访问内存使用情况?

20

我正在寻找示例Java JMX代码,以从另一个虚拟机中访问JMX属性的值。

使用JConsole,在查看java.lang/Memory/Attributes/HeapMemory时没有任何问题。

如何从在虚拟机中运行的Java程序获取相同的信息?

非常感谢提供所需的任何命令行选项示例或其他需要启动的内容。

4个回答

18

你需要设置一个JMXConnector。以下是一段代码片段,将获取远程计算机上的已提交堆内存使用情况。

String host ="myHost";
int port = 1234;
HashMap map = new HashMap();
String[] credentials = new String[2];
credentials[0] = user;
credentials[1] = password;
map.put("jmx.remote.credentials", credentials);
JMXConnector c = JMXConnectorFactory.newJMXConnector(createConnectionURL(host, port), map);
c.connect();
Object o = c.getMBeanServerConnection().getAttribute(new ObjectName("java.lang:type=Memory"), "HeapMemoryUsage");
CompositeData cd = (CompositeData) o;
System.out.println(cd.get("committed"));

private static JMXServiceURL createConnectionURL(String host, int port) throws MalformedURLException
{
    return new JMXServiceURL("rmi", "", 0, "/jndi/rmi://" + host + ":" + port + "/jmxrmi");
}

如果您不关心安全性,可以将地图设置为 null。您需要使用以下命令启动远程服务器:

-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

您可能想查看 wlshell,这是一个小型实用程序,允许您使用文本界面或脚本访问远程服务器上的MBeans,它可以与WebLogic一起使用,但对于启用了远程监视的任何Java程序都有效。


我们如何知道用户和密码,或者如何设置它?通过使用属性文件吗? - Sreevidya Aravind
MemoryUsage memuse = MemoryUsage.from((CompositeData) o); - Erik Martino

5

@Kire的回答看起来不错,但我想补充一些关于我的SimpleJMX包的细节。 它包含服务器支持,可以方便地导出bean,并且还包括一个简单的客户端接口,可以针对导出JMX信息的任何JVM工作。

要访问内存使用情况,可以这样做:

JmxClient client = new JmxClient("some.host.name", somePortNumber);
// get the memory composite information
CompositeData composite =
      (CompositeData)client.getAttribute(new ObjectName("java.lang:type=Memory"),
                                         "HeapMemoryUsage");
System.out.println(composite.get("committed"));

@Gray 看起来不错,SimpleJMX客户端可以与标准的JMX服务器一起工作吗? - raffian
1
它确实可以,它只是使用JMX协议,所以可以与任何JMX客户端/服务器一起使用。 - Gray

2
// Retrieve memory managed bean from management factory.
MemoryMXBean memBean = ManagementFactory.getMemoryMXBean() ;
MemoryUsage heap = memBean.getHeapMemoryUsage();
MemoryUsage nonHeap = memBean.getNonHeapMemoryUsage();

// Retrieve the four values stored within MemoryUsage:
// init: Amount of memory in bytes that the JVM initially requests from the OS.
// used: Amount of memory used.
// committed: Amount of memory that is committed for the JVM to use.
// max: Maximum amount of memory that can be used for memory management.
System.err.println(String.format("Heap: Init: %d, Used: %d, Committed: %d, Max.: %d",
  heap.getInit(), heap.getUsed(), heap.getCommitted(), heap.getMax()));
System.err.println(String.format("Non-Heap: Init: %d, Used: %d, Committed: %d, Max.: %d",
  nonHeap.getInit(), nonHeap.getUsed(), nonHeap.getCommitted(), nonHeap.getMax()));

除非我非常困惑,否则这是访问有关同一虚拟机的信息的代码。我试图弄清楚如何编写一个小的命令行脚本,从运行在不同虚拟机中的服务器中提取信息。 - ThoughtfulHacking
@ThoughtfulHacking,你说得对,这段代码是为了同一个虚拟机而写的。我试图在另一个虚拟机上运行相同的代码,但是在ManagementFactory中有一个名为newPlatformMXBeanProxy的方法,我使用它来获取另一个虚拟机的线程,但是我无法获取内存管理信息。你的问题的正确答案是解决方案,但我真的需要像这个答案一样去做... - Tarek

1
这是远程获取MemoryMXBean的方法(为了补充@Adamski的答案):
MemoryMXBean memoryMXBeanProxy = JMX.newMXBeanProxy(
            conn, new ObjectName("java.lang:type=Memory"), MemoryMXBean.class);

这个解决方案比@Kire的更好,因为不需要使用强制转换。 - david.perez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接