Назад | Перейти на главную страницу

Как исправить ошибку JMX "Не удалось получить заглушку RMIServer"?

Я только что завершил миграцию с Windows Server 2008 R2 на Ubuntu 10.04. Я управляю java-приложением (Java 6, Tomcat), у которого возникают проблемы с производительностью. Я хотел бы использовать JMX, чтобы попытаться устранить неполадки, но, похоже, я не могу подключить jvisualvm.

Если я сделаю ps -ef | grep "java", я вижу следующие параметры.

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

Netstat показывает, что порт 8084 прослушивает 0.0.0.0. В моей конфигурации JMX настроен для привязки к полному доменному имени сервера (мы используем частный DNS-сервер). Мой брандмауэр (IPTABLES / UFW) настроен так, чтобы разрешить весь исходящий трафик и разрешить входящий трафик на порт 8084.

Сам сервер виртуальный с двумя сетевыми адаптерами, публичным и частным. Шлюз общедоступной сетевой карты отключен, поэтому соединения могут входить только на частной стороне.

Когда я пытаюсь подключить jvisualvm к моему серверу приложений с помощью JMX, я получаю следующую ошибку в jvisualvm.

Cannot connect to [FQDN OMITTED]:8084 using server:jmx:rmi:///jndi/rmi://[FQDN OMITTED]:8084/jmxrmi

Если я посмотрю в журнал jvisualvm, то вижу следующую трассировку.

NFO [com.sun.tools.visualvm.jmx.impl.JmxModelImpl]: connect(service:jmx:rmi:///jndi/rmi://[FQDN OMITTED]:8084/jmxrmi)
java.io.EOFException: SSL peer shut down incorrectly
                at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:333)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:789)
Caused: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:808)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
                at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
                at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
                at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
                at java.io.DataOutputStream.flush(DataOutputStream.java:106)
                at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:211)
Caused: java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
                javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
                at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:286)
                at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
                at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
                at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
                at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:97)
Caused: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
                javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake]
                at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:101)
                at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:185)
                at javax.naming.InitialContext.lookup(InitialContext.java:392)
                at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnector.java:1886)
                at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.java:1856)
                at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:257)
Caused: java.io.IOException: Failed to retrieve RMIServer stub
                at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:338)
                at com.sun.tools.visualvm.jmx.impl.JmxModelImpl$ProxyClient.tryConnect(JmxModelImpl.java:451)
[catch] at com.sun.tools.visualvm.jmx.impl.JmxModelImpl$ProxyClient.connect(JmxModelImpl.java:395)
                at com.sun.tools.visualvm.jmx.impl.JmxModelImpl.connect(JmxModelImpl.java:216)
                at com.sun.tools.visualvm.jmx.impl.JmxModelImpl.<init>(JmxModelImpl.java:205)
                at com.sun.tools.visualvm.jmx.impl.JmxModelProvider.createModelFor(JmxModelProvider.java:61)
                at com.sun.tools.visualvm.jmx.impl.JmxModelProvider.createModelFor(JmxModelProvider.java:42)
                at com.sun.tools.visualvm.core.model.ModelFactory.getModel(ModelFactory.java:111)
                at com.sun.tools.visualvm.tools.jmx.JmxModelFactory.getJmxModelFor(JmxModelFactory.java:69)
                at com.sun.tools.visualvm.jmx.impl.JmxApplicationProvider.addJmxApplication(JmxApplicationProvider.java:267)
                at com.sun.tools.visualvm.jmx.impl.JmxApplicationProvider.createJmxApplication(JmxApplicationProvider.java:185)
                at com.sun.tools.visualvm.jmx.JmxApplicationsSupport.createJmxApplicationImpl(JmxApplicationsSupport.java:283)
                at com.sun.tools.visualvm.jmx.JmxApplicationsSupport.createJmxApplicationInteractive(JmxApplicationsSupport.java:261)
                at com.sun.tools.visualvm.jmx.impl.AddJMXConnectionAction$1.run(AddJMXConnectionAction.java:80)
                at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:577)
                at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:1030)

У кого-нибудь есть идеи?

Вы можете указать тот же порт для разговора JMX и RMI:

-Dcom.sun.management.jmxremote.port=8084 
-Dcom.sun.management.jmxremote.rmi.port=8084 

Проблема в том, что даже если JMX настроен на прослушивание порта 8084, после того, как начальное соединение установлено, хост JMX будет динамически выбирать другой порт для остальной части «разговора». Мой брандмауэр пропускал трафик через 8084, но блокировал последующий трафик.

Есть два варианта.

  1. Разрешить входящий трафик на все временные порты (ой!).
  2. Разработайте оболочку JMX, которая использует один порт для связи.

Я боролся с этой же проблемой, пытаясь подключиться к нашим новым виртуальным машинам Tomcat8 через JMX (используя VisualVM). Нашей команде Linux пришлось открыть заявку в Redhat, чтобы помочь нам в устранении неполадок. Но я наткнулся на эту статью, прежде чем они смогли решить нашу проблему.

Решение, упомянутое выше, заключалось в добавлении

-Dcom.sun.management.jmxremote.rmi.port=X

и X должны соответствовать вашим настройкам

-Dcom.sun.management.jmxremote.port 

Полный список аргументов:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=8091
-Dcom.sun.management.jmxremote.rmi.port=8091
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false 
-Djava.rmi.server.hostname=MYHOST

Надеюсь, это поможет кому-то еще с той же проблемой. Удачи!

В поисках решения идентичной проблемы (после решения многих других, готовых рвать за волосы) я нашел эту ветку и могу поделиться, что решение, которое сработало для меня, было https://serverfault.com/a/872756/579378 от @MaxRelax - Я бы поддержал его ответ, но у меня недостаточно репутации.

О, еще одна вещь: поскольку -Dcom.sun.management.jmxremote.ssl=false обязательно установите флажок "Не требовать SSL-соединение" в диалоговом окне Java Visual VM для добавления соединения JMX.

У меня такая же проблема с tomcat 9.0.9. на path/to/tomcat/bin/setenv.sh, у меня работала следующая конфигурация:

CATALINA_OPTS="$CATALINA_OPTS 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=1099 
-Dcom.sun.management.jmxremote.rmi.port=1099 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-Djava.rmi.server.hostname=192.168.1.20 
-Djmx.rmi.registry.port=1099 
-Djmx.rmi.port=1099 
" 

export CATALINA_OPTS