Merge
This commit is contained in:
commit
a02ddb869a
@ -70,7 +70,7 @@ endef
|
|||||||
# Filter com.sun.jdi.connect.Connector
|
# Filter com.sun.jdi.connect.Connector
|
||||||
$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector: \
|
$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector: \
|
||||||
$(JDK_TOPDIR)/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector \
|
$(JDK_TOPDIR)/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector \
|
||||||
$(HOTSPOT_TOPDIR)/agent/src/share/classes/META-INF/services/com.sun.jdi.connect.Connector
|
$(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/META-INF/services/com.sun.jdi.connect.Connector
|
||||||
$(process-provider)
|
$(process-provider)
|
||||||
|
|
||||||
# Copy the same service file into jdk.hotspot.agent so that they are kept the same.
|
# Copy the same service file into jdk.hotspot.agent so that they are kept the same.
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
WIN_VERIFY_LIB := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libverify/verify.lib
|
WIN_VERIFY_LIB := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libverify/verify.lib
|
||||||
|
|
||||||
|
# Hook to include the corresponding custom file, if present.
|
||||||
|
$(eval $(call IncludeCustomExtension, jdk, lib/CoreLibraries.gmk))
|
||||||
|
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# libfdlibm is statically linked with libjava below and not delivered into the
|
# libfdlibm is statically linked with libjava below and not delivered into the
|
||||||
# product on its own.
|
# product on its own.
|
||||||
@ -119,6 +123,9 @@ LIBJAVA_CFLAGS := $(addprefix -I, $(LIBJAVA_SRC_DIRS)) \
|
|||||||
-I$(SUPPORT_OUTPUTDIR)/headers/java.base \
|
-I$(SUPPORT_OUTPUTDIR)/headers/java.base \
|
||||||
-DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"'
|
-DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"'
|
||||||
|
|
||||||
|
# Make it possible to override this variable
|
||||||
|
LIBJAVA_MAPFILE ?= $(JDK_TOPDIR)/make/mapfiles/libjava/mapfile-vers
|
||||||
|
|
||||||
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||||
BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
|
BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
|
||||||
BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
|
BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
|
||||||
@ -146,7 +153,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
|
|||||||
System.c_CFLAGS := $(VERSION_CFLAGS), \
|
System.c_CFLAGS := $(VERSION_CFLAGS), \
|
||||||
jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
|
jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
|
||||||
DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
|
DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
|
||||||
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava/mapfile-vers, \
|
MAPFILE := $(LIBJAVA_MAPFILE), \
|
||||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||||
LDFLAGS_macosx := -L$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/, \
|
LDFLAGS_macosx := -L$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/, \
|
||||||
|
@ -27,6 +27,11 @@ include $(SPEC)
|
|||||||
include MakeBase.gmk
|
include MakeBase.gmk
|
||||||
include NativeCompilation.gmk
|
include NativeCompilation.gmk
|
||||||
|
|
||||||
|
# Hook to include the corresponding custom file, if present.
|
||||||
|
$(eval $(call IncludeCustomExtension, jdk, lib/LibCommon.gmk))
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc
|
GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc
|
||||||
|
|
||||||
# Absolute paths to lib files on windows for use in LDFLAGS. Should figure out a more
|
# Absolute paths to lib files on windows for use in LDFLAGS. Should figure out a more
|
||||||
@ -56,7 +61,7 @@ endif
|
|||||||
# Find the default set of src dirs for a native library.
|
# Find the default set of src dirs for a native library.
|
||||||
# Param 1 - module name
|
# Param 1 - module name
|
||||||
# Param 2 - library name
|
# Param 2 - library name
|
||||||
FindSrcDirsForLib = \
|
FindSrcDirsForLib += \
|
||||||
$(call uniq, $(wildcard \
|
$(call uniq, $(wildcard \
|
||||||
$(JDK_TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/lib$(strip $2) \
|
$(JDK_TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/lib$(strip $2) \
|
||||||
$(JDK_TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \
|
$(JDK_TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -29,23 +29,20 @@ package java.lang.ref;
|
|||||||
/**
|
/**
|
||||||
* Phantom reference objects, which are enqueued after the collector
|
* Phantom reference objects, which are enqueued after the collector
|
||||||
* determines that their referents may otherwise be reclaimed. Phantom
|
* determines that their referents may otherwise be reclaimed. Phantom
|
||||||
* references are most often used for scheduling pre-mortem cleanup actions in
|
* references are most often used to schedule post-mortem cleanup actions.
|
||||||
* a more flexible way than is possible with the Java finalization mechanism.
|
|
||||||
*
|
*
|
||||||
* <p> If the garbage collector determines at a certain point in time that the
|
* <p> Suppose the garbage collector determines at a certain point in time
|
||||||
* referent of a phantom reference is <a
|
* that an object is <a href="package-summary.html#reachability">
|
||||||
* href="package-summary.html#reachability">phantom reachable</a>, then at that
|
* phantom reachable</a>. At that time it will atomically clear
|
||||||
* time or at some later time it will enqueue the reference.
|
* all phantom references to that object and all phantom references to
|
||||||
|
* any other phantom-reachable objects from which that object is reachable.
|
||||||
|
* At the same time or at some later time it will enqueue those newly-cleared
|
||||||
|
* phantom references that are registered with reference queues.
|
||||||
*
|
*
|
||||||
* <p> In order to ensure that a reclaimable object remains so, the referent of
|
* <p> In order to ensure that a reclaimable object remains so, the referent of
|
||||||
* a phantom reference may not be retrieved: The {@code get} method of a
|
* a phantom reference may not be retrieved: The {@code get} method of a
|
||||||
* phantom reference always returns {@code null}.
|
* phantom reference always returns {@code null}.
|
||||||
*
|
*
|
||||||
* <p> Unlike soft and weak references, phantom references are not
|
|
||||||
* automatically cleared by the garbage collector as they are enqueued. An
|
|
||||||
* object that is reachable via phantom references will remain so until all
|
|
||||||
* such references are cleared or themselves become unreachable.
|
|
||||||
*
|
|
||||||
* @author Mark Reinhold
|
* @author Mark Reinhold
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
@ -69,8 +66,8 @@ public class PhantomReference<T> extends Reference<T> {
|
|||||||
*
|
*
|
||||||
* <p> It is possible to create a phantom reference with a {@code null}
|
* <p> It is possible to create a phantom reference with a {@code null}
|
||||||
* queue, but such a reference is completely useless: Its {@code get}
|
* queue, but such a reference is completely useless: Its {@code get}
|
||||||
* method will always return null and, since it does not have a queue, it
|
* method will always return {@code null} and, since it does not have a queue,
|
||||||
* will never be enqueued.
|
* it will never be enqueued.
|
||||||
*
|
*
|
||||||
* @param referent the object the new phantom reference will refer to
|
* @param referent the object the new phantom reference will refer to
|
||||||
* @param q the queue with which the reference is to be registered,
|
* @param q the queue with which the reference is to be registered,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -43,8 +43,7 @@
|
|||||||
* implementing memory-sensitive caches, weak references are for
|
* implementing memory-sensitive caches, weak references are for
|
||||||
* implementing canonicalizing mappings that do not prevent their keys
|
* implementing canonicalizing mappings that do not prevent their keys
|
||||||
* (or values) from being reclaimed, and phantom references are for
|
* (or values) from being reclaimed, and phantom references are for
|
||||||
* scheduling pre-mortem cleanup actions in a more flexible way than
|
* scheduling post-mortem cleanup actions.
|
||||||
* is possible with the Java finalization mechanism.
|
|
||||||
*
|
*
|
||||||
* <p> Each reference-object type is implemented by a subclass of the
|
* <p> Each reference-object type is implemented by a subclass of the
|
||||||
* abstract base {@link java.lang.ref.Reference} class.
|
* abstract base {@link java.lang.ref.Reference} class.
|
||||||
@ -64,9 +63,9 @@
|
|||||||
* object with a <em>reference queue</em> at the time the reference
|
* object with a <em>reference queue</em> at the time the reference
|
||||||
* object is created. Some time after the garbage collector
|
* object is created. Some time after the garbage collector
|
||||||
* determines that the reachability of the referent has changed to the
|
* determines that the reachability of the referent has changed to the
|
||||||
* value corresponding to the type of the reference, it will add the
|
* value corresponding to the type of the reference, it will clear the
|
||||||
* reference to the associated queue. At this point, the reference is
|
* reference and add it to the associated queue. At this point, the
|
||||||
* considered to be <em>enqueued</em>. The program may remove
|
* reference is considered to be <em>enqueued</em>. The program may remove
|
||||||
* references from a queue either by polling or by blocking until a
|
* references from a queue either by polling or by blocking until a
|
||||||
* reference becomes available. Reference queues are implemented by
|
* reference becomes available. Reference queues are implemented by
|
||||||
* the {@link java.lang.ref.ReferenceQueue} class.
|
* the {@link java.lang.ref.ReferenceQueue} class.
|
||||||
@ -92,16 +91,6 @@
|
|||||||
* structure, this check will add little overhead to the hashtable
|
* structure, this check will add little overhead to the hashtable
|
||||||
* access methods.
|
* access methods.
|
||||||
*
|
*
|
||||||
* <h3>Automatically-cleared references</h3>
|
|
||||||
*
|
|
||||||
* Soft and weak references are automatically cleared by the collector
|
|
||||||
* before being added to the queues with which they are registered, if
|
|
||||||
* any. Therefore soft and weak references need not be registered
|
|
||||||
* with a queue in order to be useful, while phantom references do.
|
|
||||||
* An object that is reachable via phantom references will remain so
|
|
||||||
* until all such references are cleared or themselves become
|
|
||||||
* unreachable.
|
|
||||||
*
|
|
||||||
* <a name="reachability"></a>
|
* <a name="reachability"></a>
|
||||||
* <h3>Reachability</h3>
|
* <h3>Reachability</h3>
|
||||||
*
|
*
|
||||||
|
@ -208,6 +208,9 @@ JVM_FillStackFrames(JNIEnv* env, jclass cls,
|
|||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
JVM_SetMethodInfo(JNIEnv* env, jobject frame);
|
JVM_SetMethodInfo(JNIEnv* env, jobject frame);
|
||||||
|
|
||||||
|
JNIEXPORT jobjectArray JNICALL
|
||||||
|
JVM_GetVmArguments(JNIEnv *env);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* java.lang.Thread
|
* java.lang.Thread
|
||||||
*/
|
*/
|
||||||
|
@ -660,7 +660,8 @@ initializeEncoding(JNIEnv *env)
|
|||||||
*/
|
*/
|
||||||
if ((strcmp(encname, "8859_1") == 0) ||
|
if ((strcmp(encname, "8859_1") == 0) ||
|
||||||
(strcmp(encname, "ISO8859-1") == 0) ||
|
(strcmp(encname, "ISO8859-1") == 0) ||
|
||||||
(strcmp(encname, "ISO8859_1") == 0))
|
(strcmp(encname, "ISO8859_1") == 0) ||
|
||||||
|
(strcmp(encname, "ISO-8859-1") == 0))
|
||||||
fastEncoding = FAST_8859_1;
|
fastEncoding = FAST_8859_1;
|
||||||
else if (strcmp(encname, "ISO646-US") == 0)
|
else if (strcmp(encname, "ISO646-US") == 0)
|
||||||
fastEncoding = FAST_646_US;
|
fastEncoding = FAST_646_US;
|
||||||
|
@ -30,9 +30,12 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.net.ServerSocket;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.rmi.NoSuchObjectException;
|
import java.rmi.NoSuchObjectException;
|
||||||
import java.rmi.Remote;
|
import java.rmi.Remote;
|
||||||
@ -40,6 +43,7 @@ import java.rmi.RemoteException;
|
|||||||
import java.rmi.registry.Registry;
|
import java.rmi.registry.Registry;
|
||||||
import java.rmi.server.RMIClientSocketFactory;
|
import java.rmi.server.RMIClientSocketFactory;
|
||||||
import java.rmi.server.RMIServerSocketFactory;
|
import java.rmi.server.RMIServerSocketFactory;
|
||||||
|
import java.rmi.server.RMISocketFactory;
|
||||||
import java.rmi.server.RemoteObject;
|
import java.rmi.server.RemoteObject;
|
||||||
import java.rmi.server.UnicastRemoteObject;
|
import java.rmi.server.UnicastRemoteObject;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
@ -60,6 +64,8 @@ import javax.management.remote.JMXServiceURL;
|
|||||||
import javax.management.remote.rmi.RMIConnectorServer;
|
import javax.management.remote.rmi.RMIConnectorServer;
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import javax.rmi.ssl.SslRMIClientSocketFactory;
|
import javax.rmi.ssl.SslRMIClientSocketFactory;
|
||||||
import javax.rmi.ssl.SslRMIServerSocketFactory;
|
import javax.rmi.ssl.SslRMIServerSocketFactory;
|
||||||
@ -107,6 +113,8 @@ public final class ConnectorBootstrap {
|
|||||||
|
|
||||||
public static final String PORT =
|
public static final String PORT =
|
||||||
"com.sun.management.jmxremote.port";
|
"com.sun.management.jmxremote.port";
|
||||||
|
public static final String HOST =
|
||||||
|
"com.sun.management.jmxremote.host";
|
||||||
public static final String RMI_PORT =
|
public static final String RMI_PORT =
|
||||||
"com.sun.management.jmxremote.rmi.port";
|
"com.sun.management.jmxremote.rmi.port";
|
||||||
public static final String CONFIG_FILE_NAME =
|
public static final String CONFIG_FILE_NAME =
|
||||||
@ -424,10 +432,14 @@ public final class ConnectorBootstrap {
|
|||||||
checkAccessFile(accessFileName);
|
checkAccessFile(accessFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final String bindAddress =
|
||||||
|
props.getProperty(PropertyNames.HOST);
|
||||||
|
|
||||||
if (log.debugOn()) {
|
if (log.debugOn()) {
|
||||||
log.debug("startRemoteConnectorServer",
|
log.debug("startRemoteConnectorServer",
|
||||||
Agent.getText("jmxremote.ConnectorBootstrap.starting") +
|
Agent.getText("jmxremote.ConnectorBootstrap.starting") +
|
||||||
"\n\t" + PropertyNames.PORT + "=" + port +
|
"\n\t" + PropertyNames.PORT + "=" + port +
|
||||||
|
(bindAddress == null ? "" : "\n\t" + PropertyNames.HOST + "=" + bindAddress) +
|
||||||
"\n\t" + PropertyNames.RMI_PORT + "=" + rmiPort +
|
"\n\t" + PropertyNames.RMI_PORT + "=" + rmiPort +
|
||||||
"\n\t" + PropertyNames.USE_SSL + "=" + useSsl +
|
"\n\t" + PropertyNames.USE_SSL + "=" + useSsl +
|
||||||
"\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl +
|
"\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl +
|
||||||
@ -458,7 +470,7 @@ public final class ConnectorBootstrap {
|
|||||||
sslConfigFileName, enabledCipherSuitesList,
|
sslConfigFileName, enabledCipherSuitesList,
|
||||||
enabledProtocolsList, sslNeedClientAuth,
|
enabledProtocolsList, sslNeedClientAuth,
|
||||||
useAuthentication, loginConfigName,
|
useAuthentication, loginConfigName,
|
||||||
passwordFileName, accessFileName);
|
passwordFileName, accessFileName, bindAddress);
|
||||||
cs = data.jmxConnectorServer;
|
cs = data.jmxConnectorServer;
|
||||||
url = data.jmxRemoteURL;
|
url = data.jmxRemoteURL;
|
||||||
log.config("startRemoteConnectorServer",
|
log.config("startRemoteConnectorServer",
|
||||||
@ -628,12 +640,13 @@ public final class ConnectorBootstrap {
|
|||||||
String sslConfigFileName,
|
String sslConfigFileName,
|
||||||
String[] enabledCipherSuites,
|
String[] enabledCipherSuites,
|
||||||
String[] enabledProtocols,
|
String[] enabledProtocols,
|
||||||
boolean sslNeedClientAuth) {
|
boolean sslNeedClientAuth,
|
||||||
|
String bindAddress) {
|
||||||
if (sslConfigFileName == null) {
|
if (sslConfigFileName == null) {
|
||||||
return new SslRMIServerSocketFactory(
|
return new HostAwareSslSocketFactory(
|
||||||
enabledCipherSuites,
|
enabledCipherSuites,
|
||||||
enabledProtocols,
|
enabledProtocols,
|
||||||
sslNeedClientAuth);
|
sslNeedClientAuth, bindAddress);
|
||||||
} else {
|
} else {
|
||||||
checkRestrictedFile(sslConfigFileName);
|
checkRestrictedFile(sslConfigFileName);
|
||||||
try {
|
try {
|
||||||
@ -687,11 +700,11 @@ public final class ConnectorBootstrap {
|
|||||||
SSLContext ctx = SSLContext.getInstance("SSL");
|
SSLContext ctx = SSLContext.getInstance("SSL");
|
||||||
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||||
|
|
||||||
return new SslRMIServerSocketFactory(
|
return new HostAwareSslSocketFactory(
|
||||||
ctx,
|
ctx,
|
||||||
enabledCipherSuites,
|
enabledCipherSuites,
|
||||||
enabledProtocols,
|
enabledProtocols,
|
||||||
sslNeedClientAuth);
|
sslNeedClientAuth, bindAddress);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
|
throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
|
||||||
}
|
}
|
||||||
@ -711,7 +724,8 @@ public final class ConnectorBootstrap {
|
|||||||
boolean useAuthentication,
|
boolean useAuthentication,
|
||||||
String loginConfigName,
|
String loginConfigName,
|
||||||
String passwordFileName,
|
String passwordFileName,
|
||||||
String accessFileName)
|
String accessFileName,
|
||||||
|
String bindAddress)
|
||||||
throws IOException, MalformedURLException {
|
throws IOException, MalformedURLException {
|
||||||
|
|
||||||
/* Make sure we use non-guessable RMI object IDs. Otherwise
|
/* Make sure we use non-guessable RMI object IDs. Otherwise
|
||||||
@ -719,7 +733,7 @@ public final class ConnectorBootstrap {
|
|||||||
* IDs. */
|
* IDs. */
|
||||||
System.setProperty("java.rmi.server.randomIDs", "true");
|
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<>();
|
Map<String, Object> env = new HashMap<>();
|
||||||
|
|
||||||
@ -727,6 +741,8 @@ public final class ConnectorBootstrap {
|
|||||||
|
|
||||||
env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
|
env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
|
||||||
|
|
||||||
|
boolean useSocketFactory = bindAddress != null && !useSsl;
|
||||||
|
|
||||||
if (useAuthentication) {
|
if (useAuthentication) {
|
||||||
if (loginConfigName != null) {
|
if (loginConfigName != null) {
|
||||||
env.put("jmx.remote.x.login.config", loginConfigName);
|
env.put("jmx.remote.x.login.config", loginConfigName);
|
||||||
@ -751,7 +767,7 @@ public final class ConnectorBootstrap {
|
|||||||
csf = new SslRMIClientSocketFactory();
|
csf = new SslRMIClientSocketFactory();
|
||||||
ssf = createSslRMIServerSocketFactory(
|
ssf = createSslRMIServerSocketFactory(
|
||||||
sslConfigFileName, enabledCipherSuites,
|
sslConfigFileName, enabledCipherSuites,
|
||||||
enabledProtocols, sslNeedClientAuth);
|
enabledProtocols, sslNeedClientAuth, bindAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useSsl) {
|
if (useSsl) {
|
||||||
@ -761,6 +777,12 @@ public final class ConnectorBootstrap {
|
|||||||
ssf);
|
ssf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (useSocketFactory) {
|
||||||
|
ssf = new HostAwareSocketFactory(bindAddress);
|
||||||
|
env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
|
||||||
|
ssf);
|
||||||
|
}
|
||||||
|
|
||||||
JMXConnectorServer connServer = null;
|
JMXConnectorServer connServer = null;
|
||||||
try {
|
try {
|
||||||
connServer =
|
connServer =
|
||||||
@ -780,6 +802,10 @@ public final class ConnectorBootstrap {
|
|||||||
registry =
|
registry =
|
||||||
new SingleEntryRegistry(port, csf, ssf,
|
new SingleEntryRegistry(port, csf, ssf,
|
||||||
"jmxrmi", exporter.firstExported);
|
"jmxrmi", exporter.firstExported);
|
||||||
|
} else if (useSocketFactory) {
|
||||||
|
registry =
|
||||||
|
new SingleEntryRegistry(port, csf, ssf,
|
||||||
|
"jmxrmi", exporter.firstExported);
|
||||||
} else {
|
} else {
|
||||||
registry =
|
registry =
|
||||||
new SingleEntryRegistry(port,
|
new SingleEntryRegistry(port,
|
||||||
@ -813,4 +839,172 @@ public final class ConnectorBootstrap {
|
|||||||
private static final ClassLogger log =
|
private static final ClassLogger log =
|
||||||
new ClassLogger(ConnectorBootstrap.class.getPackage().getName(),
|
new ClassLogger(ConnectorBootstrap.class.getPackage().getName(),
|
||||||
"ConnectorBootstrap");
|
"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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,3 +316,16 @@
|
|||||||
|
|
||||||
# For a non-default password file location use the following line
|
# For a non-default password file location use the following line
|
||||||
# com.sun.management.jmxremote.access.file=filepath
|
# 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).
|
||||||
|
#
|
||||||
|
@ -227,16 +227,10 @@ typedef struct jmmInterface_1_ {
|
|||||||
jint (JNICALL *GetOptionalSupport) (JNIEnv *env,
|
jint (JNICALL *GetOptionalSupport) (JNIEnv *env,
|
||||||
jmmOptionalSupport* support_ptr);
|
jmmOptionalSupport* support_ptr);
|
||||||
|
|
||||||
/* This is used by JDK 6 and earlier.
|
|
||||||
* For JDK 7 and after, use GetInputArgumentArray.
|
|
||||||
*/
|
|
||||||
jobject (JNICALL *GetInputArguments) (JNIEnv *env);
|
|
||||||
|
|
||||||
jint (JNICALL *GetThreadInfo) (JNIEnv *env,
|
jint (JNICALL *GetThreadInfo) (JNIEnv *env,
|
||||||
jlongArray ids,
|
jlongArray ids,
|
||||||
jint maxDepth,
|
jint maxDepth,
|
||||||
jobjectArray infoArray);
|
jobjectArray infoArray);
|
||||||
jobjectArray (JNICALL *GetInputArgumentArray) (JNIEnv *env);
|
|
||||||
|
|
||||||
jobjectArray (JNICALL *GetMemoryPools) (JNIEnv* env, jobject mgr);
|
jobjectArray (JNICALL *GetMemoryPools) (JNIEnv* env, jobject mgr);
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ JNIEXPORT jobjectArray JNICALL
|
|||||||
Java_sun_management_VMManagementImpl_getVmArguments0
|
Java_sun_management_VMManagementImpl_getVmArguments0
|
||||||
(JNIEnv *env, jobject dummy)
|
(JNIEnv *env, jobject dummy)
|
||||||
{
|
{
|
||||||
return jmm_interface->GetInputArgumentArray(env);
|
return JVM_GetVmArguments(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL
|
||||||
|
@ -121,7 +121,8 @@ jdbFailIfNotPresent 'System\..*bottom of loop'
|
|||||||
jdbFailIfNotPresent 'System\..*end of test'
|
jdbFailIfNotPresent 'System\..*end of test'
|
||||||
|
|
||||||
# make sure we had at least one full GC
|
# make sure we had at least one full GC
|
||||||
debuggeeFailIfNotPresent 'Full GC'
|
# Prior to JDK9-B95, the pattern was 'Full GC'
|
||||||
|
debuggeeMatchRegexp '^.*?\bPause Full\b\(System.gc\(\)\)\b.*?$'
|
||||||
|
|
||||||
# check for error message due to thread ID change
|
# check for error message due to thread ID change
|
||||||
debuggeeFailIfPresent \
|
debuggeeFailIfPresent \
|
||||||
|
101
jdk/test/java/lang/ref/PhantomReferentClearing.java
Normal file
101
jdk/test/java/lang/ref/PhantomReferentClearing.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8071507
|
||||||
|
* @summary Test that PhantomReferences are cleared when notified.
|
||||||
|
* @run main/othervm PhantomReferentClearing
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.ref.PhantomReference;
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PhantomReferentClearing {
|
||||||
|
|
||||||
|
private static final long ENQUEUE_TIMEOUT = 1000; // 1 sec, in millis
|
||||||
|
|
||||||
|
// P1 & P2 are PhantomReference objects
|
||||||
|
// O1 & O2 are objects
|
||||||
|
//
|
||||||
|
// -> is a strong reference
|
||||||
|
// => is a referent reference
|
||||||
|
//
|
||||||
|
// root -> P1
|
||||||
|
// root -> P2
|
||||||
|
// root -> O1
|
||||||
|
// root -> O2
|
||||||
|
// O1 -> O2
|
||||||
|
// P1 => O1
|
||||||
|
// P2 => O2
|
||||||
|
//
|
||||||
|
// (1) Remove root -> O1 and collect. P1 notified, P2 !notified.
|
||||||
|
// (2) Remove root -> O2 and collect.
|
||||||
|
//
|
||||||
|
// If phantom references are cleared when notified, as proposed by
|
||||||
|
// 8071507, then P2 should be notified, and the test passes.
|
||||||
|
//
|
||||||
|
// Otherwise, P2 does not get notified because it remains reachable
|
||||||
|
// from O1, which is being retained by P1. This fails the test.
|
||||||
|
|
||||||
|
private static final ReferenceQueue<Object> Q1 = new ReferenceQueue<>();
|
||||||
|
private static final ReferenceQueue<Object> Q2 = new ReferenceQueue<>();
|
||||||
|
|
||||||
|
private static volatile Object O2 = new Object();
|
||||||
|
private static volatile List<Object> O1 = new ArrayList<>();
|
||||||
|
static {
|
||||||
|
O1.add(O2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final PhantomReference<Object> P1 = new PhantomReference<>(O1, Q1);
|
||||||
|
private static final PhantomReference<Object> P2 = new PhantomReference<>(O2, Q2);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
|
||||||
|
// Collect, and verify neither P1 or P2 notified.
|
||||||
|
System.gc();
|
||||||
|
if (Q1.remove(ENQUEUE_TIMEOUT) != null) {
|
||||||
|
throw new RuntimeException("P1 already notified");
|
||||||
|
} else if (Q2.poll() != null) {
|
||||||
|
throw new RuntimeException("P2 already notified");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete root -> O1, collect, verify P1 notified, P2 not notified.
|
||||||
|
O1 = null;
|
||||||
|
System.gc();
|
||||||
|
if (Q1.remove(ENQUEUE_TIMEOUT) == null) {
|
||||||
|
throw new RuntimeException("P1 not notified by O1 deletion");
|
||||||
|
} else if (Q2.remove(ENQUEUE_TIMEOUT) != null) {
|
||||||
|
throw new RuntimeException("P2 notified by O1 deletion.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete root -> O2, collect. P2 should be notified.
|
||||||
|
O2 = null;
|
||||||
|
System.gc();
|
||||||
|
if (Q2.remove(ENQUEUE_TIMEOUT) == null) {
|
||||||
|
throw new RuntimeException("P2 not notified by O2 deletion");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,297 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* 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 jdk.testlibrary.ProcessThread;
|
||||||
|
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 = 143;
|
||||||
|
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) {
|
||||||
|
ProcessThread[] jvms = new ProcessThread[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 (ProcessThread 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.getOutput().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 ProcessThread 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));
|
||||||
|
ProcessThread jvm = new ProcessThread("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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user