You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.0.1如何通过JMX编程调用shutdown端点?

编程式连接Spring Boot 2.0.1的JMX端点解决方法

咱们先理清楚问题核心:Spring Boot默认情况下JMX的RMI注册表端口是随机生成的,所以硬写端口肯定会失败,而jconsole能自动发现本地JVM的JMX地址,所以能正常连接。下面给你两种靠谱的解决方案:

方案一:固定JMX端口(适合远程连接场景)

直接在Spring Boot配置文件里固定JMX相关端口,这样就能在代码里明确指定端口了。

配置文件设置

如果用application.properties:

# 启用JMX
spring.jmx.enabled=true
# 固定RMI注册表端口和JMX服务器端口(建议设为同一个,避免混淆)
spring.jmx.remote.rmi.port=9999
spring.jmx.server.port=9999
# 启用shutdown端点并通过JMX暴露
management.endpoint.shutdown.enabled=true
management.endpoints.jmx.exposure.include=shutdown

如果用application.yml:

spring:
  jmx:
    enabled: true
    remote:
      rmi:
        port: 9999
    server:
      port: 9999
management:
  endpoint:
    shutdown:
      enabled: true
  endpoints:
    jmx:
      exposure:
        include: shutdown

修正后的JMX连接代码

配置好端口后,你的代码就可以正常使用固定端口连接了:

import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;

public class JmxShutdownExample {
    public static void main(String[] args) throws IOException {
        // 现在端口固定为9999,直接写死即可
        String url = "service:jmx:rmi:///jndi/rmi://127.0.0.1:9999/jmxrmi";
        JMXServiceURL serviceUrl = new JMXServiceURL(url);
        // 建立连接
        JMXConnector connector = JMXConnectorFactory.connect(serviceUrl, null);
        
        // 调用shutdown端点的MBean
        try {
            connector.getMBeanServerConnection().invoke(
                new javax.management.ObjectName("org.springframework.boot:name=SpringApplication,type=Admin"),
                "shutdown",
                new Object[]{},
                new String[]{}
            );
            System.out.println("应用已成功关闭");
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        connector.close();
    }
}

方案二:用Attach API动态连接(适合本地连接场景)

如果不想固定端口,或者只是本地操作的话,可以用JDK自带的Attach API,直接通过进程ID或者进程名找到目标Spring Boot应用,动态获取JMX连接地址,完全不需要关心端口。

示例代码

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.util.List;

public class LocalJmxShutdown {
    public static void main(String[] args) throws IOException, AttachNotSupportedException {
        // 遍历本地所有JVM进程,找到你的Spring Boot应用
        List<VirtualMachineDescriptor> vmDescriptors = VirtualMachine.list();
        for (VirtualMachineDescriptor vmd : vmDescriptors) {
            // 这里替换成你的Spring Boot应用主类名,比如"com.example.MyApplication"
            if (vmd.displayName().contains("com.example.MyApplication")) {
                // 附加到目标进程
                VirtualMachine vm = VirtualMachine.attach(vmd.id());
                
                // 获取JMX连接地址,如果没加载代理就手动加载
                String jmxUrl = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
                if (jmxUrl == null) {
                    String agentPath = vm.getSystemProperties().getProperty("java.home") + "/lib/management-agent.jar";
                    vm.loadAgent(agentPath);
                    jmxUrl = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
                }
                
                // 建立JMX连接并调用shutdown
                JMXServiceURL serviceUrl = new JMXServiceURL(jmxUrl);
                JMXConnector connector = JMXConnectorFactory.connect(serviceUrl);
                MBeanServerConnection connection = connector.getMBeanServerConnection();
                
                try {
                    connection.invoke(
                        new javax.management.ObjectName("org.springframework.boot:name=SpringApplication,type=Admin"),
                        "shutdown",
                        new Object[]{},
                        new String[]{}
                    );
                    System.out.println("本地应用已关闭");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                
                // 清理资源
                connector.close();
                vm.detach();
                break;
            }
        }
    }
}

依赖注意事项

Attach API需要依赖JDK的tools.jar,在Gradle里可以这样添加依赖:

implementation files("${System.getProperty('java.home')}/../lib/tools.jar")

如果是Java 9及以上版本,因为tools.jar已经模块化,你需要在module-info.java里添加模块依赖:

requires jdk.attach;
requires jdk.management;

最后提醒

不管用哪种方案,都要确保你的shutdown端点已经正确启用并通过JMX暴露,也就是前面配置里的management.endpoint.shutdown.enabled=true和management.endpoints.jmx.exposure.include=shutdown这两行不能少。

内容的提问来源于stack exchange,提问作者Robert Lohr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:08:38