--- a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk Wed Jan 06 02:31:59 2016 +0000
@@ -70,7 +70,7 @@
# Filter 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 \
- $(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)
# Copy the same service file into jdk.hotspot.agent so that they are kept the same.
--- a/jdk/make/lib/CoreLibraries.gmk Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/make/lib/CoreLibraries.gmk Wed Jan 06 02:31:59 2016 +0000
@@ -25,6 +25,10 @@
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
# product on its own.
@@ -119,6 +123,9 @@
-I$(SUPPORT_OUTPUTDIR)/headers/java.base \
-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)
BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
@@ -146,7 +153,7 @@
System.c_CFLAGS := $(VERSION_CFLAGS), \
jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
- MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava/mapfile-vers, \
+ MAPFILE := $(LIBJAVA_MAPFILE), \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_macosx := -L$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/, \
--- a/jdk/make/lib/LibCommon.gmk Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/make/lib/LibCommon.gmk Wed Jan 06 02:31:59 2016 +0000
@@ -27,6 +27,11 @@
include MakeBase.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
# Absolute paths to lib files on windows for use in LDFLAGS. Should figure out a more
@@ -56,7 +61,7 @@
# Find the default set of src dirs for a native library.
# Param 1 - module name
# Param 2 - library name
-FindSrcDirsForLib = \
+FindSrcDirsForLib += \
$(call uniq, $(wildcard \
$(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) \
--- a/jdk/src/java.base/share/classes/java/lang/ref/PhantomReference.java Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ref/PhantomReference.java Wed Jan 06 02:31:59 2016 +0000
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,23 +29,20 @@
/**
* Phantom reference objects, which are enqueued after the collector
* determines that their referents may otherwise be reclaimed. Phantom
- * references are most often used for scheduling pre-mortem cleanup actions in
- * a more flexible way than is possible with the Java finalization mechanism.
+ * references are most often used to schedule post-mortem cleanup actions.
*
- * <p> If the garbage collector determines at a certain point in time that the
- * referent of a phantom reference is <a
- * href="package-summary.html#reachability">phantom reachable</a>, then at that
- * time or at some later time it will enqueue the reference.
+ * <p> Suppose the garbage collector determines at a certain point in time
+ * that an object is <a href="package-summary.html#reachability">
+ * phantom reachable</a>. At that time it will atomically clear
+ * 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
* a phantom reference may not be retrieved: The {@code get} method of a
* 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
* @since 1.2
*/
@@ -69,8 +66,8 @@
*
* <p> It is possible to create a phantom reference with a {@code null}
* 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
- * will never be enqueued.
+ * method will always return {@code null} and, since it does not have a queue,
+ * it will never be enqueued.
*
* @param referent the object the new phantom reference will refer to
* @param q the queue with which the reference is to be registered,
--- a/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Wed Jan 06 02:31:59 2016 +0000
@@ -66,9 +66,9 @@
* object with a <em>reference queue</em> at the time the reference
* object is created. Some time after the garbage collector
* determines that the reachability of the referent has changed to the
- * value corresponding to the type of the reference, it will add the
- * reference to the associated queue. At this point, the reference is
- * considered to be <em>enqueued</em>. The program may remove
+ * value corresponding to the type of the reference, it will clear the
+ * reference and add it to the associated queue. At this point, the
+ * reference is considered to be <em>enqueued</em>. The program may remove
* references from a queue either by polling or by blocking until a
* reference becomes available. Reference queues are implemented by
* the {@link java.lang.ref.ReferenceQueue} class.
@@ -94,16 +94,6 @@
* structure, this check will add little overhead to the hashtable
* 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>
* <h3>Reachability</h3>
*
--- a/jdk/src/java.base/share/native/include/jvm.h Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.base/share/native/include/jvm.h Wed Jan 06 02:31:59 2016 +0000
@@ -208,6 +208,9 @@
JNIEXPORT void JNICALL
JVM_SetMethodInfo(JNIEnv* env, jobject frame);
+JNIEXPORT jobjectArray JNICALL
+JVM_GetVmArguments(JNIEnv *env);
+
/*
* java.lang.Thread
*/
--- a/jdk/src/java.base/share/native/libjava/jni_util.c Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.base/share/native/libjava/jni_util.c Wed Jan 06 02:31:59 2016 +0000
@@ -660,7 +660,8 @@
*/
if ((strcmp(encname, "8859_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;
else if (strcmp(encname, "ISO646-US") == 0)
fastEncoding = FAST_646_US;
--- a/jdk/src/java.management/share/classes/javax/management/loading/MLetParser.java Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/loading/MLetParser.java Wed Jan 06 02:31:59 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
@@ -142,7 +143,7 @@
skipSpace(in);
val = buf.toString();
}
- atts.put(att.toLowerCase(), val);
+ atts.put(att.toLowerCase(Locale.ENGLISH), val);
skipSpace(in);
}
return atts;
--- a/jdk/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java Wed Jan 06 02:31:59 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -45,6 +45,7 @@
import java.security.AccessController;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
@@ -283,7 +284,7 @@
throw new RuntimeOperationsException(iae, msg);
}
- final String lowerInStr = inStr.toLowerCase();
+ final String lowerInStr = inStr.toLowerCase(Locale.ENGLISH);
if (!lowerInStr.startsWith("<descriptor>")
|| !lowerInStr.endsWith("</descriptor>")) {
throw new XMLParseException("No <descriptor>, </descriptor> pair");
--- a/jdk/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java Wed Jan 06 02:31:59 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -38,6 +38,7 @@
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.util.BitSet;
+import java.util.Locale;
import java.util.StringTokenizer;
/**
@@ -168,7 +169,7 @@
final int protoStart = requiredPrefixLength;
final int protoEnd = indexOf(serviceURL, ':', protoStart);
this.protocol =
- serviceURL.substring(protoStart, protoEnd).toLowerCase();
+ serviceURL.substring(protoStart, protoEnd).toLowerCase(Locale.ENGLISH);
if (!serviceURL.regionMatches(protoEnd, "://", 0, 3)) {
throw new MalformedURLException("Missing \"://\" after " +
@@ -328,7 +329,7 @@
throw new MalformedURLException("More than one [[...]]");
}
- this.protocol = protocol.toLowerCase();
+ this.protocol = protocol.toLowerCase(Locale.ENGLISH);
this.host = host;
this.port = port;
--- a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Wed Jan 06 02:31:59 2016 +0000
@@ -30,9 +30,12 @@
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.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.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 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 @@
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 @@
sslConfigFileName, enabledCipherSuitesList,
enabledProtocolsList, sslNeedClientAuth,
useAuthentication, loginConfigName,
- passwordFileName, accessFileName);
+ passwordFileName, accessFileName, bindAddress);
cs = data.jmxConnectorServer;
url = data.jmxRemoteURL;
log.config("startRemoteConnectorServer",
@@ -628,12 +640,13 @@
String sslConfigFileName,
String[] enabledCipherSuites,
String[] enabledProtocols,
- boolean sslNeedClientAuth) {
+ boolean sslNeedClientAuth,
+ String bindAddress) {
if (sslConfigFileName == null) {
- return new SslRMIServerSocketFactory(
+ return new HostAwareSslSocketFactory(
enabledCipherSuites,
enabledProtocols,
- sslNeedClientAuth);
+ sslNeedClientAuth, bindAddress);
} else {
checkRestrictedFile(sslConfigFileName);
try {
@@ -687,11 +700,11 @@
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
- return new SslRMIServerSocketFactory(
+ return new HostAwareSslSocketFactory(
ctx,
enabledCipherSuites,
enabledProtocols,
- sslNeedClientAuth);
+ sslNeedClientAuth, bindAddress);
} catch (Exception e) {
throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
}
@@ -711,7 +724,8 @@
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 @@
* 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 @@
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 @@
csf = new SslRMIClientSocketFactory();
ssf = createSslRMIServerSocketFactory(
sslConfigFileName, enabledCipherSuites,
- enabledProtocols, sslNeedClientAuth);
+ enabledProtocols, sslNeedClientAuth, bindAddress);
}
if (useSsl) {
@@ -761,6 +777,12 @@
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 @@
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 @@
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;
+ }
+ }
+
+ }
}
--- a/jdk/src/java.management/share/conf/management.properties Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.management/share/conf/management.properties Wed Jan 06 02:31:59 2016 +0000
@@ -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).
+#
--- a/jdk/src/java.management/share/native/include/jmm.h Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.management/share/native/include/jmm.h Wed Jan 06 02:31:59 2016 +0000
@@ -227,16 +227,10 @@
jint (JNICALL *GetOptionalSupport) (JNIEnv *env,
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,
jlongArray ids,
jint maxDepth,
jobjectArray infoArray);
- jobjectArray (JNICALL *GetInputArgumentArray) (JNIEnv *env);
jobjectArray (JNICALL *GetMemoryPools) (JNIEnv* env, jobject mgr);
--- a/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c Wed Jan 06 02:31:59 2016 +0000
@@ -112,7 +112,7 @@
Java_sun_management_VMManagementImpl_getVmArguments0
(JNIEnv *env, jobject dummy)
{
- return jmm_interface->GetInputArgumentArray(env);
+ return JVM_GetVmArguments(env);
}
JNIEXPORT jlong JNICALL
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/EventRequestManagerImpl.java Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/EventRequestManagerImpl.java Wed Jan 06 02:31:59 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
class EventRequestManagerImpl extends MirrorImpl
implements EventRequestManager
{
- List<? extends EventRequest>[] requestLists;
+ private final List<? extends EventRequest>[] requestLists;
private static int methodExitEventCmd = 0;
static int JDWPtoJDISuspendPolicy(byte jdwpPolicy) {
@@ -83,7 +83,7 @@
return System.identityHashCode(this);
}
- abstract class EventRequestImpl extends MirrorImpl implements EventRequest {
+ private abstract class EventRequestImpl extends MirrorImpl implements EventRequest {
int id;
/*
@@ -734,7 +734,7 @@
}
requestLists = new List[highest+1];
for (int i=0; i <= highest; i++) {
- requestLists[i] = new ArrayList<>();
+ requestLists[i] = Collections.synchronizedList(new ArrayList<>());
}
}
@@ -933,22 +933,27 @@
}
List<? extends EventRequest> unmodifiableRequestList(int eventCmd) {
- return Collections.unmodifiableList(requestList(eventCmd));
+ // No need of explicit synchronization for requestList here.
+ // It is taken care internally by SynchronizedList class.
+ return Collections.unmodifiableList(new ArrayList<>(requestList(eventCmd)));
}
EventRequest request(int eventCmd, int requestId) {
List<? extends EventRequest> rl = requestList(eventCmd);
- for (int i = rl.size() - 1; i >= 0; i--) {
- EventRequestImpl er = (EventRequestImpl)rl.get(i);
- if (er.id == requestId) {
- return er;
+ synchronized(rl) { // Refer Collections.synchronizedList javadoc.
+ Iterator<? extends EventRequest> itr = rl.iterator();
+ while (itr.hasNext()){
+ EventRequestImpl er = (EventRequestImpl)itr.next();
+ if (er.id == requestId)
+ return er;
}
}
return null;
}
- List<? extends EventRequest> requestList(int eventCmd) {
+ private List<? extends EventRequest> requestList(int eventCmd) {
return requestLists[eventCmd];
}
}
+
--- a/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh Tue Jan 05 13:08:05 2016 -0800
+++ b/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh Wed Jan 06 02:31:59 2016 +0000
@@ -121,7 +121,8 @@
jdbFailIfNotPresent 'System\..*end of test'
# 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
debuggeeFailIfPresent \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ref/PhantomReferentClearing.java Wed Jan 06 02:31:59 2016 +0000
@@ -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");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/loading/MletParserLocaleTest.java Wed Jan 06 02:31:59 2016 +0000
@@ -0,0 +1,109 @@
+/*
+ * 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 7065236
+ * @summary Checking MletParser for Locale insensitive strings
+ * @author Harsha Wardhana B
+ * @modules java.management
+ * @run clean MletParserLocaleTest
+ * @run build MletParserLocaleTest
+ * @run main/othervm/timeout=5 MletParserLocaleTest mlet4.html
+ */
+
+import java.io.File;
+import java.util.Locale;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.loading.MLet;
+
+public class MletParserLocaleTest {
+
+ public static void main(String[] args) throws Exception {
+
+ boolean error = false;
+
+ // Instantiate the MBean server
+ //
+ System.out.println("Create the MBean server");
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+
+ // Get Default Locale
+ Locale loc = Locale.getDefault();
+
+ // Instantiate an MLet
+ //
+ System.out.println("Create the MLet");
+ MLet mlet = new MLet();
+
+ // Register the MLet MBean with the MBeanServer
+ //
+ System.out.println("Register the MLet MBean");
+ ObjectName mletObjectName = new ObjectName("Test:type=MLet");
+ mbs.registerMBean(mlet, mletObjectName);
+
+ // Call getMBeansFromURL
+ //
+ System.out.println("Call mlet.getMBeansFromURL(<url>)");
+ String testSrc = System.getProperty("test.src");
+ System.out.println("test.src = " + testSrc);
+ String urlCodebase;
+ if (testSrc.startsWith("/")) {
+ urlCodebase =
+ "file:" + testSrc.replace(File.separatorChar, '/') + "/";
+ } else {
+ urlCodebase =
+ "file:/" + testSrc.replace(File.separatorChar, '/') + "/";
+ }
+ String mletFile = urlCodebase + args[0];
+ System.out.println("MLet File = " + mletFile);
+ try {
+ // Change default Locale to Turkish
+ Locale.setDefault(new Locale("tr", "TR"));
+ mlet.getMBeansFromURL(mletFile);
+ System.out.println("Test Passes");
+ } catch (Exception e) {
+ error = true;
+ e.printStackTrace(System.out);
+ }finally {
+ Locale.setDefault(loc);
+ }
+
+ // Unregister the MLet MBean
+ //
+ System.out.println("Unregister the MLet MBean");
+ mbs.unregisterMBean(mletObjectName);
+
+ // Release MBean server
+ //
+ System.out.println("Release the MBean server");
+ MBeanServerFactory.releaseMBeanServer(mbs);
+
+ // End Test
+ //
+ System.out.println("Bye! Bye!");
+ if (error) System.exit(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/loading/mlet4.html Wed Jan 06 02:31:59 2016 +0000
@@ -0,0 +1,2 @@
+<MLET CODE=HelloWorld ARCHIVE="helloworld.jar">
+</MLET>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/modelmbean/DescriptorSupportXMLLocaleTest.java Wed Jan 06 02:31:59 2016 +0000
@@ -0,0 +1,64 @@
+/*
+ * 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 7065236
+ * @summary Test for locale insensitive strings in DescriptorSupport class
+ * @author Harsha Wardhana B
+ * @modules java.management
+ * @run clean DescriptorSupportXMLLocaleTest
+ * @run build DescriptorSupportXMLLocaleTest
+ * @run main DescriptorSupportXMLLocaleTest
+ */
+import java.util.Locale;
+import javax.management.modelmbean.DescriptorSupport;
+
+public class DescriptorSupportXMLLocaleTest {
+
+ public static void main(String[] args) throws Exception {
+ boolean failed = false;
+ String xmlDesc = "<DESCRIPTOR>"
+ + "<FIELD name=\"field1\" value=\"dummy\">"
+ + "</FIELD>"
+ + "</DESCRIPTOR>";
+ Locale loc = Locale.getDefault();
+ try {
+ Locale.setDefault(new Locale("tr", "TR"));
+ new DescriptorSupport(xmlDesc);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ failed = true;
+ }finally{
+ Locale.setDefault(loc);
+ }
+
+ if (!failed) {
+ System.out.println("OK: all tests passed");
+ } else {
+ System.out.println("TEST FAILED");
+ throw new IllegalArgumentException("Test Failed");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/remote/mandatory/connection/JMXServiceURLLocaleTest.java Wed Jan 06 02:31:59 2016 +0000
@@ -0,0 +1,68 @@
+/*
+ * 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 7065236
+ * @summary Test for locale insensitive strings in JMXServiceURL class
+ * @author Harsha Wardhana B
+ * @modules java.management
+ * @run clean JMXServiceURLLocaleTest
+ * @run build JMXServiceURLLocaleTest
+ * @run main JMXServiceURLLocaleTest
+*/
+
+import java.util.Locale;
+import javax.management.remote.JMXServiceURL;
+
+public class JMXServiceURLLocaleTest {
+ public static void main(String[] args) throws Exception {
+
+ boolean error = false;
+ Locale loc = Locale.getDefault();
+
+ try {
+ echo("Setting Turkish locale");
+ // Set locale other than Locale.ENGLISH
+ Locale.setDefault(new Locale("tr", "TR"));
+ new JMXServiceURL("service:jmx:RMI://");
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ error = true;
+ } finally {
+ Locale.setDefault(loc);
+ echo("\n>>> Bye! Bye!");
+ }
+
+ if (error) {
+ echo("\nTest failed! ");
+ throw new IllegalArgumentException("Test failed");
+ } else {
+ echo("\nTest passed!\n");
+ }
+ }
+
+ private static void echo(String msg) {
+ System.out.println(msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java Wed Jan 06 02:31:59 2016 +0000
@@ -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);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java Wed Jan 06 02:31:59 2016 +0000
@@ -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'");
+ return;
+ }
+ 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;
+ }
+}