允许立即启用JMX监视重新启动Java应用程序

时间:2014-05-08 02:10:02

标签: java jmx restart shutdown reusability

我有一个启用了JMX监控的Java应用程序,如下所示:

-Dcom.sun.management.jmxremote.port=9999 \
// some other properties omitted

但是当我尝试重新启动应用程序时,有时我收到错误说JMX端口号已经在使用中。这是不可接受的。

所以我想为底层套接字设置SO_REUSEADDR为true以避免此错误,但是没有找到相关的JMX属性。

有什么想法吗?

4 个答案:

答案 0 :(得分:6)

我担心你无法从命令行那样做。

您需要创建一个RMIServerSocketFactory,其中ServerSockets会生成所需的选项(SO_REUSEADDR)。

文档:http://docs.oracle.com/javase/8/docs/technotes/guides/rmi/socketfactory/

其他人解决了同样的问题: https://svn.apache.org/viewvc?view=revision&revision=r1596579

答案 1 :(得分:0)

是的,您应该以编程方式创建JMX连接器。 作为更简单的解决方法,如果默认端口忙于被杀死的进程,则可以在运行时为JMX选择另一个端口。或者只是尝试一次又一次地打开你的端口,直到它成功。

这是我用来打开兼容JConsole的JMX连接器的代码片段。在Scala中,抱歉,但你应该能够轻松地适应它

def startJmx(port: Int): Unit = {
if (port < 1) {
  return
}

val log = LoggerFactory.getLogger(getClass)

log.info("Starting JMX server connector on port {}", port)

val registry = LocateRegistry.createRegistry(port)

val server = ManagementFactory.getPlatformMBeanServer()

val url = new JMXServiceURL(s"service:jmx:rmi:///jndi/rmi://localhost:$port/jmxrmi")

val connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, Collections.emptyMap(), server)

 val thread = new Thread {
   override def run = try {
     connectorServer.start()
   } catch { 
     case e: Exception => log.error("Unable to start JMX connector", e)
   }
 }
 thread.setDaemon(true)
 thread.setName("JMX connector Thread")
 thread.start()
}

答案 2 :(得分:0)

我有同样的问题。这是我的应用程序的第一个实例(我已停止),它仍然订阅了这个端口,因此新实例无法启动。在我的情况下,它没有与套接字TIME_WAIT机制有关,而是在调用stop()之后,需要一些时间才能正常运行所有正在运行的线程。在我的案例中有用的是在停止应用程序之前取消注册bean,以便套接字是免费的。

private void unregisterBeanForName(String name) {
        try {

            JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://127.0.0.1:9999/jmxrmi");
            JMXConnector cc = JMXConnectorFactory.connect(jmxServiceURL);
            MBeanServerConnection mbsc = cc.getMBeanServerConnection();
//This information is available in jconsole
            ObjectName serviceConfigName = new ObjectName("YourObjectName");
            mbsc.unregisterMBean(serviceConfigName);
// Close JMX connector
            cc.close();
        } catch (Exception e) {
            System.out.println("Exception occurred: " + e.toString());
            e.printStackTrace();
        }
    }

答案 3 :(得分:-1)

在你的应用程序上添加一个将会杀死jmx的关闭钩子。

// kill process with port 9999    
fuser -k 9999/tcp