我有一个启用了JMX监控的Java应用程序,如下所示:
-Dcom.sun.management.jmxremote.port=9999 \
// some other properties omitted
但是当我尝试重新启动应用程序时,有时我收到错误说JMX端口号已经在使用中。这是不可接受的。
所以我想为底层套接字设置SO_REUSEADDR为true以避免此错误,但是没有找到相关的JMX属性。
有什么想法吗?
答案 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