使用JMX从命令行获取堆转储。

3

在Linux(CentOS)上,是否可以使用JMX从命令行获取正在运行的进程的服务器堆转储?

无法打开VisualVM, 无法安装jmap。

2个回答

6
可以用以下简单代码实现:
import com.sun.management.HotSpotDiagnosticMXBean;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

@SuppressWarnings("restriction")
public class CreateHeapDump
{
    public static void main(String[] args) throws Exception
    {
        String host = args[0];
        String port = args[1];

        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi");
        JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
        ObjectName mbeanName = new ObjectName("com.sun.management:type=HotSpotDiagnostic");
        HotSpotDiagnosticMXBean bean = JMX.newMBeanProxy(mbsc, mbeanName, HotSpotDiagnosticMXBean.class, true);

        String fileName = "heap_dump_" + new SimpleDateFormat("dd.MM.yyyy HH.mm").format(new Date()) + ".hprof";
        boolean onlyLiveObjects = true;
        bean.dumpHeap(fileName, onlyLiveObjects);
    }
}

编译它:

javac CreateHeapDump.java

从命令行调用它:

java CreateHeapDump localhost 9010

0

这不会很漂亮,但它能工作。话虽如此,您可能想考虑使用Groovy或Jython甚至JavaScript来编写脚本....

我向jmxlocal添加了一个快速附加组件,该项目实现了本地JVM的标准JMX远程控制。它现在支持针对连接的MBeanServer执行一个命令的命令行调用,并且必须在Java代码中指定该命令。

克隆存储库并使用mvn clean install进行构建。 将jar文件(jmxlocal-1.0-SNAPSHOT.jar)复制到目标服务器。 使用目标Java进程的PID执行转储JMX命令,如下所示:

java -jar target/jmxlocal-1.0-SNAPSHOT.jar -j service:jmx:attach:///<PID> -c "conn.invoke(on(\"com.sun.management:type=HotSpotDiagnostic\"), \"dumpHeap\", new Object[]{\"/tmp/heap.dump\", true}, new String[]{String.class.getName(), boolean.class.getName()})"

输出结果将会是:

Command Executed. Result [null]

你应该在/tmp/heap.dump找到你的转储文件。

如果需要,你可以使用-u [用户名]-p [密码]参数提供凭据。


那么我该怎么办呢?显然目标服务器上没有JDK。我尝试将tools.jar复制到java旁边,但仍然没有成功。 - Nati
你不同意吗?嗯......好的。那我来修补它,让它在与 jmxlocal jar 相同的目录中查找 tools.jar。 - Nicholas
在Github上,我没有看到任何提交记录……你确定已经打了补丁吗? - Nati
让我们在聊天中继续这个讨论 - Nati
@Nati; 无法从工作网络连接聊天。添加了内置的堆转储。实现了新的命令行处理程序。更加清洁且易于扩展。命令:java -jar target/jmxlocal-1.0-SNAPSHOT.jar -jmxurl service:jmx:attach:///29431 -psx -c hdump 结果:成功完成。结果:/tmp/29431-heap-2016-03-02-110323.dmp。如果有任何问题,请通过github给我发消息。 - Nicholas
显示剩余3条评论

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