通过Nashorn的JMX连接,jjs。

问题描述 投票:1回答:1

我正在用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'))
javascript java jmx jjs
1个回答
3
投票

看看你脚本的这一行。

environment.put("javax.management.remote.JMXConnector.CREDENTIALS",credentials)

API将地图条目的密钥定义为常量。javax.management.remote.JMXConnector.CREDENTIALS.价值 的常数是 "jmx.remote.credentials".

因此,试着把这一行改成:

environment.put("jmx.remote.credentials",credentials)
© www.soinside.com 2019 - 2024. All rights reserved.