Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
919afc52
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
919afc52
编写于
11月 04, 2015
作者:
S
sgehwolf
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6425769: Allow specifying an address to bind JMX remote connector
Reviewed-by: jbachorik, dfuchs
上级
f9f1dd5a
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
754 addition
and
9 deletion
+754
-9
src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
.../classes/sun/management/jmxremote/ConnectorBootstrap.java
+203
-9
src/share/lib/management/management.properties
src/share/lib/management/management.properties
+13
-0
test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java
...agement/jmxremote/bootstrap/JMXAgentInterfaceBinding.java
+297
-0
test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java
...nagement/jmxremote/bootstrap/JMXInterfaceBindingTest.java
+241
-0
未找到文件。
src/share/classes/sun/management/jmxremote/ConnectorBootstrap.java
浏览文件 @
919afc52
...
...
@@ -30,9 +30,12 @@ import java.io.File;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.Serializable
;
import
java.lang.management.ManagementFactory
;
import
java.net.InetAddress
;
import
java.net.MalformedURLException
;
import
java.net.Socket
;
import
java.net.ServerSocket
;
import
java.net.UnknownHostException
;
import
java.rmi.NoSuchObjectException
;
import
java.rmi.Remote
;
...
...
@@ -40,6 +43,7 @@ import java.rmi.RemoteException;
import
java.rmi.registry.Registry
;
import
java.rmi.server.RMIClientSocketFactory
;
import
java.rmi.server.RMIServerSocketFactory
;
import
java.rmi.server.RMISocketFactory
;
import
java.rmi.server.RemoteObject
;
import
java.rmi.server.UnicastRemoteObject
;
import
java.security.KeyStore
;
...
...
@@ -60,6 +64,8 @@ import javax.management.remote.JMXServiceURL;
import
javax.management.remote.rmi.RMIConnectorServer
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLSocket
;
import
javax.net.ssl.SSLSocketFactory
;
import
javax.net.ssl.TrustManagerFactory
;
import
javax.rmi.ssl.SslRMIClientSocketFactory
;
import
javax.rmi.ssl.SslRMIServerSocketFactory
;
...
...
@@ -107,6 +113,8 @@ public final class ConnectorBootstrap {
public
static
final
String
PORT
=
"com.sun.management.jmxremote.port"
;
public
static
final
String
HOST
=
"com.sun.management.jmxremote.host"
;
public
static
final
String
RMI_PORT
=
"com.sun.management.jmxremote.rmi.port"
;
public
static
final
String
CONFIG_FILE_NAME
=
...
...
@@ -424,10 +432,14 @@ public final class ConnectorBootstrap {
checkAccessFile
(
accessFileName
);
}
final
String
bindAddress
=
props
.
getProperty
(
PropertyNames
.
HOST
);
if
(
log
.
debugOn
())
{
log
.
debug
(
"startRemoteConnectorServer"
,
Agent
.
getText
(
"jmxremote.ConnectorBootstrap.starting"
)
+
"\n\t"
+
PropertyNames
.
PORT
+
"="
+
port
+
(
bindAddress
==
null
?
""
:
"\n\t"
+
PropertyNames
.
HOST
+
"="
+
bindAddress
)
+
"\n\t"
+
PropertyNames
.
RMI_PORT
+
"="
+
rmiPort
+
"\n\t"
+
PropertyNames
.
USE_SSL
+
"="
+
useSsl
+
"\n\t"
+
PropertyNames
.
USE_REGISTRY_SSL
+
"="
+
useRegistrySsl
+
...
...
@@ -458,7 +470,7 @@ public final class ConnectorBootstrap {
sslConfigFileName
,
enabledCipherSuitesList
,
enabledProtocolsList
,
sslNeedClientAuth
,
useAuthentication
,
loginConfigName
,
passwordFileName
,
accessFileName
);
passwordFileName
,
accessFileName
,
bindAddress
);
cs
=
data
.
jmxConnectorServer
;
url
=
data
.
jmxRemoteURL
;
log
.
config
(
"startRemoteConnectorServer"
,
...
...
@@ -628,12 +640,13 @@ public final class ConnectorBootstrap {
String
sslConfigFileName
,
String
[]
enabledCipherSuites
,
String
[]
enabledProtocols
,
boolean
sslNeedClientAuth
)
{
boolean
sslNeedClientAuth
,
String
bindAddress
)
{
if
(
sslConfigFileName
==
null
)
{
return
new
SslRMIServer
SocketFactory
(
return
new
HostAwareSsl
SocketFactory
(
enabledCipherSuites
,
enabledProtocols
,
sslNeedClientAuth
);
sslNeedClientAuth
,
bindAddress
);
}
else
{
checkRestrictedFile
(
sslConfigFileName
);
try
{
...
...
@@ -687,11 +700,11 @@ public final class ConnectorBootstrap {
SSLContext
ctx
=
SSLContext
.
getInstance
(
"SSL"
);
ctx
.
init
(
kmf
.
getKeyManagers
(),
tmf
.
getTrustManagers
(),
null
);
return
new
SslRMIServer
SocketFactory
(
return
new
HostAwareSsl
SocketFactory
(
ctx
,
enabledCipherSuites
,
enabledProtocols
,
sslNeedClientAuth
);
sslNeedClientAuth
,
bindAddress
);
}
catch
(
Exception
e
)
{
throw
new
AgentConfigurationError
(
AGENT_EXCEPTION
,
e
,
e
.
toString
());
}
...
...
@@ -711,7 +724,8 @@ public final class ConnectorBootstrap {
boolean
useAuthentication
,
String
loginConfigName
,
String
passwordFileName
,
String
accessFileName
)
String
accessFileName
,
String
bindAddress
)
throws
IOException
,
MalformedURLException
{
/* Make sure we use non-guessable RMI object IDs. Otherwise
...
...
@@ -719,7 +733,7 @@ public final class ConnectorBootstrap {
* IDs. */
System
.
setProperty
(
"java.rmi.server.randomIDs"
,
"true"
);
JMXServiceURL
url
=
new
JMXServiceURL
(
"rmi"
,
null
,
rmiPort
);
JMXServiceURL
url
=
new
JMXServiceURL
(
"rmi"
,
bindAddress
,
rmiPort
);
Map
<
String
,
Object
>
env
=
new
HashMap
<>();
...
...
@@ -727,6 +741,8 @@ public final class ConnectorBootstrap {
env
.
put
(
RMIExporter
.
EXPORTER_ATTRIBUTE
,
exporter
);
boolean
useSocketFactory
=
bindAddress
!=
null
&&
!
useSsl
;
if
(
useAuthentication
)
{
if
(
loginConfigName
!=
null
)
{
env
.
put
(
"jmx.remote.x.login.config"
,
loginConfigName
);
...
...
@@ -751,7 +767,7 @@ public final class ConnectorBootstrap {
csf
=
new
SslRMIClientSocketFactory
();
ssf
=
createSslRMIServerSocketFactory
(
sslConfigFileName
,
enabledCipherSuites
,
enabledProtocols
,
sslNeedClientAuth
);
enabledProtocols
,
sslNeedClientAuth
,
bindAddress
);
}
if
(
useSsl
)
{
...
...
@@ -761,6 +777,12 @@ public final class ConnectorBootstrap {
ssf
);
}
if
(
useSocketFactory
)
{
ssf
=
new
HostAwareSocketFactory
(
bindAddress
);
env
.
put
(
RMIConnectorServer
.
RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE
,
ssf
);
}
JMXConnectorServer
connServer
=
null
;
try
{
connServer
=
...
...
@@ -780,6 +802,10 @@ public final class ConnectorBootstrap {
registry
=
new
SingleEntryRegistry
(
port
,
csf
,
ssf
,
"jmxrmi"
,
exporter
.
firstExported
);
}
else
if
(
useSocketFactory
)
{
registry
=
new
SingleEntryRegistry
(
port
,
csf
,
ssf
,
"jmxrmi"
,
exporter
.
firstExported
);
}
else
{
registry
=
new
SingleEntryRegistry
(
port
,
...
...
@@ -813,4 +839,172 @@ public final class ConnectorBootstrap {
private
static
final
ClassLogger
log
=
new
ClassLogger
(
ConnectorBootstrap
.
class
.
getPackage
().
getName
(),
"ConnectorBootstrap"
);
private
static
class
HostAwareSocketFactory
implements
RMIServerSocketFactory
{
private
final
String
bindAddress
;
private
HostAwareSocketFactory
(
String
bindAddress
)
{
this
.
bindAddress
=
bindAddress
;
}
@Override
public
ServerSocket
createServerSocket
(
int
port
)
throws
IOException
{
if
(
bindAddress
==
null
)
{
return
new
ServerSocket
(
port
);
}
else
{
try
{
InetAddress
addr
=
InetAddress
.
getByName
(
bindAddress
);
return
new
ServerSocket
(
port
,
0
,
addr
);
}
catch
(
UnknownHostException
e
)
{
return
new
ServerSocket
(
port
);
}
}
}
}
private
static
class
HostAwareSslSocketFactory
extends
SslRMIServerSocketFactory
{
private
final
String
bindAddress
;
private
final
String
[]
enabledCipherSuites
;
private
final
String
[]
enabledProtocols
;
private
final
boolean
needClientAuth
;
private
final
SSLContext
context
;
private
HostAwareSslSocketFactory
(
String
[]
enabledCipherSuites
,
String
[]
enabledProtocols
,
boolean
sslNeedClientAuth
,
String
bindAddress
)
throws
IllegalArgumentException
{
this
(
null
,
enabledCipherSuites
,
enabledProtocols
,
sslNeedClientAuth
,
bindAddress
);
}
private
HostAwareSslSocketFactory
(
SSLContext
ctx
,
String
[]
enabledCipherSuites
,
String
[]
enabledProtocols
,
boolean
sslNeedClientAuth
,
String
bindAddress
)
throws
IllegalArgumentException
{
this
.
context
=
ctx
;
this
.
bindAddress
=
bindAddress
;
this
.
enabledProtocols
=
enabledProtocols
;
this
.
enabledCipherSuites
=
enabledCipherSuites
;
this
.
needClientAuth
=
sslNeedClientAuth
;
checkValues
(
ctx
,
enabledCipherSuites
,
enabledProtocols
);
}
@Override
public
ServerSocket
createServerSocket
(
int
port
)
throws
IOException
{
if
(
bindAddress
!=
null
)
{
try
{
InetAddress
addr
=
InetAddress
.
getByName
(
bindAddress
);
return
new
SslServerSocket
(
port
,
0
,
addr
,
context
,
enabledCipherSuites
,
enabledProtocols
,
needClientAuth
);
}
catch
(
UnknownHostException
e
)
{
return
new
SslServerSocket
(
port
,
context
,
enabledCipherSuites
,
enabledProtocols
,
needClientAuth
);
}
}
else
{
return
new
SslServerSocket
(
port
,
context
,
enabledCipherSuites
,
enabledProtocols
,
needClientAuth
);
}
}
private
static
void
checkValues
(
SSLContext
context
,
String
[]
enabledCipherSuites
,
String
[]
enabledProtocols
)
throws
IllegalArgumentException
{
// Force the initialization of the default at construction time,
// rather than delaying it to the first time createServerSocket()
// is called.
//
final
SSLSocketFactory
sslSocketFactory
=
context
==
null
?
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
()
:
context
.
getSocketFactory
();
SSLSocket
sslSocket
=
null
;
if
(
enabledCipherSuites
!=
null
||
enabledProtocols
!=
null
)
{
try
{
sslSocket
=
(
SSLSocket
)
sslSocketFactory
.
createSocket
();
}
catch
(
Exception
e
)
{
final
String
msg
=
"Unable to check if the cipher suites "
+
"and protocols to enable are supported"
;
throw
(
IllegalArgumentException
)
new
IllegalArgumentException
(
msg
).
initCause
(
e
);
}
}
// Check if all the cipher suites and protocol versions to enable
// are supported by the underlying SSL/TLS implementation and if
// true create lists from arrays.
//
if
(
enabledCipherSuites
!=
null
)
{
sslSocket
.
setEnabledCipherSuites
(
enabledCipherSuites
);
}
if
(
enabledProtocols
!=
null
)
{
sslSocket
.
setEnabledProtocols
(
enabledProtocols
);
}
}
}
private
static
class
SslServerSocket
extends
ServerSocket
{
private
static
SSLSocketFactory
defaultSSLSocketFactory
;
private
final
String
[]
enabledCipherSuites
;
private
final
String
[]
enabledProtocols
;
private
final
boolean
needClientAuth
;
private
final
SSLContext
context
;
private
SslServerSocket
(
int
port
,
SSLContext
ctx
,
String
[]
enabledCipherSuites
,
String
[]
enabledProtocols
,
boolean
needClientAuth
)
throws
IOException
{
super
(
port
);
this
.
enabledProtocols
=
enabledProtocols
;
this
.
enabledCipherSuites
=
enabledCipherSuites
;
this
.
needClientAuth
=
needClientAuth
;
this
.
context
=
ctx
;
}
private
SslServerSocket
(
int
port
,
int
backlog
,
InetAddress
bindAddr
,
SSLContext
ctx
,
String
[]
enabledCipherSuites
,
String
[]
enabledProtocols
,
boolean
needClientAuth
)
throws
IOException
{
super
(
port
,
backlog
,
bindAddr
);
this
.
enabledProtocols
=
enabledProtocols
;
this
.
enabledCipherSuites
=
enabledCipherSuites
;
this
.
needClientAuth
=
needClientAuth
;
this
.
context
=
ctx
;
}
@Override
public
Socket
accept
()
throws
IOException
{
final
SSLSocketFactory
sslSocketFactory
=
context
==
null
?
getDefaultSSLSocketFactory
()
:
context
.
getSocketFactory
();
Socket
socket
=
super
.
accept
();
SSLSocket
sslSocket
=
(
SSLSocket
)
sslSocketFactory
.
createSocket
(
socket
,
socket
.
getInetAddress
().
getHostName
(),
socket
.
getPort
(),
true
);
sslSocket
.
setUseClientMode
(
false
);
if
(
enabledCipherSuites
!=
null
)
{
sslSocket
.
setEnabledCipherSuites
(
enabledCipherSuites
);
}
if
(
enabledProtocols
!=
null
)
{
sslSocket
.
setEnabledProtocols
(
enabledProtocols
);
}
sslSocket
.
setNeedClientAuth
(
needClientAuth
);
return
sslSocket
;
}
private
static
synchronized
SSLSocketFactory
getDefaultSSLSocketFactory
()
{
if
(
defaultSSLSocketFactory
==
null
)
{
defaultSSLSocketFactory
=
(
SSLSocketFactory
)
SSLSocketFactory
.
getDefault
();
return
defaultSSLSocketFactory
;
}
else
{
return
defaultSSLSocketFactory
;
}
}
}
}
src/share/lib/management/management.properties
浏览文件 @
919afc52
...
...
@@ -316,3 +316,16 @@
# For a non-default password file location use the following line
# com.sun.management.jmxremote.access.file=filepath
#
# ################ Management agent listen interface #########################
#
# com.sun.management.jmxremote.host=<host-or-interface-name>
# Specifies the local interface on which the JMX RMI agent will bind.
# This is useful when running on machines which have several
# interfaces defined. It makes it possible to listen to a specific
# subnet accessible through that interface.
#
# The format of the value for that property is any string accepted
# by java.net.InetAddress.getByName(String).
#
test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java
0 → 100644
浏览文件 @
919afc52
/*
* Copyright (c) 2015, Red Hat Inc
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
java.io.IOException
;
import
java.net.InetAddress
;
import
java.net.InetSocketAddress
;
import
java.net.MalformedURLException
;
import
java.net.Socket
;
import
java.net.SocketAddress
;
import
java.net.UnknownHostException
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.TimeUnit
;
import
javax.management.remote.JMXConnector
;
import
javax.management.remote.JMXConnectorFactory
;
import
javax.management.remote.JMXServiceURL
;
import
javax.management.remote.rmi.RMIConnectorServer
;
import
javax.net.ssl.SSLSocket
;
import
javax.net.ssl.SSLSocketFactory
;
import
javax.rmi.ssl.SslRMIClientSocketFactory
;
/**
* Tests client connections to the JDK's built-in JMX agent server on the given
* ports/interface combinations.
*
* @see JMXInterfaceBindingTest
*
* @author Severin Gehwolf <sgehwolf@redhat.com>
*
* Usage:
*
* SSL:
* java -Dcom.sun.management.jmxremote.ssl.need.client.auth=true \
* -Dcom.sun.management.jmxremote.host=127.0.0.1 \
* -Dcom.sun.management.jmxremote.port=9111 \
* -Dcom.sun.management.jmxremote.rmi.port=9112 \
* -Dcom.sun.management.jmxremote.authenticate=false \
* -Dcom.sun.management.jmxremote.ssl=true \
* -Dcom.sun.management.jmxremote.registry.ssl=true
* -Djavax.net.ssl.keyStore=... \
* -Djavax.net.ssl.keyStorePassword=... \
* JMXAgentInterfaceBinding 127.0.0.1 9111 9112 true
*
* Non-SSL:
* java -Dcom.sun.management.jmxremote.host=127.0.0.1 \
* -Dcom.sun.management.jmxremote.port=9111 \
* -Dcom.sun.management.jmxremote.rmi.port=9112 \
* -Dcom.sun.management.jmxremote.authenticate=false \
* -Dcom.sun.management.jmxremote.ssl=false \
* JMXAgentInterfaceBinding 127.0.0.1 9111 9112 false
*
*/
public
class
JMXAgentInterfaceBinding
{
private
final
MainThread
mainThread
;
public
JMXAgentInterfaceBinding
(
InetAddress
bindAddress
,
int
jmxPort
,
int
rmiPort
,
boolean
useSSL
)
{
this
.
mainThread
=
new
MainThread
(
bindAddress
,
jmxPort
,
rmiPort
,
useSSL
);
}
public
void
startEndpoint
()
{
mainThread
.
start
();
try
{
mainThread
.
join
();
}
catch
(
InterruptedException
e
)
{
throw
new
RuntimeException
(
"Test failed"
,
e
);
}
if
(
mainThread
.
isFailed
())
{
mainThread
.
rethrowException
();
}
}
public
static
void
main
(
String
[]
args
)
{
if
(
args
.
length
!=
4
)
{
throw
new
RuntimeException
(
"Test failed. usage: java JMXInterfaceBindingTest <BIND_ADDRESS> <JMX_PORT> <RMI_PORT> {true|false}"
);
}
int
jmxPort
=
parsePortFromString
(
args
[
1
]);
int
rmiPort
=
parsePortFromString
(
args
[
2
]);
boolean
useSSL
=
Boolean
.
parseBoolean
(
args
[
3
]);
String
strBindAddr
=
args
[
0
];
System
.
out
.
println
(
"DEBUG: Running test for triplet (hostname,jmxPort,rmiPort) = ("
+
strBindAddr
+
","
+
jmxPort
+
","
+
rmiPort
+
"), useSSL = "
+
useSSL
);
InetAddress
bindAddress
;
try
{
bindAddress
=
InetAddress
.
getByName
(
args
[
0
]);
}
catch
(
UnknownHostException
e
)
{
throw
new
RuntimeException
(
"Test failed. Unknown ip: "
+
args
[
0
]);
}
JMXAgentInterfaceBinding
test
=
new
JMXAgentInterfaceBinding
(
bindAddress
,
jmxPort
,
rmiPort
,
useSSL
);
test
.
startEndpoint
();
// Expect for main test to terminate process
}
private
static
int
parsePortFromString
(
String
port
)
{
try
{
return
Integer
.
parseInt
(
port
);
}
catch
(
NumberFormatException
e
)
{
throw
new
RuntimeException
(
"Invalid port specified. Not an integer! Value was: "
+
port
);
}
}
private
static
class
JMXConnectorThread
extends
Thread
{
private
final
InetAddress
addr
;
private
final
int
jmxPort
;
private
final
int
rmiPort
;
private
final
boolean
useSSL
;
private
final
CountDownLatch
latch
;
private
boolean
failed
;
private
boolean
jmxConnectWorked
;
private
boolean
rmiConnectWorked
;
private
JMXConnectorThread
(
InetAddress
addr
,
int
jmxPort
,
int
rmiPort
,
boolean
useSSL
,
CountDownLatch
latch
)
{
this
.
addr
=
addr
;
this
.
jmxPort
=
jmxPort
;
this
.
rmiPort
=
rmiPort
;
this
.
latch
=
latch
;
this
.
useSSL
=
useSSL
;
}
@Override
public
void
run
()
{
try
{
connect
();
}
catch
(
IOException
e
)
{
failed
=
true
;
}
}
private
void
connect
()
throws
IOException
{
System
.
out
.
println
(
"JMXConnectorThread: Attempting JMX connection on: "
+
addr
.
getHostAddress
()
+
" on port "
+
jmxPort
);
JMXServiceURL
url
;
try
{
url
=
new
JMXServiceURL
(
"service:jmx:rmi:///jndi/rmi://"
+
addr
.
getHostAddress
()
+
":"
+
jmxPort
+
"/jmxrmi"
);
}
catch
(
MalformedURLException
e
)
{
throw
new
RuntimeException
(
"Test failed."
,
e
);
}
Map
<
String
,
Object
>
env
=
new
HashMap
<>();
if
(
useSSL
)
{
SslRMIClientSocketFactory
csf
=
new
SslRMIClientSocketFactory
();
env
.
put
(
"com.sun.jndi.rmi.factory.socket"
,
csf
);
env
.
put
(
RMIConnectorServer
.
RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE
,
csf
);
}
// connect and immediately close
JMXConnector
c
=
JMXConnectorFactory
.
connect
(
url
,
env
);
c
.
close
();
System
.
out
.
println
(
"JMXConnectorThread: connection to JMX worked"
);
jmxConnectWorked
=
true
;
checkRmiSocket
();
latch
.
countDown
();
// signal we are done.
}
private
void
checkRmiSocket
()
throws
IOException
{
Socket
rmiConnection
;
if
(
useSSL
)
{
rmiConnection
=
SSLSocketFactory
.
getDefault
().
createSocket
();
}
else
{
rmiConnection
=
new
Socket
();
}
SocketAddress
target
=
new
InetSocketAddress
(
addr
,
rmiPort
);
rmiConnection
.
connect
(
target
);
if
(
useSSL
)
{
((
SSLSocket
)
rmiConnection
).
startHandshake
();
}
System
.
out
.
println
(
"JMXConnectorThread: connection to rmi socket worked host/port = "
+
addr
.
getHostAddress
()
+
"/"
+
rmiPort
);
rmiConnectWorked
=
true
;
// Closing the channel without sending any data will cause an
// java.io.EOFException on the server endpoint. We don't care about this
// though, since we only want to test if we can connect.
rmiConnection
.
close
();
}
public
boolean
isFailed
()
{
return
failed
;
}
public
boolean
jmxConnectionWorked
()
{
return
jmxConnectWorked
;
}
public
boolean
rmiConnectionWorked
()
{
return
rmiConnectWorked
;
}
}
private
static
class
MainThread
extends
Thread
{
private
static
final
int
WAIT_FOR_JMX_AGENT_TIMEOUT_MS
=
500
;
private
final
InetAddress
bindAddress
;
private
final
int
jmxPort
;
private
final
int
rmiPort
;
private
final
boolean
useSSL
;
private
boolean
terminated
=
false
;
private
boolean
jmxAgentStarted
=
false
;
private
Exception
excptn
;
private
MainThread
(
InetAddress
bindAddress
,
int
jmxPort
,
int
rmiPort
,
boolean
useSSL
)
{
this
.
bindAddress
=
bindAddress
;
this
.
jmxPort
=
jmxPort
;
this
.
rmiPort
=
rmiPort
;
this
.
useSSL
=
useSSL
;
}
@Override
public
void
run
()
{
try
{
waitUntilReadyForConnections
();
// Do nothing, but wait for termination.
try
{
while
(!
terminated
)
{
Thread
.
sleep
(
100
);
}
}
catch
(
InterruptedException
e
)
{
// ignore
}
System
.
out
.
println
(
"MainThread: Thread stopped."
);
}
catch
(
Exception
e
)
{
this
.
excptn
=
e
;
}
}
private
void
waitUntilReadyForConnections
()
{
CountDownLatch
latch
=
new
CountDownLatch
(
1
);
JMXConnectorThread
connectionTester
=
new
JMXConnectorThread
(
bindAddress
,
jmxPort
,
rmiPort
,
useSSL
,
latch
);
connectionTester
.
start
();
boolean
expired
=
false
;
try
{
expired
=
!
latch
.
await
(
WAIT_FOR_JMX_AGENT_TIMEOUT_MS
,
TimeUnit
.
MILLISECONDS
);
System
.
out
.
println
(
"MainThread: Finished waiting for JMX agent to become available: expired == "
+
expired
);
jmxAgentStarted
=
!
expired
;
}
catch
(
InterruptedException
e
)
{
throw
new
RuntimeException
(
"Test failed"
,
e
);
}
if
(!
jmxAgentStarted
)
{
throw
new
RuntimeException
(
"Test failed. JMX server agents not becoming available."
);
}
if
(
connectionTester
.
isFailed
()
||
!
connectionTester
.
jmxConnectionWorked
()
||
!
connectionTester
.
rmiConnectionWorked
())
{
throw
new
RuntimeException
(
"Test failed. JMX agent does not seem ready. See log output for details."
);
}
// The main test expects this exact message being printed
System
.
out
.
println
(
"MainThread: Ready for connections"
);
}
private
boolean
isFailed
()
{
return
excptn
!=
null
;
}
private
void
rethrowException
()
throws
RuntimeException
{
throw
new
RuntimeException
(
excptn
);
}
}
}
test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java
0 → 100644
浏览文件 @
919afc52
/*
* Copyright (c) 2015, Red Hat Inc
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import
java.io.File
;
import
java.net.InetAddress
;
import
java.net.UnknownHostException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.TimeUnit
;
import
java.util.function.Predicate
;
import
jdk.testlibrary.ProcessTools
;
/**
* NOTE:
* This test requires at least a setup similar to the following in
* /etc/hosts file (or the windows equivalent). I.e. it expects it to
* be multi-homed and not both being the loop-back interface.
* For example:
* ----->8-------- /etc/hosts ----------->8---
* 127.0.0.1 localhost
* 192.168.0.1 localhost
* ----->8-------- /etc/hosts ----------->8---
*
* @test
* @bug 6425769
* @summary Test JMX agent host address binding. Same ports but different
* interfaces to bind to (using plain sockets and SSL sockets).
*
* @modules java.management/sun.management
* java.management/sun.management.jmxremote
* @library /lib/testlibrary
* @build jdk.testlibrary.* JMXAgentInterfaceBinding
* @run main/timeout=5 JMXInterfaceBindingTest
*/
public
class
JMXInterfaceBindingTest
{
public
static
final
int
COMMUNICATION_ERROR_EXIT_VAL
=
1
;
public
static
final
int
STOP_PROCESS_EXIT_VAL
=
137
;
public
static
final
int
JMX_PORT
=
9111
;
public
static
final
int
RMI_PORT
=
9112
;
public
static
final
String
READY_MSG
=
"MainThread: Ready for connections"
;
public
static
final
String
TEST_CLASS
=
JMXAgentInterfaceBinding
.
class
.
getSimpleName
();
public
static
final
String
KEYSTORE_LOC
=
System
.
getProperty
(
"test.src"
,
"."
)
+
File
.
separator
+
"ssl"
+
File
.
separator
+
"keystore"
;
public
static
final
String
TRUSTSTORE_LOC
=
System
.
getProperty
(
"test.src"
,
"."
)
+
File
.
separator
+
"ssl"
+
File
.
separator
+
"truststore"
;
public
static
final
String
TEST_CLASSPATH
=
System
.
getProperty
(
"test.classes"
,
"."
);
public
void
run
(
InetAddress
[]
addrs
)
{
System
.
out
.
println
(
"DEBUG: Running tests with plain sockets."
);
runTests
(
addrs
,
false
);
System
.
out
.
println
(
"DEBUG: Running tests with SSL sockets."
);
runTests
(
addrs
,
true
);
}
private
void
runTests
(
InetAddress
[]
addrs
,
boolean
useSSL
)
{
TestProcessThread
[]
jvms
=
new
TestProcessThread
[
addrs
.
length
];
for
(
int
i
=
0
;
i
<
addrs
.
length
;
i
++)
{
System
.
out
.
println
();
String
msg
=
String
.
format
(
"DEBUG: Launching java tester for triplet (HOSTNAME,JMX_PORT,RMI_PORT) == (%s,%d,%d)"
,
addrs
[
i
].
getHostAddress
(),
JMX_PORT
,
RMI_PORT
);
System
.
out
.
println
(
msg
);
jvms
[
i
]
=
runJMXBindingTest
(
addrs
[
i
],
useSSL
);
jvms
[
i
].
start
();
System
.
out
.
println
(
"DEBUG: Started "
+
(
i
+
1
)
+
" Process(es)."
);
}
int
failedProcesses
=
0
;
for
(
TestProcessThread
pt:
jvms
)
{
try
{
pt
.
stopProcess
();
pt
.
join
();
}
catch
(
InterruptedException
e
)
{
System
.
err
.
println
(
"Failed to stop process: "
+
pt
.
getName
());
throw
new
RuntimeException
(
"Test failed"
,
e
);
}
int
exitValue
=
pt
.
getExitValue
();
// If there is a communication error (the case we care about)
// we get a exit code of 1
if
(
exitValue
==
COMMUNICATION_ERROR_EXIT_VAL
)
{
// Failure case since the java processes should still be
// running.
System
.
err
.
println
(
"Test FAILURE on "
+
pt
.
getName
());
failedProcesses
++;
}
else
if
(
exitValue
==
STOP_PROCESS_EXIT_VAL
)
{
System
.
out
.
println
(
"DEBUG: OK. Spawned java process terminated with expected exit code of "
+
STOP_PROCESS_EXIT_VAL
);
}
else
{
System
.
err
.
println
(
"Test FAILURE on "
+
pt
.
getName
()
+
" reason: Unexpected exit code => "
+
exitValue
);
failedProcesses
++;
}
}
if
(
failedProcesses
>
0
)
{
throw
new
RuntimeException
(
"Test FAILED. "
+
failedProcesses
+
" out of "
+
addrs
.
length
+
" process(es) failed to start the JMX agent."
);
}
}
private
TestProcessThread
runJMXBindingTest
(
InetAddress
a
,
boolean
useSSL
)
{
List
<
String
>
args
=
new
ArrayList
<>();
args
.
add
(
"-classpath"
);
args
.
add
(
TEST_CLASSPATH
);
args
.
add
(
"-Dcom.sun.management.jmxremote.host="
+
a
.
getHostAddress
());
args
.
add
(
"-Dcom.sun.management.jmxremote.port="
+
JMX_PORT
);
args
.
add
(
"-Dcom.sun.management.jmxremote.rmi.port="
+
RMI_PORT
);
args
.
add
(
"-Dcom.sun.management.jmxremote.authenticate=false"
);
args
.
add
(
"-Dcom.sun.management.jmxremote.ssl="
+
Boolean
.
toString
(
useSSL
));
if
(
useSSL
)
{
args
.
add
(
"-Dcom.sun.management.jmxremote.registry.ssl=true"
);
args
.
add
(
"-Djavax.net.ssl.keyStore="
+
KEYSTORE_LOC
);
args
.
add
(
"-Djavax.net.ssl.trustStore="
+
TRUSTSTORE_LOC
);
args
.
add
(
"-Djavax.net.ssl.keyStorePassword=password"
);
args
.
add
(
"-Djavax.net.ssl.trustStorePassword=trustword"
);
}
args
.
add
(
TEST_CLASS
);
args
.
add
(
a
.
getHostAddress
());
args
.
add
(
Integer
.
toString
(
JMX_PORT
));
args
.
add
(
Integer
.
toString
(
RMI_PORT
));
args
.
add
(
Boolean
.
toString
(
useSSL
));
try
{
ProcessBuilder
builder
=
ProcessTools
.
createJavaProcessBuilder
(
args
.
toArray
(
new
String
[]
{}));
System
.
out
.
println
(
ProcessTools
.
getCommandLine
(
builder
));
TestProcessThread
jvm
=
new
TestProcessThread
(
"JMX-Tester-"
+
a
.
getHostAddress
(),
JMXInterfaceBindingTest:
:
isJMXAgentResponseAvailable
,
builder
);
return
jvm
;
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Test failed"
,
e
);
}
}
private
static
boolean
isJMXAgentResponseAvailable
(
String
line
)
{
if
(
line
.
equals
(
READY_MSG
))
{
System
.
out
.
println
(
"DEBUG: Found expected READY_MSG."
);
return
true
;
}
else
if
(
line
.
startsWith
(
"Error:"
))
{
// Allow for a JVM process that exits with
// "Error: JMX connector server communication error: ..."
// to continue as well since we handle that case elsewhere.
// This has the effect that the test does not timeout and
// fails with an exception in the test.
System
.
err
.
println
(
"PROBLEM: JMX agent of target JVM did not start as it should."
);
return
true
;
}
else
{
return
false
;
}
}
public
static
void
main
(
String
[]
args
)
{
InetAddress
[]
addrs
=
getAddressesForLocalHost
();
if
(
addrs
.
length
<
2
)
{
System
.
out
.
println
(
"Ignoring manual test since no more than one IPs are configured for 'localhost'"
);
System
.
exit
(
0
);
}
JMXInterfaceBindingTest
test
=
new
JMXInterfaceBindingTest
();
test
.
run
(
addrs
);
System
.
out
.
println
(
"All tests PASSED."
);
}
private
static
InetAddress
[]
getAddressesForLocalHost
()
{
InetAddress
[]
addrs
;
try
{
addrs
=
InetAddress
.
getAllByName
(
"localhost"
);
}
catch
(
UnknownHostException
e
)
{
throw
new
RuntimeException
(
"Test failed"
,
e
);
}
return
addrs
;
}
private
static
class
TestProcessThread
extends
Thread
{
private
final
Predicate
<
String
>
predicate
;
private
final
ProcessBuilder
pb
;
private
final
CountDownLatch
latch
;
private
Process
process
;
public
TestProcessThread
(
String
threadName
,
Predicate
<
String
>
predicate
,
ProcessBuilder
pb
)
{
super
(
threadName
);
this
.
predicate
=
predicate
;
this
.
pb
=
pb
;
this
.
latch
=
new
CountDownLatch
(
1
);
}
@Override
public
void
run
()
{
try
{
process
=
ProcessTools
.
startProcess
(
getName
(),
pb
,
predicate
,
10
,
TimeUnit
.
SECONDS
);
latch
.
countDown
();
process
.
waitFor
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Test failed"
,
e
);
}
}
public
void
stopProcess
()
{
try
{
latch
.
await
();
}
catch
(
InterruptedException
e1
)
{
throw
new
RuntimeException
(
"Test failed"
,
e1
);
}
if
(
process
!=
null
)
{
process
.
destroyForcibly
();
try
{
process
.
waitFor
();
}
catch
(
InterruptedException
e
)
{
throw
new
RuntimeException
(
"Test failed"
,
e
);
}
}
}
public
int
getExitValue
()
{
return
process
.
exitValue
();
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录