# HG changeset patch # User jprovino # Date 1451668104 0 # Node ID e18371fa3e760f247404d1412a9cae2509023b73 # Parent abe1866e51e3b103043b1bc981d2b49e9c27a12e# Parent 87b434f45259a7092be4e4c2c1a5b66594f7c188 Merge diff -r abe1866e51e3 -r e18371fa3e76 jdk/make/gensrc/Gensrc-jdk.jdi.gmk --- a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk Fri Jan 01 17:08:24 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. diff -r abe1866e51e3 -r e18371fa3e76 jdk/make/lib/CoreLibraries.gmk --- a/jdk/make/lib/CoreLibraries.gmk Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/make/lib/CoreLibraries.gmk Fri Jan 01 17:08:24 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)/, \ diff -r abe1866e51e3 -r e18371fa3e76 jdk/make/lib/LibCommon.gmk --- a/jdk/make/lib/LibCommon.gmk Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/make/lib/LibCommon.gmk Fri Jan 01 17:08:24 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) \ diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.base/share/classes/java/lang/ref/PhantomReference.java --- a/jdk/src/java.base/share/classes/java/lang/ref/PhantomReference.java Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/ref/PhantomReference.java Fri Jan 01 17:08:24 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. * - *

If the garbage collector determines at a certain point in time that the - * referent of a phantom reference is phantom reachable, then at that - * time or at some later time it will enqueue the reference. + *

Suppose the garbage collector determines at a certain point in time + * that an object is + * phantom reachable. 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. * *

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}. * - *

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 @@ * *

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, diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.base/share/classes/java/lang/ref/package-info.java --- a/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Fri Jan 01 17:08:24 2016 +0000 @@ -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. * * 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 canonicalizing mappings that do not prevent their keys * (or values) from being reclaimed, and phantom references are for - * scheduling pre-mortem cleanup actions in a more flexible way than - * is possible with the Java finalization mechanism. + * scheduling post-mortem cleanup actions. * *

Each reference-object type is implemented by a subclass of the * abstract base {@link java.lang.ref.Reference} class. @@ -64,9 +63,9 @@ * object with a reference queue 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 enqueued. 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 enqueued. 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. @@ -92,16 +91,6 @@ * structure, this check will add little overhead to the hashtable * access methods. * - *

Automatically-cleared references

- * - * 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. - * * *

Reachability

* diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.base/share/native/include/jvm.h --- a/jdk/src/java.base/share/native/include/jvm.h Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.base/share/native/include/jvm.h Fri Jan 01 17:08:24 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 */ diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.base/share/native/libjava/jni_util.c --- a/jdk/src/java.base/share/native/libjava/jni_util.c Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.base/share/native/libjava/jni_util.c Fri Jan 01 17:08:24 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; diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java --- a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Fri Jan 01 17:08:24 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 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; + } + } + + } } diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.management/share/conf/management.properties --- a/jdk/src/java.management/share/conf/management.properties Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.management/share/conf/management.properties Fri Jan 01 17:08:24 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= +# 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). +# diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.management/share/native/include/jmm.h --- a/jdk/src/java.management/share/native/include/jmm.h Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.management/share/native/include/jmm.h Fri Jan 01 17:08:24 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); diff -r abe1866e51e3 -r e18371fa3e76 jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c --- a/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c Fri Jan 01 17:08:24 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 diff -r abe1866e51e3 -r e18371fa3e76 jdk/test/com/sun/jdi/BreakpointWithFullGC.sh --- a/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh Fri Dec 18 09:37:18 2015 -0800 +++ b/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh Fri Jan 01 17:08:24 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 \ diff -r abe1866e51e3 -r e18371fa3e76 jdk/test/java/lang/ref/PhantomReferentClearing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/ref/PhantomReferentClearing.java Fri Jan 01 17:08:24 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 Q1 = new ReferenceQueue<>(); + private static final ReferenceQueue Q2 = new ReferenceQueue<>(); + + private static volatile Object O2 = new Object(); + private static volatile List O1 = new ArrayList<>(); + static { + O1.add(O2); + } + + private static final PhantomReference P1 = new PhantomReference<>(O1, Q1); + private static final PhantomReference 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"); + } + } +} diff -r abe1866e51e3 -r e18371fa3e76 jdk/test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java Fri Jan 01 17:08:24 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 + * + * 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 {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 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); + } + } + +} diff -r abe1866e51e3 -r e18371fa3e76 jdk/test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java Fri Jan 01 17:08:24 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 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; + } +}