我正在用JDK8自带的JavaScript引擎编写一个脚本。这个脚本将使用JMX连接到一个远程Java实例。我使用了认证,但没有使用SSL。JMX连接在任何JMX客户端上都能正常工作,问题出在这个脚本中。
脚本的输出是。
[root@testvm ~]# /opt/scripts/jmx-test.jjs
{javax.management.remote.JMXConnector.CREDENTIALS=[Ljava.lang.String;@679b62af}
Exception in thread "main" java.lang.SecurityException: Authentication failed! Credentials required
at com.sun.jmx.remote.security.JMXPluggableAuthenticator.authenticationFailure(JMXPluggableAuthenticator.java:211)
at com.sun.jmx.remote.security.JMXPluggableAuthenticator.authenticate(JMXPluggableAuthenticator.java:163)
at sun.management.jmxremote.ConnectorBootstrap$AccessFileCheckerAuthenticator.authenticate(ConnectorBootstrap.java:219)
at javax.management.remote.rmi.RMIServerImpl.doNewClient(RMIServerImpl.java:232)
at javax.management.remote.rmi.RMIServerImpl.newClient(RMIServerImpl.java:199)
at sun.reflect.GeneratedMethodAccessor18147.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:276)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:253)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:162)
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2404)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:308)
at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270)
at jdk.nashorn.internal.scripts.Script$jmx_test_jjs.runScript(/opt/scripts/jmx-test.jjs:14)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:535)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:209)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.tools.Shell.apply(Shell.java:383)
at jdk.nashorn.tools.Shell.runScripts(Shell.java:312)
at jdk.nashorn.tools.Shell.run(Shell.java:168)
at jdk.nashorn.tools.Shell.main(Shell.java:132)
at jdk.nashorn.tools.Shell.main(Shell.java:111)
这是脚本。
#! /usr/java/jdk1.8.0_25/bin/jjs
host="remotehost"
port=7091
serviceURL = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi"
url = new javax.management.remote.JMXServiceURL(serviceURL);
stringArrayType = Java.type("java.lang.String[]")
credentials = new stringArrayType(2)
credentials[0]="user"
credentials[1]="password1"
HashMapType = Java.type("java.util.HashMap")
environment = new HashMapType()
environment.put("javax.management.remote.JMXConnector.CREDENTIALS",credentials)
print(environment)
connector = javax.management.remote.JMXConnectorFactory.connect(url,environment)
似乎证书变成了 null
. 请看。http:/grepcode.comfilerepository.grepcode.comjavarootjdkopenjdk6-b14comsunjmxremotesecurityJMXPluggableAuthenticator.java#162。
问题是,我不知道如何正确地将环境发送到javax.management.remote.JMXConnectorFactory.connect()。
编辑: 经过@Nicholas的回答,现在脚本可以用了。下面是完整的例子。
#! /usr/java/jdk1.8.0_25/bin/jjs
host="remotehost"
port=7091
serviceURL = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi"
url = new javax.management.remote.JMXServiceURL(serviceURL);
stringArrayType = Java.type("java.lang.String[]")
credentials = new stringArrayType(2)
credentials[0]="user"
credentials[1]="password1"
HashMapType = Java.type("java.util.HashMap")
environment = new HashMapType()
environment.put("jmx.remote.credentials",credentials)
connector = javax.management.remote.JMXConnectorFactory.connect(url,environment)
mbeanServerConnection=connector.getMBeanServerConnection()
ObjectNameType = Java.type("javax.management.ObjectName")
objectName = new ObjectNameType('Catalina:type=Connector,port=8009,address="tomcat.example.org"')
print(mbeanServerConnection.getAttribute(objectName, "proxyName"))
objectName = new ObjectNameType('java.lang:type=Memory')
#print(mbeanServerConnection.getAttribute(objectName, "HeapMemoryUsage"))
print('HeapMemoryUsage, used = ' + mbeanServerConnection.getAttribute(objectName, "HeapMemoryUsage").get('used'))
看看你脚本的这一行。
environment.put("javax.management.remote.JMXConnector.CREDENTIALS",credentials)
API将地图条目的密钥定义为常量。javax.management.remote.JMXConnector.CREDENTIALS. 而 价值 的常数是 "jmx.remote.credentials".
因此,试着把这一行改成:
environment.put("jmx.remote.credentials",credentials)