OpenJDK / aarch32-port / jdk9u / jdk
changeset 14463:1a74d902715a
Merge
author | amurillo |
---|---|
date | Thu, 28 Apr 2016 23:08:17 -0700 |
parents | ce87b09f35dd f39e271718d9 |
children | 48363aba4811 |
files | make/launcher/Launcher-jdk.jvmstat.rmi.gmk src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java src/java.base/share/classes/jdk/net/NetworkPermission.java src/java.base/share/classes/jdk/net/SocketFlow.java src/java.base/share/classes/jdk/net/Sockets.java src/java.base/share/classes/jdk/net/package-info.java src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java src/java.base/unix/native/libnet/ExtendedOptionsImpl.c src/java.base/windows/native/libnet/ExtendedOptionsImpl.c src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java src/jdk.jvmstat.rmi/share/classes/module-info.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/package.html src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/Jstatd.java src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteHostImpl.java src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteVmImpl.java src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java |
diffstat | 181 files changed, 7262 insertions(+), 5135 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu Apr 28 00:38:21 2016 -0700 +++ b/.hgtags Thu Apr 28 23:08:17 2016 -0700 @@ -358,3 +358,4 @@ 68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113 bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114 35225b837d66582037eeadeb471c13235dfd793d jdk-9+115 +baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/launcher/Launcher-jdk.jstatd.gmk Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,30 @@ +# +# Copyright (c) 2011, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +include LauncherCommon.gmk + +$(eval $(call SetupBuildLauncher, jstatd, \ + MAIN_CLASS := sun.tools.jstatd.Jstatd, \ +))
--- a/make/launcher/Launcher-jdk.jvmstat.rmi.gmk Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -# -# Copyright (c) 2011, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -include LauncherCommon.gmk - -$(eval $(call SetupBuildLauncher, jstatd, \ - MAIN_CLASS := sun.tools.jstatd.Jstatd, \ -))
--- a/make/lib/CoreLibraries.gmk Thu Apr 28 00:38:21 2016 -0700 +++ b/make/lib/CoreLibraries.gmk Thu Apr 28 23:08:17 2016 -0700 @@ -267,7 +267,7 @@ LDFLAGS_windows := -export:JIMAGE_Open -export:JIMAGE_Close \ -export:JIMAGE_PackageToModule \ -export:JIMAGE_FindResource -export:JIMAGE_GetResource \ - -export:JIMAGE_ResourceIterator, \ + -export:JIMAGE_ResourceIterator -export:JIMAGE_ResourcePath, \ LIBS_unix := -ljvm -ldl $(LIBCXX), \ LIBS_solaris := -lc, \ LIBS_macosx := -lc++, \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/lib/Lib-jdk.net.gmk Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,51 @@ +# +# Copyright (c) 2016, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +include LibCommon.gmk + +################################################################################ + +ifeq ($(OPENJDK_TARGET_OS), solaris) + + $(eval $(call SetupNativeCompilation, BUILD_LIBEXTNET, \ + LIBRARY := extnet, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(JDK_TOPDIR)/src/jdk.net/solaris/native/libextnet, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \ + MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libextnet/mapfile-vers, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LIBS := -lsocket -lc -ljava, \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libextnet, \ + )) + + $(BUILD_LIBEXTNET): $(call FindLib, java.base, java) + + TARGETS += $(BUILD_LIBEXTNET) +endif + + +################################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/mapfiles/libextnet/mapfile-vers Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,34 @@ +# +# Copyright (c) 2016, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +SUNWprivate_1.1 { + global: + Java_jdk_net_SolarisSocketOptions_init; + Java_jdk_net_SolarisSocketOptions_setFlowOption; + Java_jdk_net_SolarisSocketOptions_getFlowOption; + Java_jdk_net_SolarisSocketOptions_flowSupported; + local: + *; +};
--- a/make/mapfiles/libjimage/mapfile-vers Thu Apr 28 00:38:21 2016 -0700 +++ b/make/mapfiles/libjimage/mapfile-vers Thu Apr 28 23:08:17 2016 -0700 @@ -34,6 +34,7 @@ JIMAGE_FindResource; JIMAGE_GetResource; JIMAGE_ResourceIterator; + JIMAGE_ResourcePath; local: *; };
--- a/make/mapfiles/libnet/mapfile-vers Thu Apr 28 00:38:21 2016 -0700 +++ b/make/mapfiles/libnet/mapfile-vers Thu Apr 28 23:08:17 2016 -0700 @@ -98,10 +98,6 @@ Java_sun_net_sdp_SdpSupport_create0; Java_sun_net_spi_DefaultProxySelector_init; Java_sun_net_spi_DefaultProxySelector_getSystemProxy; - Java_sun_net_ExtendedOptionsImpl_init; - Java_sun_net_ExtendedOptionsImpl_setFlowOption; - Java_sun_net_ExtendedOptionsImpl_getFlowOption; - Java_sun_net_ExtendedOptionsImpl_flowSupported; NET_AllocSockaddr; NET_SockaddrToInetAddress; NET_SockaddrEqualsInetAddress;
--- a/make/netbeans/client_sanity/nbproject/genfiles.properties Thu Apr 28 00:38:21 2016 -0700 +++ b/make/netbeans/client_sanity/nbproject/genfiles.properties Thu Apr 28 23:08:17 2016 -0700 @@ -3,6 +3,6 @@ build.xml.stylesheet.CRC32=8064a381@1.75.2.48 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=55414227 +nbproject/build-impl.xml.data.CRC32=16caf60f nbproject/build-impl.xml.script.CRC32=c12f9d04 nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48
--- a/make/netbeans/client_sanity/nbproject/project.properties Thu Apr 28 00:38:21 2016 -0700 +++ b/make/netbeans/client_sanity/nbproject/project.properties Thu Apr 28 23:08:17 2016 -0700 @@ -76,4 +76,4 @@ src.src.dir=..\\..\\..\\test\\sanity\\client\\SwingSet\\src src.src2.dir=..\\..\\..\\test\\sanity\\client\\lib\\SwingSet3\\src src.src3.dir=..\\..\\..\\test\\sanity\\client\\lib\\jemmy\\src -src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Jemmy2Ext\\src +src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Extensions\\src
--- a/make/netbeans/client_sanity/nbproject/project.xml Thu Apr 28 00:38:21 2016 -0700 +++ b/make/netbeans/client_sanity/nbproject/project.xml Thu Apr 28 23:08:17 2016 -0700 @@ -6,7 +6,7 @@ <name>SanityTests</name> <source-roots> <root id="src.src3.dir" name="lib\jemmy\src"/> - <root id="src.src4.dir" name="lib\Jemmy2Ext\src"/> + <root id="src.src4.dir" name="lib\Extensions\src"/> <root id="src.src2.dir" name="lib\SwingSet3\src"/> <root id="src.src.dir" name="SwingSet\src"/> </source-roots>
--- a/make/src/classes/build/tools/module/GenModuleInfoSource.java Thu Apr 28 00:38:21 2016 -0700 +++ b/make/src/classes/build/tools/module/GenModuleInfoSource.java Thu Apr 28 23:08:17 2016 -0700 @@ -52,7 +52,7 @@ "Usage: GenModuleInfoSource [option] -o <output file> <module-info-java>\n" + "Options are:\n" + " -exports <package-name>\n" + - " -exports <package-name>/<module-name>\n" + + " -exports <package-name>[/<module-name>]\n" + " -uses <service>\n" + " -provides <service>/<provider-impl-classname>\n";
--- a/src/java.base/aix/native/libnet/aix_close.c Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/aix/native/libnet/aix_close.c Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,6 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, SAP SE 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 @@ -50,6 +51,8 @@ ... */ +#include <assert.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> @@ -86,10 +89,35 @@ static int sigWakeup = (SIGRTMAX - 1); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable = NULL; -static int fdCount = 0; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -108,42 +136,42 @@ struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* Check already initialized */ - if (fdCount > 0 && fdTable != NULL) { - return; - } - - /* - * Allocate table based on the maximum number of - * file descriptors. - */ + /* Determine the maximum number of possible file descriptors. */ if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { fprintf(stderr, "library initialization failed - " "unable to get max # of allocated fds\n"); abort(); } - fdCount = nbr_files.rlim_max; - /* - * We have a conceptual problem here, when the number of files is - * unlimited. As a kind of workaround, we ensure the table is big - * enough for handle even a large number of files. Since SAP itself - * recommends a limit of 32000 files, we just use 64000 as 'infinity'. - */ - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = 64000; + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - { - int i; - for (i=0; i < fdCount; i++) { - pthread_mutex_init(&fdTable[i].lock, NULL); + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); } } @@ -161,17 +189,60 @@ } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd.
--- a/src/java.base/linux/native/libnet/linux_close.c Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/linux/native/libnet/linux_close.c Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -23,6 +23,8 @@ * questions. */ +#include <assert.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> @@ -59,10 +61,35 @@ static int sigWakeup = (__SIGRTMAX - 2); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -78,18 +105,43 @@ struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - fdCount = nbr_files.rlim_max; - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); + } + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; + } + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } + } + + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -106,15 +158,57 @@ } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } /*
--- a/src/java.base/macosx/native/libnet/bsd_close.c Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/macosx/native/libnet/bsd_close.c Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -23,6 +23,8 @@ * questions. */ +#include <assert.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <sys/param.h> @@ -61,18 +63,35 @@ static int sigWakeup = SIGIO; /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; -/* - * This limit applies if getlimit() returns unlimited. - * Unfortunately, this means if someone wants a higher limit - * then they have to set an explicit limit, higher than this, - * which is probably counter-intuitive. +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. */ -#define MAX_FD_COUNT 4096 +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -88,26 +107,43 @@ struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; - int i; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = MAX_FD_COUNT; + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); + } + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; } else { - fdCount = nbr_files.rlim_max; + /* We just do not know. */ + fdLimit = INT_MAX; } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - for (i=0; i<fdCount; i++) { - pthread_mutex_init(&fdTable[i].lock, NULL); + + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -124,17 +160,60 @@ } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd.
--- a/src/java.base/share/classes/java/lang/Runtime.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/lang/Runtime.java Thu Apr 28 23:08:17 2016 -0700 @@ -718,41 +718,27 @@ } /** - * Enables/Disables tracing of instructions. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each instruction in the virtual machine as it - * is executed. The format of this information, and the file or other - * output stream to which it is emitted, depends on the host environment. - * The virtual machine may ignore this request if it does not support - * this feature. The destination of the trace output is system - * dependent. - * <p> - * If the {@code boolean} argument is {@code false}, this - * method causes the virtual machine to stop performing the - * detailed instruction trace it is performing. + * Not implemented, does nothing. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @deprecated + * This method was intended to control instruction tracing. + * It has been superseded by JVM-specific tracing mechanisms. + * + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceInstructions(boolean on) { } /** - * Enables/Disables tracing of method calls. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each method in the virtual machine as it is - * called. The format of this information, and the file or other output - * stream to which it is emitted, depends on the host environment. The - * virtual machine may ignore this request if it does not support - * this feature. - * <p> - * Calling this method with argument false suggests that the - * virtual machine cease emitting per-call debugging information. + * Not implemented, does nothing. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @deprecated + * This method was intended to control method call tracing. + * It has been superseded by JVM-specific tracing mechanisms. + * + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceMethodCalls(boolean on) { } /**
--- a/src/java.base/share/classes/java/lang/System.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/lang/System.java Thu Apr 28 23:08:17 2016 -0700 @@ -1155,8 +1155,9 @@ * @param level the log message level. * @param msg the string message (or a key in the message catalog, if * this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * * @throws NullPointerException if {@code level} is {@code null}. */ @@ -1222,8 +1223,9 @@ * @param level the log message level. * @param msg the string message (or a key in the message catalog, if * this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * @param thrown a {@code Throwable} associated with the log message; * can be {@code null}. * @@ -1270,8 +1272,9 @@ * @param format the string message format in {@link * java.text.MessageFormat} format, (or a key in the message * catalog, if this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * @param params an optional list of parameters to the message (may be * none). * @@ -1453,30 +1456,30 @@ /** * Returns an instance of {@link Logger Logger} - * for the given {@code caller}. + * for the given {@code module}. * * @param name the name of the logger. - * @param caller the class for which the logger is being requested. + * @param module the module for which the logger is being requested. * - * @return a {@link Logger logger} suitable for the given caller's - * use. + * @return a {@link Logger logger} suitable for use within the given + * module. * @throws NullPointerException if {@code name} is {@code null} or - * {@code caller} is {@code null}. + * {@code module} is {@code null}. * @throws SecurityException if a security manager is present and its * {@code checkPermission} method doesn't allow the * {@code RuntimePermission("loggerFinder")}. */ - public abstract Logger getLogger(String name, /* Module */ Class<?> caller); + public abstract Logger getLogger(String name, Module module); /** * Returns a localizable instance of {@link Logger Logger} - * for the given {@code caller}. + * for the given {@code module}. * The returned logger will use the provided resource bundle for * message localization. * * @implSpec By default, this method calls {@link - * #getLogger(java.lang.String, java.lang.Class) - * this.getLogger(name, caller)} to obtain a logger, then wraps that + * #getLogger(java.lang.String, java.lang.reflect.Module) + * this.getLogger(name, module)} to obtain a logger, then wraps that * logger in a {@link Logger} instance where all methods that do not * take a {@link ResourceBundle} as parameter are redirected to one * which does - passing the given {@code bundle} for @@ -1499,19 +1502,19 @@ * * @param name the name of the logger. * @param bundle a resource bundle; can be {@code null}. - * @param caller the class for which the logger is being requested. + * @param module the module for which the logger is being requested. * @return an instance of {@link Logger Logger} which will use the * provided resource bundle for message localization. * * @throws NullPointerException if {@code name} is {@code null} or - * {@code caller} is {@code null}. + * {@code module} is {@code null}. * @throws SecurityException if a security manager is present and its * {@code checkPermission} method doesn't allow the * {@code RuntimePermission("loggerFinder")}. */ public Logger getLocalizedLogger(String name, ResourceBundle bundle, - /* Module */ Class<?> caller) { - return new LocalizedLoggerWrapper<>(getLogger(name, caller), bundle); + Module module) { + return new LocalizedLoggerWrapper<>(getLogger(name, module), bundle); } /** @@ -1558,12 +1561,13 @@ * * @implSpec * Instances returned by this method route messages to loggers - * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class) - * LoggerFinder.getLogger(name, caller)}. + * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, + * java.lang.reflect.Module) LoggerFinder.getLogger(name, module)}, where + * {@code module} is the caller's module. * * @apiNote * This method may defer calling the {@link - * LoggerFinder#getLogger(java.lang.String, java.lang.Class) + * LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module) * LoggerFinder.getLogger} method to create an actual logger supplied by * the logging backend, for instance, to allow loggers to be obtained during * the system initialization time. @@ -1579,7 +1583,7 @@ public static Logger getLogger(String name) { Objects.requireNonNull(name); final Class<?> caller = Reflection.getCallerClass(); - return LazyLoggers.getLogger(name, caller); + return LazyLoggers.getLogger(name, caller.getModule()); } /** @@ -1591,8 +1595,9 @@ * @implSpec * The returned logger will perform message localization as specified * by {@link LoggerFinder#getLocalizedLogger(java.lang.String, - * java.util.ResourceBundle, java.lang.Class) - * LoggerFinder.getLocalizedLogger(name, bundle, caller}. + * java.util.ResourceBundle, java.lang.reflect.Module) + * LoggerFinder.getLocalizedLogger(name, bundle, module}, where + * {@code module} is the caller's module. * * @apiNote * This method is intended to be used after the system is fully initialized. @@ -1624,12 +1629,14 @@ // Bootstrap sensitive classes in the JDK do not use resource bundles // when logging. This could be revisited later, if it needs to. if (sm != null) { - return AccessController.doPrivileged((PrivilegedAction<Logger>) - () -> LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller), - null, - LoggerFinder.LOGGERFINDER_PERMISSION); + final PrivilegedAction<Logger> pa = + () -> LoggerFinder.accessProvider() + .getLocalizedLogger(name, rb, caller.getModule()); + return AccessController.doPrivileged(pa, null, + LoggerFinder.LOGGERFINDER_PERMISSION); } - return LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller); + return LoggerFinder.accessProvider() + .getLocalizedLogger(name, rb, caller.getModule()); } /**
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -25,6 +25,7 @@ package java.lang.invoke; +import java.lang.reflect.Array; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; @@ -1892,7 +1893,8 @@ MH_tryFinallyExec = 12, MH_tryFinallyVoidExec = 13, MH_decrementCounter = 14, - MH_LIMIT = 15; + MH_Array_newInstance = 15, + MH_LIMIT = 16; static MethodHandle getConstantHandle(int idx) { MethodHandle handle = HANDLES[idx]; @@ -1965,6 +1967,9 @@ case MH_decrementCounter: return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "decrementCounter", MethodType.methodType(int.class, int.class)); + case MH_Array_newInstance: + return IMPL_LOOKUP.findStatic(Array.class, "newInstance", + MethodType.methodType(Object.class, Class.class, int.class)); } } catch (ReflectiveOperationException ex) { throw newInternalError(ex);
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Apr 28 23:08:17 2016 -0700 @@ -25,34 +25,38 @@ package java.lang.invoke; -import java.lang.reflect.*; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; +import sun.invoke.util.ValueConversions; +import sun.invoke.util.VerifyAccess; +import sun.invoke.util.Wrapper; +import sun.reflect.misc.ReflectUtil; +import sun.security.util.SecurityConstants; + +import java.lang.invoke.LambdaForm.BasicType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ReflectPermission; +import java.nio.ByteOrder; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; import java.util.Iterator; import java.util.List; -import java.util.Arrays; import java.util.Objects; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import sun.invoke.util.ValueConversions; -import sun.invoke.util.VerifyAccess; -import sun.invoke.util.Wrapper; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; -import sun.reflect.misc.ReflectUtil; -import sun.security.util.SecurityConstants; -import java.lang.invoke.LambdaForm.BasicType; - -import static java.lang.invoke.MethodHandleImpl.Intrinsic; -import static java.lang.invoke.MethodHandleNatives.Constants.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Opcodes; - +import static java.lang.invoke.MethodHandleImpl.Intrinsic; +import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; import static java.lang.invoke.MethodType.methodType; @@ -741,10 +745,13 @@ if (name.startsWith("java.lang.invoke.")) throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); - // For caller-sensitive MethodHandles.lookup() - // disallow lookup more restricted packages + // For caller-sensitive MethodHandles.lookup() disallow lookup from + // restricted packages. This a fragile and blunt approach. + // TODO replace with a more formal and less fragile mechanism + // that does not bluntly restrict classes under packages within + // java.base from looking up MethodHandles or VarHandles. if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { - if (name.startsWith("java.") || + if ((name.startsWith("java.") && !name.startsWith("java.util.concurrent.")) || (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); } @@ -1003,6 +1010,9 @@ * @throws NullPointerException if any argument is null */ public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { + if (refc.isArray()) { + throw new NoSuchMethodException("no constructor for array class: " + refc.getName()); + } String name = "<init>"; MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); return getDirectConstructor(refc, ctor); @@ -2214,6 +2224,27 @@ } /** + * Produces a method handle constructing arrays of a desired type. + * The return type of the method handle will be the array type. + * The type of its sole argument will be {@code int}, which specifies the size of the array. + * @param arrayClass an array type + * @return a method handle which can create arrays of the given type + * @throws NullPointerException if the argument is {@code null} + * @throws IllegalArgumentException if {@code arrayClass} is not an array type + * @see java.lang.reflect.Array#newInstance(Class, int) + * @since 9 + */ + public static + MethodHandle arrayConstructor(Class<?> arrayClass) throws IllegalArgumentException { + if (!arrayClass.isArray()) { + throw newIllegalArgumentException("not an array class: " + arrayClass.getName()); + } + MethodHandle ani = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_Array_newInstance). + bindTo(arrayClass.getComponentType()); + return ani.asType(ani.type().changeReturnType(arrayClass)); + } + + /** * Produces a method handle giving read access to elements of an array. * The type of the method handle will have a return type of the array's * element type. Its first argument will be the array type, @@ -2337,13 +2368,12 @@ * * @param viewArrayClass the view array class, with a component type of * type {@code T} - * @param bigEndian true if the endianness of the view array elements, as - * stored in the underlying {@code byte} array, is big endian, otherwise - * little endian + * @param byteOrder the endianness of the view array elements, as + * stored in the underlying {@code byte} array * @return a VarHandle giving access to elements of a {@code byte[]} array * viewed as if elements corresponding to the components type of the view * array class - * @throws NullPointerException if viewArrayClass is null + * @throws NullPointerException if viewArrayClass or byteOrder is null * @throws IllegalArgumentException if viewArrayClass is not an array type * @throws UnsupportedOperationException if the component type of * viewArrayClass is not supported as a variable type @@ -2351,8 +2381,10 @@ */ public static VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass, - boolean bigEndian) throws IllegalArgumentException { - return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian); + ByteOrder byteOrder) throws IllegalArgumentException { + Objects.requireNonNull(byteOrder); + return VarHandles.byteArrayViewHandle(viewArrayClass, + byteOrder == ByteOrder.BIG_ENDIAN); } /** @@ -2422,14 +2454,13 @@ * * @param viewArrayClass the view array class, with a component type of * type {@code T} - * @param bigEndian true if the endianness of the view array elements, as - * stored in the underlying {@code ByteBuffer}, is big endian, otherwise - * little endian (Note this overrides the endianness of a - * {@code ByteBuffer}) + * @param byteOrder the endianness of the view array elements, as + * stored in the underlying {@code ByteBuffer} (Note this overrides the + * endianness of a {@code ByteBuffer}) * @return a VarHandle giving access to elements of a {@code ByteBuffer} * viewed as if elements corresponding to the components type of the view * array class - * @throws NullPointerException if viewArrayClass is null + * @throws NullPointerException if viewArrayClass or byteOrder is null * @throws IllegalArgumentException if viewArrayClass is not an array type * @throws UnsupportedOperationException if the component type of * viewArrayClass is not supported as a variable type @@ -2437,8 +2468,10 @@ */ public static VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass, - boolean bigEndian) throws IllegalArgumentException { - return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian); + ByteOrder byteOrder) throws IllegalArgumentException { + Objects.requireNonNull(byteOrder); + return VarHandles.makeByteBufferViewHandle(viewArrayClass, + byteOrder == ByteOrder.BIG_ENDIAN); } @@ -4476,12 +4509,24 @@ * @since 9 */ public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { - MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ? - zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class); + Class<?> resultType; + MethodHandle actualInit; + if (init == null) { + resultType = body == null ? void.class : body.type().returnType(); + actualInit = empty(methodType(resultType)); + } else { + resultType = init.type().returnType(); + actualInit = init; + } + MethodHandle defaultResultHandle = resultType == void.class ? zero(void.class) : identity(resultType); + MethodHandle actualBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; + MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class); + MethodHandle actualEnd = end == null ? constant(int.class, 0) : end; MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; - MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; - MethodHandle[] bodyClause = {init, - filterArgument(dropArguments(body, 1, int.class), 0, + MethodHandle[] loopLimit = {actualEnd, null, + MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; + MethodHandle[] bodyClause = {actualInit, + filterArgument(dropArguments(actualBody, 1, int.class), 0, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))}; return loop(indexVar, loopLimit, bodyClause); } @@ -4572,17 +4617,24 @@ */ public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) { checkIteratedLoop(iterator, body); - final boolean voidInit = init == null || init.type().returnType() == void.class; + Class<?> resultType = init == null ? + body == null ? void.class : body.type().returnType() : + init.type().returnType(); + boolean voidResult = resultType == void.class; - MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); - MethodHandle initIterator = iterator == null ? - initit.asType(initit.type().changeParameterType(0, body.type().parameterType(voidInit ? 1 : 2))) : - iterator; - Class<?> itype = initIterator.type().returnType(); + MethodHandle initIterator; + if (iterator == null) { + MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); + initIterator = initit.asType(initit.type().changeParameterType(0, + body.type().parameterType(voidResult ? 1 : 2))); + } else { + initIterator = iterator.asType(iterator.type().changeReturnType(Iterator.class)); + } + Class<?> ttype = body.type().parameterType(0); MethodHandle returnVar = - dropArguments(voidInit ? zero(void.class) : identity(init.type().returnType()), 0, itype); + dropArguments(voidResult ? zero(void.class) : identity(resultType), 0, Iterator.class); MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext); MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype));
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -284,6 +284,7 @@ * D day-of-year number 189 * M/L month-of-year number/text 7; 07; Jul; July; J * d day-of-month number 10 + * g modified-julian-day number 2451334 * * Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter * Y week-based-year year 1996; 96 @@ -308,10 +309,10 @@ * * V time-zone ID zone-id America/Los_Angeles; Z; -08:30 * z time-zone name zone-name Pacific Standard Time; PST - * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00; - * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15; - * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15; - * Z zone-offset offset-Z +0000; -0800; -08:00; + * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00 + * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15 + * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15 + * Z zone-offset offset-Z +0000; -0800; -08:00 * * p pad next pad modifier 1 *
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Thu Apr 28 23:08:17 2016 -0700 @@ -90,6 +90,7 @@ import java.time.format.DateTimeTextProvider.LocaleStore; import java.time.temporal.ChronoField; import java.time.temporal.IsoFields; +import java.time.temporal.JulianFields; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQueries; @@ -666,8 +667,11 @@ * No rounding occurs due to the maximum width - digits are simply dropped. * <p> * When parsing in strict mode, the number of parsed digits must be between - * the minimum and maximum width. When parsing in lenient mode, the minimum - * width is considered to be zero and the maximum is nine. + * the minimum and maximum width. In strict mode, if the minimum and maximum widths + * are equal and there is no decimal point then the parser will + * participate in adjacent value parsing, see + * {@link appendValue(java.time.temporal.TemporalField, int)}. When parsing in lenient mode, + * the minimum width is considered to be zero and the maximum is nine. * <p> * If the value cannot be obtained then an exception will be thrown. * If the value is negative an exception will be thrown. @@ -686,7 +690,12 @@ */ public DateTimeFormatterBuilder appendFraction( TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { - appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + if (minWidth == maxWidth && decimalPoint == false) { + // adjacent parsing + appendValue(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } else { + appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } return this; } @@ -1383,6 +1392,7 @@ * D day-of-year number 189 * M/L month-of-year number/text 7; 07; Jul; July; J * d day-of-month number 10 + * g modified-julian-day number 2451334 * * Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter * Y week-based-year year 1996; 96 @@ -1408,9 +1418,9 @@ * V time-zone ID zone-id America/Los_Angeles; Z; -08:30 * z time-zone name zone-name Pacific Standard Time; PST * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00; - * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15; - * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15; - * Z zone-offset offset-Z +0000; -0800; -08:00; + * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15 + * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15 + * Z zone-offset offset-Z +0000; -0800; -08:00 * * p pad next pad modifier 1 * @@ -1437,37 +1447,37 @@ * GGGG 4 appendText(ChronoField.ERA, TextStyle.FULL) * GGGGG 5 appendText(ChronoField.ERA, TextStyle.NARROW) * - * u 1 appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL); - * uu 2 appendValueReduced(ChronoField.YEAR, 2, 2000); - * uuu 3 appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL); - * u..u 4..n appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD); - * y 1 appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL); - * yy 2 appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000); - * yyy 3 appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL); - * y..y 4..n appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD); + * u 1 appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL) + * uu 2 appendValueReduced(ChronoField.YEAR, 2, 2000) + * uuu 3 appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL) + * u..u 4..n appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD) + * y 1 appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL) + * yy 2 appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000) + * yyy 3 appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL) + * y..y 4..n appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD) * Y 1 append special localized WeekFields element for numeric week-based-year - * YY 2 append special localized WeekFields element for reduced numeric week-based-year 2 digits; - * YYY 3 append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL); - * Y..Y 4..n append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD); + * YY 2 append special localized WeekFields element for reduced numeric week-based-year 2 digits + * YYY 3 append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL) + * Y..Y 4..n append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD) * - * Q 1 appendValue(IsoFields.QUARTER_OF_YEAR); - * QQ 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2); + * Q 1 appendValue(IsoFields.QUARTER_OF_YEAR) + * QQ 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2) * QQQ 3 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT) * QQQQ 4 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL) * QQQQQ 5 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW) - * q 1 appendValue(IsoFields.QUARTER_OF_YEAR); - * qq 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2); + * q 1 appendValue(IsoFields.QUARTER_OF_YEAR) + * qq 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2) * qqq 3 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT_STANDALONE) * qqqq 4 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL_STANDALONE) * qqqqq 5 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW_STANDALONE) * - * M 1 appendValue(ChronoField.MONTH_OF_YEAR); - * MM 2 appendValue(ChronoField.MONTH_OF_YEAR, 2); + * M 1 appendValue(ChronoField.MONTH_OF_YEAR) + * MM 2 appendValue(ChronoField.MONTH_OF_YEAR, 2) * MMM 3 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT) * MMMM 4 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL) * MMMMM 5 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW) - * L 1 appendValue(ChronoField.MONTH_OF_YEAR); - * LL 2 appendValue(ChronoField.MONTH_OF_YEAR, 2); + * L 1 appendValue(ChronoField.MONTH_OF_YEAR) + * LL 2 appendValue(ChronoField.MONTH_OF_YEAR, 2) * LLL 3 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE) * LLLL 4 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL_STANDALONE) * LLLLL 5 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW_STANDALONE) @@ -1481,6 +1491,7 @@ * DD 2 appendValue(ChronoField.DAY_OF_YEAR, 2) * DDD 3 appendValue(ChronoField.DAY_OF_YEAR, 3) * F 1 appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH) + * g..g 1..n appendValue(JulianFields.MODIFIED_JULIAN_DAY, n, 19, SignStyle.NORMAL) * E 1 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) * EE 2 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) * EEE 3 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) @@ -1539,8 +1550,8 @@ * <pre> * Pattern Count Equivalent builder methods * ------- ----- -------------------------- - * O 1 appendLocalizedOffset(TextStyle.SHORT); - * OOOO 4 appendLocalizedOffset(TextStyle.FULL); + * O 1 appendLocalizedOffset(TextStyle.SHORT) + * OOOO 4 appendLocalizedOffset(TextStyle.FULL) * X 1 appendOffset("+HHmm","Z") * XX 2 appendOffset("+HHMM","Z") * XXX 3 appendOffset("+HH:MM","Z") @@ -1554,7 +1565,7 @@ * Z 1 appendOffset("+HHMM","+0000") * ZZ 2 appendOffset("+HHMM","+0000") * ZZZ 3 appendOffset("+HHMM","+0000") - * ZZZZ 4 appendLocalizedOffset(TextStyle.FULL); + * ZZZZ 4 appendLocalizedOffset(TextStyle.FULL) * ZZZZZ 5 appendOffset("+HH:MM:ss","Z") * </pre> * <p> @@ -1836,6 +1847,9 @@ throw new IllegalArgumentException("Too many pattern letters: " + cur); } break; + case 'g': + appendValue(field, count, 19, SignStyle.NORMAL); + break; default: if (count == 1) { appendValue(field); @@ -1874,6 +1888,7 @@ FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY); // LDML FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND); // 310 (proposed for LDML) FIELD_MAP.put('N', ChronoField.NANO_OF_DAY); // 310 (proposed for LDML) + FIELD_MAP.put('g', JulianFields.MODIFIED_JULIAN_DAY); // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4 // 310 - Z - matches SimpleDateFormat and LDML // 310 - V - time-zone id, matches LDML @@ -1884,7 +1899,6 @@ // LDML - U - cycle year name, not supported by 310 yet // LDML - l - deprecated // LDML - j - not relevant - // LDML - g - modified-julian-day // LDML - v,V - extended time-zone names } @@ -2919,11 +2933,8 @@ /** * Prints and parses a numeric date-time field with optional padding. */ - static final class FractionPrinterParser implements DateTimePrinterParser { - private final TemporalField field; - private final int minWidth; - private final int maxWidth; - private final boolean decimalPoint; + static final class FractionPrinterParser extends NumberPrinterParser { + private final boolean decimalPoint; /** * Constructor. @@ -2934,6 +2945,7 @@ * @param decimalPoint whether to output the localized decimal point symbol */ FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { + this(field, minWidth, maxWidth, decimalPoint, 0); Objects.requireNonNull(field, "field"); if (field.range().isFixed() == false) { throw new IllegalArgumentException("Field must have a fixed set of values: " + field); @@ -2948,12 +2960,61 @@ throw new IllegalArgumentException("Maximum width must exceed or equal the minimum width but " + maxWidth + " < " + minWidth); } - this.field = field; - this.minWidth = minWidth; - this.maxWidth = maxWidth; + } + + /** + * Constructor. + * + * @param field the field to output, not null + * @param minWidth the minimum width to output, from 0 to 9 + * @param maxWidth the maximum width to output, from 0 to 9 + * @param decimalPoint whether to output the localized decimal point symbol + * @param subsequentWidth the subsequentWidth for this instance + */ + FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { + super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth); this.decimalPoint = decimalPoint; } + /** + * Returns a new instance with fixed width flag set. + * + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withFixedWidth() { + if (subsequentWidth == -1) { + return this; + } + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, -1); + } + + /** + * Returns a new instance with an updated subsequent width. + * + * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withSubsequentWidth(int subsequentWidth) { + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, this.subsequentWidth + subsequentWidth); + } + + /** + * For FractionPrinterPrinterParser, the width is fixed if context is sttrict, + * minWidth equal to maxWidth and decimalpoint is absent. + * @param context the context + * @return if the field is fixed width + * @see DateTimeFormatterBuilder#appendValueFraction(java.time.temporal.TemporalField, int, int, boolean) + */ + @Override + boolean isFixedWidth(DateTimeParseContext context) { + if (context.isStrict() && minWidth == maxWidth && decimalPoint == false) { + return true; + } + return false; + } + @Override public boolean format(DateTimePrintContext context, StringBuilder buf) { Long value = context.getValue(field); @@ -2986,8 +3047,8 @@ @Override public int parse(DateTimeParseContext context, CharSequence text, int position) { - int effectiveMin = (context.isStrict() ? minWidth : 0); - int effectiveMax = (context.isStrict() ? maxWidth : 9); + int effectiveMin = (context.isStrict() || isFixedWidth(context) ? minWidth : 0); + int effectiveMax = (context.isStrict() || isFixedWidth(context) ? maxWidth : 9); int length = text.length(); if (position == length) { // valid if whole field is optional, invalid if minimum width
--- a/src/java.base/share/classes/java/time/temporal/JulianFields.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/time/temporal/JulianFields.java Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -117,7 +117,13 @@ * * <h3>Astronomical and Scientific Notes</h3> * The standard astronomical definition uses a fraction to indicate the time-of-day, - * thus 3.25 would represent the time 18:00, since days start at midday. + * where each day is counted from midday to midday. For example, + * a fraction of 0 represents midday, a fraction of 0.25 + * represents 18:00, a fraction of 0.5 represents midnight and a fraction + * of 0.75 represents 06:00. + * <p> + * By contrast, this implementation has no fractional part, and counts + * days from midnight to midnight. * This implementation uses an integer and days starting at midnight. * The integer value for the Julian Day Number is the astronomical Julian Day value at midday * of the date in question.
--- a/src/java.base/share/classes/java/util/Observable.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/util/Observable.java Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, 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 @@ -58,7 +58,19 @@ * @see java.util.Observer * @see java.util.Observer#update(java.util.Observable, java.lang.Object) * @since 1.0 + * + * @deprecated + * This class and the {@link Observer} interface have been deprecated. + * The event model supported by {@code Observer} and {@code Observable} + * is quite limited, the order of notifications delivered by + * {@code Observable} is unspecified, and state changes are not in + * one-for-one correspondence with notifications. + * For a richer event model, consider using the + * {@link java.beans} package. For reliable and ordered + * messaging among threads, consider using one of the concurrent data + * structures in the {@link java.util.concurrent} package. */ +@Deprecated(since="9") public class Observable { private boolean changed = false; private Vector<Observer> obs;
--- a/src/java.base/share/classes/java/util/Observer.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/java/util/Observer.java Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, 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 @@ -31,7 +31,12 @@ * @author Chris Warth * @see java.util.Observable * @since 1.0 + * + * @deprecated + * This interface has been deprecated. See the {@link Observable} + * class for further information. */ +@Deprecated(since="9") public interface Observer { /** * This method is called whenever the observed object is changed. An
--- a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java Thu Apr 28 23:08:17 2016 -0700 @@ -183,7 +183,9 @@ } public static void releaseByteBuffer(ByteBuffer buffer) { - ImageBufferCache.releaseBuffer(buffer); + if (!MAP_ALL) { + ImageBufferCache.releaseBuffer(buffer); + } } public String getName() {
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java Thu Apr 28 23:08:17 2016 -0700 @@ -25,6 +25,7 @@ package jdk.internal.jimage; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -36,8 +37,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.function.Consumer; /** @@ -47,80 +51,486 @@ * but also compiled and delivered as part of the jrtfs.jar to support access * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ -public class ImageReader extends BasicImageReader { +public final class ImageReader implements AutoCloseable { + private SharedImageReader reader; - private static final int SIZE_OF_OFFSET = 4; - - // Map of files opened as LITTLE_ENDIAN - private static final HashMap<Path, ImageReader> OPEN_LE_FILES - = new HashMap<>(); - - // Map of files opened as BIG_ENDIAN - private static final HashMap<Path, ImageReader> OPEN_BE_FILES - = new HashMap<>(); - - private int openCount; - - // attributes of the .jimage file. jimage file does not contain - // attributes for the individual resources (yet). We use attributes - // of the jimage file itself (creation, modification, access times). - // Iniitalized lazily, see {@link #imageFileAttributes()}. - private BasicFileAttributes imageFileAttributes; - - // directory management implementation - private final HashMap<String, Node> nodes; - private volatile Directory rootDir; - - private Directory packagesDir; - private Directory modulesDir; - - private ImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { - super(imagePath, byteOrder); - this.nodes = new HashMap<>(); + private ImageReader(SharedImageReader reader) { + this.reader = reader; } public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { - HashMap<Path, ImageReader> openFiles = getOpenFilesMap(byteOrder); - ImageReader reader; - synchronized (openFiles) { - reader = openFiles.get(imagePath); - if (reader == null) { - reader = new ImageReader(imagePath, byteOrder); - ImageReader existingReader = openFiles.putIfAbsent(imagePath, reader); - assert (existingReader == null); - } - reader.openCount++; - } - return reader; + return SharedImageReader.open(imagePath, byteOrder); } - private static HashMap<Path, ImageReader> getOpenFilesMap(ByteOrder byteOrder) { - return (byteOrder == ByteOrder.BIG_ENDIAN) ? OPEN_BE_FILES : OPEN_LE_FILES; - } - - /** - * Opens the given file path as an image file, returning an {@code ImageReader}. - */ public static ImageReader open(Path imagePath) throws IOException { return open(imagePath, ByteOrder.nativeOrder()); } - private boolean canClose() { - HashMap<Path, ImageReader> openFiles = getOpenFilesMap(this.getByteOrder()); - synchronized (openFiles) { - if (--this.openCount == 0) { - return openFiles.remove(this.getName(), this); + @Override + public void close() throws IOException { + if (reader == null) { + throw new IOException("image file already closed"); + } + + reader.close(this); + reader = null; + } + + // directory management interface + public Directory getRootDirectory() throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getRootDirectory(); + } + + public Node findNode(String name) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.findNode(name); + } + + public byte[] getResource(Node node) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getResource(node); + } + + public byte[] getResource(Resource rs) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getResource(rs); + } + + public ImageHeader getHeader() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getHeader(); + } + + public static void releaseByteBuffer(ByteBuffer buffer) { + BasicImageReader.releaseByteBuffer(buffer); + } + + public String getName() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getName() ; + } + + public ByteOrder getByteOrder() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getByteOrder(); + } + + public Path getImagePath() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getImagePath(); + } + + public ImageStringsReader getStrings() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getStrings(); + } + + public ImageLocation findLocation(String mn, String rn) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(mn, rn); + } + + public ImageLocation findLocation(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(name); + } + + public String[] getEntryNames() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getEntryNames(); + } + + public long[] getAttributes(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getAttributes(offset); + } + + public String getString(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getString(offset); + } + + public byte[] getResource(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(name); + } + + public byte[] getResource(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(loc); + } + + public ByteBuffer getResourceBuffer(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceBuffer(loc); + } + + public InputStream getResourceStream(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceStream(loc); + } + + private final static class SharedImageReader extends BasicImageReader { + static final int SIZE_OF_OFFSET = Integer.BYTES; + + static final Map<Path, SharedImageReader> OPEN_FILES = new HashMap<>(); + + // List of openers for this shared image. + final Set<ImageReader> openers; + + // attributes of the .jimage file. jimage file does not contain + // attributes for the individual resources (yet). We use attributes + // of the jimage file itself (creation, modification, access times). + // Iniitalized lazily, see {@link #imageFileAttributes()}. + BasicFileAttributes imageFileAttributes; + + // directory management implementation + final HashMap<String, Node> nodes; + volatile Directory rootDir; + + Directory packagesDir; + Directory modulesDir; + + private SharedImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { + super(imagePath, byteOrder); + this.openers = new HashSet<>(); + this.nodes = new HashMap<>(); + } + + public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { + synchronized (OPEN_FILES) { + SharedImageReader reader = OPEN_FILES.get(imagePath); + + if (reader == null) { + // Will fail with an IOException if wrong byteOrder. + reader = new SharedImageReader(imagePath, byteOrder); + OPEN_FILES.put(imagePath, reader); + } else if (reader.getByteOrder() != byteOrder) { + throw new IOException("\"" + reader.getName() + "\" is not an image file"); + } + + ImageReader image = new ImageReader(reader); + reader.openers.add(image); + + return image; } } - return false; - } - @Override - public void close() throws IOException { - if (canClose()) { - super.close(); - clearNodes(); - } + public void close(ImageReader image) throws IOException { + synchronized (OPEN_FILES) { + if (!openers.remove(image)) { + throw new IOException("image file already closed"); + } + + if (openers.isEmpty()) { + close(); + nodes.clear(); + rootDir = null; + + if (!OPEN_FILES.remove(this.getImagePath(), this)) { + throw new IOException("image file not found in open list"); + } + } + } + } + + void addOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + openers.add(reader); + } + } + + boolean removeOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + return openers.remove(reader); + } + } + + // directory management interface + Directory getRootDirectory() { + return buildRootDirectory(); + } + + /** + * Lazily build a node from a name. + */ + synchronized Node buildNode(String name) { + Node n; + boolean isPackages = name.startsWith("/packages"); + boolean isModules = !isPackages && name.startsWith("/modules"); + + if (!(isModules || isPackages)) { + return null; + } + + ImageLocation loc = findLocation(name); + + if (loc != null) { // A sub tree node + if (isPackages) { + n = handlePackages(name, loc); + } else { // modules sub tree + n = handleModulesSubTree(name, loc); + } + } else { // Asking for a resource? /modules/java.base/java/lang/Object.class + if (isModules) { + n = handleResource(name); + } else { + // Possibly ask for /packages/java.lang/java.base + // although /packages/java.base not created + n = handleModuleLink(name); + } + } + return n; + } + + synchronized Directory buildRootDirectory() { + Directory root = rootDir; // volatile read + if (root != null) { + return root; + } + + root = newDirectory(null, "/"); + root.setIsRootDir(); + + // /packages dir + packagesDir = newDirectory(root, "/packages"); + packagesDir.setIsPackagesDir(); + + // /modules dir + modulesDir = newDirectory(root, "/modules"); + modulesDir.setIsModulesDir(); + + root.setCompleted(true); + return rootDir = root; + } + + /** + * To visit sub tree resources. + */ + interface LocationVisitor { + void visit(ImageLocation loc); + } + + void visitLocation(ImageLocation loc, LocationVisitor visitor) { + byte[] offsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(offsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { + int offset = intBuffer.get(i); + ImageLocation pkgLoc = getLocation(offset); + visitor.visit(pkgLoc); + } + } + + void visitPackageLocation(ImageLocation loc) { + // Retrieve package name + String pkgName = getBaseExt(loc); + // Content is array of offsets in Strings table + byte[] stringsOffsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + // For each module, create a link node. + for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { + // skip empty state, useless. + intBuffer.get(i); + i++; + int offset = intBuffer.get(i); + String moduleName = getString(offset); + Node targetNode = findNode("/modules/" + moduleName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); + } + } + } + + Node handlePackages(String name, ImageLocation loc) { + long size = loc.getUncompressedSize(); + Node n = null; + // Only possiblities are /packages, /packages/package/module + if (name.equals("/packages")) { + visitLocation(loc, (childloc) -> { + findNode(childloc.getFullName()); + }); + packagesDir.setCompleted(true); + n = packagesDir; + } else { + if (size != 0) { // children are offsets to module in StringsTable + String pkgName = getBaseExt(loc); + Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); + visitPackageLocation(loc); + pkgDir.setCompleted(true); + n = pkgDir; + } else { // Link to module + String pkgName = loc.getParent(); + String modName = getBaseExt(loc); + Node targetNode = findNode("/modules/" + modName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); + n = linkNode; + } + } + } + return n; + } + + // Asking for /packages/package/module although + // /packages/<pkg>/ not yet created, need to create it + // prior to return the link to module node. + Node handleModuleLink(String name) { + // eg: unresolved /packages/package/module + // Build /packages/package node + Node ret = null; + String radical = "/packages/"; + String path = name; + if (path.startsWith(radical)) { + int start = radical.length(); + int pkgEnd = path.indexOf('/', start); + if (pkgEnd != -1) { + String pkg = path.substring(start, pkgEnd); + String pkgPath = radical + pkg; + Node n = findNode(pkgPath); + // If not found means that this is a symbolic link such as: + // /packages/java.util/java.base/java/util/Vector.class + // and will be done by a retry of the filesystem + for (Node child : n.getChildren()) { + if (child.name.equals(name)) { + ret = child; + break; + } + } + } + } + return ret; + } + + Node handleModulesSubTree(String name, ImageLocation loc) { + Node n; + assert (name.equals(loc.getFullName())); + Directory dir = makeDirectories(name); + visitLocation(loc, (childloc) -> { + String path = childloc.getFullName(); + if (path.startsWith("/modules")) { // a package + makeDirectories(path); + } else { // a resource + makeDirectories(childloc.buildName(true, true, false)); + newResource(dir, childloc); + } + }); + dir.setCompleted(true); + n = dir; + return n; + } + + Node handleResource(String name) { + Node n = null; + String locationPath = name.substring("/modules".length()); + ImageLocation resourceLoc = findLocation(locationPath); + if (resourceLoc != null) { + Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); + Resource res = newResource(dir, resourceLoc); + n = res; + } + return n; + } + + String getBaseExt(ImageLocation loc) { + String base = loc.getBase(); + String ext = loc.getExtension(); + if (ext != null && !ext.isEmpty()) { + base = base + "." + ext; + } + return base; + } + + synchronized Node findNode(String name) { + buildRootDirectory(); + Node n = nodes.get(name); + if (n == null || !n.isCompleted()) { + n = buildNode(name); + } + return n; + } + + /** + * Returns the file attributes of the image file. + */ + BasicFileAttributes imageFileAttributes() { + BasicFileAttributes attrs = imageFileAttributes; + if (attrs == null) { + try { + Path file = getImagePath(); + attrs = Files.readAttributes(file, BasicFileAttributes.class); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + imageFileAttributes = attrs; + } + return attrs; + } + + Directory newDirectory(Directory parent, String name) { + Directory dir = Directory.create(parent, name, imageFileAttributes()); + nodes.put(dir.getName(), dir); + return dir; + } + + Resource newResource(Directory parent, ImageLocation loc) { + Resource res = Resource.create(parent, loc, imageFileAttributes()); + nodes.put(res.getName(), res); + return res; + } + + LinkNode newLinkNode(Directory dir, String name, Node link) { + LinkNode linkNode = LinkNode.create(dir, name, link); + nodes.put(linkNode.getName(), linkNode); + return linkNode; + } + + Directory makeDirectories(String parent) { + Directory last = rootDir; + for (int offset = parent.indexOf('/', 1); + offset != -1; + offset = parent.indexOf('/', offset + 1)) { + String dir = parent.substring(0, offset); + last = makeDirectory(dir, last); + } + return makeDirectory(parent, last); + + } + + Directory makeDirectory(String dir, Directory last) { + Directory nextDir = (Directory) nodes.get(dir); + if (nextDir == null) { + nextDir = newDirectory(last, dir); + } + return nextDir; + } + + byte[] getResource(Node node) throws IOException { + if (node.isResource()) { + return super.getResource(node.getLocation()); + } + throw new IOException("Not a resource: " + node); + } + + byte[] getResource(Resource rs) throws IOException { + return super.getResource(rs.getLocation()); + } } // jimage file does not store directory structure. We build nodes @@ -389,7 +799,7 @@ @Override public Node resolveLink(boolean recursive) { - return recursive && (link instanceof LinkNode)? ((LinkNode)link).resolveLink(true) : link; + return (recursive && link instanceof LinkNode) ? ((LinkNode)link).resolveLink(true) : link; } @Override @@ -397,297 +807,4 @@ return true; } } - - // directory management interface - public Directory getRootDirectory() { - return buildRootDirectory(); - } - - /** - * To visit sub tree resources. - */ - interface LocationVisitor { - - void visit(ImageLocation loc); - } - - /** - * Lazily build a node from a name. - */ - private Node buildNode(String name) { - Node n; - boolean isPackages = name.startsWith("/packages"); - boolean isModules = !isPackages && name.startsWith("/modules"); - - if (!(isModules || isPackages)) { - return null; - } - - ImageLocation loc = findLocation(name); - - if (loc != null) { // A sub tree node - if (isPackages) { - n = handlePackages(name, loc); - } else { // modules sub tree - n = handleModulesSubTree(name, loc); - } - } else { // Asking for a resource? /modules/java.base/java/lang/Object.class - if (isModules) { - n = handleResource(name); - } else { - // Possibly ask for /packages/java.lang/java.base - // although /packages/java.base not created - n = handleModuleLink(name); - } - } - return n; - } - - private void visitLocation(ImageLocation loc, LocationVisitor visitor) { - byte[] offsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(offsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { - int offset = intBuffer.get(i); - ImageLocation pkgLoc = getLocation(offset); - visitor.visit(pkgLoc); - } - } - - private void visitPackageLocation(ImageLocation loc) { - // Retrieve package name - String pkgName = getBaseExt(loc); - // Content is array of offsets in Strings table - byte[] stringsOffsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - // For each module, create a link node. - for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { - // skip empty state, useless. - intBuffer.get(i); - i++; - int offset = intBuffer.get(i); - String moduleName = getString(offset); - Node targetNode = findNode("/modules/" + moduleName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); - } - } - } - - private Node handlePackages(String name, ImageLocation loc) { - long size = loc.getUncompressedSize(); - Node n = null; - // Only possiblities are /packages, /packages/package/module - if (name.equals("/packages")) { - visitLocation(loc, (childloc) -> { - findNode(childloc.getFullName()); - }); - packagesDir.setCompleted(true); - n = packagesDir; - } else { - if (size != 0) { // children are offsets to module in StringsTable - String pkgName = getBaseExt(loc); - Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); - visitPackageLocation(loc); - pkgDir.setCompleted(true); - n = pkgDir; - } else { // Link to module - String pkgName = loc.getParent(); - String modName = getBaseExt(loc); - Node targetNode = findNode("/modules/" + modName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); - n = linkNode; - } - } - } - return n; - } - - // Asking for /packages/package/module although - // /packages/<pkg>/ not yet created, need to create it - // prior to return the link to module node. - private Node handleModuleLink(String name) { - // eg: unresolved /packages/package/module - // Build /packages/package node - Node ret = null; - String radical = "/packages/"; - String path = name; - if (path.startsWith(radical)) { - int start = radical.length(); - int pkgEnd = path.indexOf('/', start); - if (pkgEnd != -1) { - String pkg = path.substring(start, pkgEnd); - String pkgPath = radical + pkg; - Node n = findNode(pkgPath); - // If not found means that this is a symbolic link such as: - // /packages/java.util/java.base/java/util/Vector.class - // and will be done by a retry of the filesystem - for (Node child : n.getChildren()) { - if (child.name.equals(name)) { - ret = child; - break; - } - } - } - } - return ret; - } - - private Node handleModulesSubTree(String name, ImageLocation loc) { - Node n; - assert (name.equals(loc.getFullName())); - Directory dir = makeDirectories(name); - visitLocation(loc, (childloc) -> { - String path = childloc.getFullName(); - if (path.startsWith("/modules")) { // a package - makeDirectories(path); - } else { // a resource - makeDirectories(childloc.buildName(true, true, false)); - newResource(dir, childloc); - } - }); - dir.setCompleted(true); - n = dir; - return n; - } - - private Node handleResource(String name) { - Node n = null; - String locationPath = name.substring("/modules".length()); - ImageLocation resourceLoc = findLocation(locationPath); - if (resourceLoc != null) { - Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); - Resource res = newResource(dir, resourceLoc); - n = res; - } - return n; - } - - private String getBaseExt(ImageLocation loc) { - String base = loc.getBase(); - String ext = loc.getExtension(); - if (ext != null && !ext.isEmpty()) { - base = base + "." + ext; - } - return base; - } - - public synchronized Node findNode(String name) { - buildRootDirectory(); - Node n = nodes.get(name); - if (n == null || !n.isCompleted()) { - n = buildNode(name); - } - return n; - } - - private synchronized void clearNodes() { - nodes.clear(); - rootDir = null; - } - - /** - * Returns the file attributes of the image file. - */ - private BasicFileAttributes imageFileAttributes() { - BasicFileAttributes attrs = imageFileAttributes; - if (attrs == null) { - try { - Path file = getImagePath(); - attrs = Files.readAttributes(file, BasicFileAttributes.class); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - imageFileAttributes = attrs; - } - return attrs; - } - - private Directory buildRootDirectory() { - Directory root = rootDir; // volatile read - if (root != null) { - return root; - } - - synchronized (this) { - root = rootDir; - if (root != null) { - return root; - } - - // FIXME no time information per resource in jimage file (yet?) - // we use file attributes of jimage itself. - // root directory - root = newDirectory(null, "/"); - root.setIsRootDir(); - - // /packages dir - packagesDir = newDirectory(root, "/packages"); - packagesDir.setIsPackagesDir(); - - // /modules dir - modulesDir = newDirectory(root, "/modules"); - modulesDir.setIsModulesDir(); - - root.setCompleted(true); - return rootDir = root; - } - } - - private Directory newDirectory(Directory parent, String name) { - Directory dir = Directory.create(parent, name, imageFileAttributes()); - nodes.put(dir.getName(), dir); - return dir; - } - - private Resource newResource(Directory parent, ImageLocation loc) { - Resource res = Resource.create(parent, loc, imageFileAttributes()); - nodes.put(res.getName(), res); - return res; - } - - private LinkNode newLinkNode(Directory dir, String name, Node link) { - LinkNode linkNode = LinkNode.create(dir, name, link); - nodes.put(linkNode.getName(), linkNode); - return linkNode; - } - - private Directory makeDirectories(String parent) { - Directory last = rootDir; - for (int offset = parent.indexOf('/', 1); - offset != -1; - offset = parent.indexOf('/', offset + 1)) { - String dir = parent.substring(0, offset); - last = makeDirectory(dir, last); - } - return makeDirectory(parent, last); - - } - - private Directory makeDirectory(String dir, Directory last) { - Directory nextDir = (Directory) nodes.get(dir); - if (nextDir == null) { - nextDir = newDirectory(last, dir); - } - return nextDir; - } - - public byte[] getResource(Node node) throws IOException { - if (node.isResource()) { - return super.getResource(node.getLocation()); - } - throw new IOException("Not a resource: " + node); - } - - public byte[] getResource(Resource rs) throws IOException { - return super.getResource(rs.getLocation()); - } }
--- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java Thu Apr 28 23:08:17 2016 -0700 @@ -299,13 +299,9 @@ } // clean up this file system - called from finalize and close - void cleanup() throws IOException { - if (!isOpen) { - return; - } - synchronized (this) { + synchronized void cleanup() throws IOException { + if (isOpen) { isOpen = false; - // close image reader and null out image.close(); image = null; } @@ -461,8 +457,8 @@ private Node lookup(String path) { try { return image.findNode(path); - } catch (RuntimeException re) { - throw new InvalidPathException(path, re.toString()); + } catch (RuntimeException | IOException ex) { + throw new InvalidPathException(path, ex.toString()); } }
--- a/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java Thu Apr 28 23:08:17 2016 -0700 @@ -49,7 +49,7 @@ */ abstract class SystemImage { - abstract Node findNode(String path); + abstract Node findNode(String path) throws IOException; abstract byte[] getResource(Node node) throws IOException; abstract void close() throws IOException; @@ -60,7 +60,7 @@ image.getRootDirectory(); return new SystemImage() { @Override - Node findNode(String path) { + Node findNode(String path) throws IOException { return image.findNode(path); } @Override
--- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Thu Apr 28 23:08:17 2016 -0700 @@ -30,6 +30,7 @@ import java.lang.reflect.Layer; import java.lang.reflect.Module; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -184,9 +185,9 @@ /** * Define the {@code Package} with the given name. The specified - * location is a jrt URL to a named module in the run-time image, a - * file path to a module in an exploded run-time image, or the file - * path to an enty on the boot class path (java agent Boot-Class-Path + * location is a jrt URL to a named module in the run-time image, + * a file URL to a module in an exploded run-time image, or a file + * path to an entry on the boot class path (java agent Boot-Class-Path * or -Xbootclasspath/a. * * <p> If the given location is a JAR file containing a manifest, @@ -194,7 +195,9 @@ * the manifest, if present. * * @param name package name - * @param location location where the package is (jrt URL or file path) + * @param location location where the package is (jrt URL or file URL + * for a named module in the run-time or exploded image; + * a file path for a package from -Xbootclasspath/a) */ static Package definePackage(String name, String location) { Module module = findModule(location); @@ -222,9 +225,9 @@ if (location.startsWith("jrt:/")) { // named module in runtime image ("jrt:/".length() == 5) mn = location.substring(5, location.length()); - } else { + } else if (location.startsWith("file:/")) { // named module in exploded image - Path path = Paths.get(location); + Path path = Paths.get(URI.create(location)); Path modulesDir = Paths.get(JAVA_HOME, "modules"); if (path.startsWith(modulesDir)) { mn = path.getFileName().toString();
--- a/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java Thu Apr 28 23:08:17 2016 -0700 @@ -33,6 +33,9 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.ref.ReferenceQueue; +import java.lang.reflect.Module; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collection; import java.util.ResourceBundle; @@ -129,41 +132,49 @@ return w; } - final static SharedLoggers system = new SharedLoggers(); final static SharedLoggers application = new SharedLoggers(); } + public static boolean isSystem(Module m) { + ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<>() { + @Override + public ClassLoader run() { + return m.getClassLoader(); + } + }); + return cl == null; + } + @Override - public final Logger getLogger(String name, /* Module */ Class<?> caller) { + public final Logger getLogger(String name, Module module) { checkPermission(); - return demandLoggerFor(name, caller); + return demandLoggerFor(name, module); } @Override public final Logger getLocalizedLogger(String name, ResourceBundle bundle, - /* Module */ Class<?> caller) { - return super.getLocalizedLogger(name, bundle, caller); + Module module) { + return super.getLocalizedLogger(name, bundle, module); } - - /** - * Returns a {@link Logger logger} suitable for the caller usage. + * Returns a {@link Logger logger} suitable for use within the + * given {@code module}. * * @implSpec The default implementation for this method is to return a * simple logger that will print all messages of INFO level and above * to the console. That simple logger is not configurable. * * @param name The name of the logger. - * @param caller The class on behalf of which the logger is created. + * @param module The module on behalf of which the logger is created. * @return A {@link Logger logger} suitable for the application usage. * @throws SecurityException if the calling code does not have the * {@code RuntimePermission("loggerFinder")}. */ - protected Logger demandLoggerFor(String name, /* Module */ Class<?> caller) { + protected Logger demandLoggerFor(String name, Module module) { checkPermission(); - if (caller.getClassLoader() == null) { + if (isSystem(module)) { return SharedLoggers.system.get(SimpleConsoleLogger::makeSimpleLogger, name); } else { return SharedLoggers.application.get(SimpleConsoleLogger::makeSimpleLogger, name);
--- a/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java Thu Apr 28 23:08:17 2016 -0700 @@ -31,6 +31,7 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.ref.WeakReference; +import java.lang.reflect.Module; import java.util.Objects; import jdk.internal.misc.VM; import sun.util.logging.PlatformLogger; @@ -59,15 +60,15 @@ * A factory method to create an SPI logger. * Usually, this will be something like LazyLoggers::getSystemLogger. */ - final BiFunction<String, Class<?>, L> loggerSupplier; + final BiFunction<String, Module, L> loggerSupplier; - public LazyLoggerFactories(BiFunction<String, Class<?>, L> loggerSupplier) { + public LazyLoggerFactories(BiFunction<String, Module, L> loggerSupplier) { this(Objects.requireNonNull(loggerSupplier), (Void)null); } - private LazyLoggerFactories(BiFunction<String, Class<?>, L> loggerSupplier, + private LazyLoggerFactories(BiFunction<String, Module, L> loggerSupplier, Void unused) { this.loggerSupplier = loggerSupplier; } @@ -107,8 +108,8 @@ // The factories that will be used to create the logger lazyly final LazyLoggerFactories<? extends Logger> factories; - // We need to pass the actual caller when creating the logger. - private final WeakReference<Class<?>> callerRef; + // We need to pass the actual caller module when creating the logger. + private final WeakReference<Module> moduleRef; // The name of the logger that will be created lazyly final String name; @@ -121,17 +122,17 @@ private LazyLoggerAccessor(String name, LazyLoggerFactories<? extends Logger> factories, - Class<?> caller) { + Module module) { this(Objects.requireNonNull(name), Objects.requireNonNull(factories), - Objects.requireNonNull(caller), null); + Objects.requireNonNull(module), null); } private LazyLoggerAccessor(String name, LazyLoggerFactories<? extends Logger> factories, - Class<?> caller, Void unused) { + Module module, Void unused) { this.name = name; this.factories = factories; - this.callerRef = new WeakReference<Class<?>>(caller); + this.moduleRef = new WeakReference<>(module); } /** @@ -270,12 +271,12 @@ // Creates the wrapped logger by invoking the SPI. Logger createLogger() { - final Class<?> caller = callerRef.get(); - if (caller == null) { - throw new IllegalStateException("The class for which this logger" + final Module module = moduleRef.get(); + if (module == null) { + throw new IllegalStateException("The module for which this logger" + " was created has been garbage collected"); } - return this.factories.loggerSupplier.apply(name, caller); + return this.factories.loggerSupplier.apply(name, module); } /** @@ -289,8 +290,8 @@ * @return A new LazyLoggerAccessor. */ public static LazyLoggerAccessor makeAccessor(String name, - LazyLoggerFactories<? extends Logger> factories, Class<?> caller) { - return new LazyLoggerAccessor(name, factories, caller); + LazyLoggerFactories<? extends Logger> factories, Module module) { + return new LazyLoggerAccessor(name, factories, module); } } @@ -346,11 +347,11 @@ // Avoid using lambda here as lazy loggers could be created early // in the bootstrap sequence... - private static final BiFunction<String, Class<?>, Logger> loggerSupplier = + private static final BiFunction<String, Module, Logger> loggerSupplier = new BiFunction<>() { @Override - public Logger apply(String name, Class<?> caller) { - return LazyLoggers.getLoggerFromFinder(name, caller); + public Logger apply(String name, Module module) { + return LazyLoggers.getLoggerFromFinder(name, module); } }; @@ -367,8 +368,8 @@ // logger provider until the VM has finished booting. // private static final class JdkLazyLogger extends LazyLoggerWrapper { - JdkLazyLogger(String name, Class<?> caller) { - this(LazyLoggerAccessor.makeAccessor(name, factories, caller), + JdkLazyLogger(String name, Module module) { + this(LazyLoggerAccessor.makeAccessor(name, factories, module), (Void)null); } private JdkLazyLogger(LazyLoggerAccessor holder, Void unused) { @@ -380,16 +381,16 @@ * Gets a logger from the LoggerFinder. Creates the actual concrete * logger. * @param name name of the logger - * @param caller class on behalf of which the logger is created + * @param module module on behalf of which the logger is created * @return The logger returned by the LoggerFinder. */ - static Logger getLoggerFromFinder(String name, Class<?> caller) { + static Logger getLoggerFromFinder(String name, Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm == null) { - return accessLoggerFinder().getLogger(name, caller); + return accessLoggerFinder().getLogger(name, module); } else { return AccessController.doPrivileged((PrivilegedAction<Logger>) - () -> {return accessLoggerFinder().getLogger(name, caller);}, + () -> {return accessLoggerFinder().getLogger(name, module);}, null, LOGGERFINDER_PERMISSION); } } @@ -398,22 +399,22 @@ * Returns a (possibly lazy) Logger for the caller. * * @param name the logger name - * @param caller The class on behalf of which the logger is created. - * If the caller is not loaded from the Boot ClassLoader, + * @param module The module on behalf of which the logger is created. + * If the module is not loaded from the Boot ClassLoader, * the LoggerFinder is accessed and the logger returned - * by {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class)} + * by {@link LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module)} * is returned to the caller directly. * Otherwise, the logger returned by - * {@link #getLazyLogger(java.lang.String, java.lang.Class)} + * {@link #getLazyLogger(java.lang.String, java.lang.reflect.Module)} * is returned to the caller. * * @return a (possibly lazy) Logger instance. */ - public static final Logger getLogger(String name, Class<?> caller) { - if (caller.getClassLoader() == null) { - return getLazyLogger(name, caller); + public static final Logger getLogger(String name, Module module) { + if (DefaultLoggerFinder.isSystem(module)) { + return getLazyLogger(name, module); } else { - return getLoggerFromFinder(name, caller); + return getLoggerFromFinder(name, module); } } @@ -423,10 +424,10 @@ * returned by {@link BootstrapLogger#useLazyLoggers()}. * * @param name the logger name - * @param caller the class on behalf of which the logger is created. + * @param module the module on behalf of which the logger is created. * @return a (possibly lazy) Logger instance. */ - public static final Logger getLazyLogger(String name, Class<?> caller) { + public static final Logger getLazyLogger(String name, Module module) { // BootstrapLogger has the logic to determine whether a LazyLogger // should be used. Usually, it is worth it only if: @@ -438,10 +439,10 @@ // configuration, we're not going to delay the creation of loggers... final boolean useLazyLogger = BootstrapLogger.useLazyLoggers(); if (useLazyLogger) { - return new JdkLazyLogger(name, caller); + return new JdkLazyLogger(name, module); } else { // Directly invoke the LoggerFinder. - return getLoggerFromFinder(name, caller); + return getLoggerFromFinder(name, module); } }
--- a/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.net; - -import java.net.SocketOption; - -/** - * Defines extended socket options, beyond those defined in - * {@link java.net.StandardSocketOptions}. These options may be platform - * specific. - * - * @since 1.8 - */ -public final class ExtendedSocketOptions { - - private static class ExtSocketOption<T> implements SocketOption<T> { - private final String name; - private final Class<T> type; - ExtSocketOption(String name, Class<T> type) { - this.name = name; - this.type = type; - } - @Override public String name() { return name; } - @Override public Class<T> type() { return type; } - @Override public String toString() { return name; } - } - - private ExtendedSocketOptions() {} - - /** - * Service level properties. When a security manager is installed, - * setting or getting this option requires a {@link NetworkPermission} - * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"} - * respectively. - */ - public static final SocketOption<SocketFlow> SO_FLOW_SLA = new - ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class); -}
--- a/src/java.base/share/classes/jdk/net/NetworkPermission.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.net; - -import java.security.BasicPermission; - -/** - * Represents permission to access the extended networking capabilities - * defined in the jdk.net package. These permissions contain a target - * name, but no actions list. Callers either possess the permission or not. - * <p> - * The following targets are defined: - * - * <table border=1 cellpadding=5 summary="permission target name, - * what the target allows,and associated risks"> - * <tr> - * <th>Permission Target Name</th> - * <th>What the Permission Allows</th> - * <th>Risks of Allowing this Permission</th> - * </tr> - * <tr> - * <td>setOption.SO_FLOW_SLA</td> - * <td>set the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option - * on any socket that supports it</td> - * <td>allows caller to set a higher priority or bandwidth allocation - * to sockets it creates, than they might otherwise be allowed.</td> - * </tr> - * <tr> - * <td>getOption.SO_FLOW_SLA</td> - * <td>retrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} - * setting from any socket that supports the option</td> - * <td>allows caller access to SLA information that it might not - * otherwise have</td> - * </tr></table> - * - * @see jdk.net.ExtendedSocketOptions - * - * @since 1.8 - */ - -public final class NetworkPermission extends BasicPermission { - - private static final long serialVersionUID = -2012939586906722291L; - - /** - * Creates a NetworkPermission with the given target name. - * - * @param name the permission target name - * @throws NullPointerException if {@code name} is {@code null}. - * @throws IllegalArgumentException if {@code name} is empty. - */ - public NetworkPermission(String name) - { - super(name); - } - - /** - * Creates a NetworkPermission with the given target name. - * - * @param name the permission target name - * @param actions should be {@code null}. Is ignored if not. - * @throws NullPointerException if {@code name} is {@code null}. - * @throws IllegalArgumentException if {@code name} is empty. - */ - public NetworkPermission(String name, String actions) - { - super(name, actions); - } -}
--- a/src/java.base/share/classes/jdk/net/SocketFlow.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.net; - -import java.lang.annotation.Native; - -/** - * Represents the service level properties for the platform specific socket - * option {@link ExtendedSocketOptions#SO_FLOW_SLA}. - * <p> - * The priority and bandwidth parameters must be set before - * setting the socket option. - * <p> - * When the {@code SO_FLOW_SLA} option is set then it may not take effect - * immediately. If the value of the socket option is obtained with - * {@code getOption()} then the status may be returned as {@code INPROGRESS} - * until it takes effect. The priority and bandwidth values are only valid when - * the status is returned as OK. - * <p> - * When a security manager is installed, a {@link NetworkPermission} - * is required to set or get this option. - * - * @since 1.8 - */ -public class SocketFlow { - - private static final int UNSET = -1; - @Native public static final int NORMAL_PRIORITY = 1; - @Native public static final int HIGH_PRIORITY = 2; - - private int priority = NORMAL_PRIORITY; - - private long bandwidth = UNSET; - - private Status status = Status.NO_STATUS; - - private SocketFlow() {} - - /** - * Enumeration of the return values from the SO_FLOW_SLA - * socket option. Both setting and getting the option return - * one of these statuses, which reflect the state of socket's - * flow. - * - * @since 1.8 - */ - public enum Status { - /** - * Set or get socket option has not been called yet. Status - * values can only be retrieved after calling set or get. - */ - NO_STATUS, - /** - * Flow successfully created. - */ - OK, - /** - * Caller has no permission to create flow. - */ - NO_PERMISSION, - /** - * Flow can not be created because socket is not connected. - */ - NOT_CONNECTED, - /** - * Flow creation not supported for this socket. - */ - NOT_SUPPORTED, - /** - * A flow already exists with identical attributes. - */ - ALREADY_CREATED, - /** - * A flow is being created. - */ - IN_PROGRESS, - /** - * Some other unspecified error. - */ - OTHER - } - - /** - * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA - * socket option and create a socket flow. - */ - public static SocketFlow create() { - return new SocketFlow(); - } - - /** - * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY - * HIGH_PRIORITY. If not set, a flow's priority is normal. - * - * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or - * HIGH_PRIORITY. - */ - public SocketFlow priority(int priority) { - if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) { - throw new IllegalArgumentException("invalid priority"); - } - this.priority = priority; - return this; - } - - /** - * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero. - * A value of zero drops all packets for the socket. - * - * @throws IllegalArgumentException if bandwidth is less than zero. - */ - public SocketFlow bandwidth(long bandwidth) { - if (bandwidth < 0) { - throw new IllegalArgumentException("invalid bandwidth"); - } else { - this.bandwidth = bandwidth; - } - return this; - } - - /** - * Returns this SocketFlow's priority. - */ - public int priority() { - return priority; - } - - /** - * Returns this SocketFlow's bandwidth. - * - * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK. - */ - public long bandwidth() { - return bandwidth; - } - - /** - * Returns the Status value of this SocketFlow. NO_STATUS is returned - * if the object was not used in a call to set or get the option. - */ - public Status status() { - return status; - } -}
--- a/src/java.base/share/classes/jdk/net/Sockets.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,339 +0,0 @@ -/* - * Copyright (c) 2016, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package jdk.net; - -import java.net.*; -import java.io.IOException; -import java.io.FileDescriptor; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.lang.reflect.Field; -import java.util.Set; -import java.util.HashSet; -import java.util.HashMap; -import java.util.Collections; -import sun.net.ExtendedOptionsImpl; - -/** - * Defines static methods to set and get socket options defined by the - * {@link java.net.SocketOption} interface. All of the standard options defined - * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and - * {@link java.net.DatagramSocket} can be set this way, as well as additional - * or platform specific options supported by each socket type. - * <p> - * The {@link #supportedOptions(Class)} method can be called to determine - * the complete set of options available (per socket type) on the - * current system. - * <p> - * When a security manager is installed, some non-standard socket options - * may require a security permission before being set or get. - * The details are specified in {@link ExtendedSocketOptions}. No permission - * is required for {@link java.net.StandardSocketOptions}. - * - * @see java.nio.channels.NetworkChannel - */ -public class Sockets { - - private static final HashMap<Class<?>,Set<SocketOption<?>>> - options = new HashMap<>(); - - static { - initOptionSets(); - } - - private Sockets() {} - - /** - * Sets the value of a socket option on a {@link java.net.Socket} - * - * @param s the socket - * @param name The socket option - * @param value The value of the socket option. May be null for some - * options. - * - * @throws UnsupportedOperationException if the socket does not support - * the option. - * - * @throws IllegalArgumentException if the value is not valid for - * the option. - * - * @throws IOException if an I/O error occurs, or socket is closed. - * - * @throws SecurityException if a security manager is set and the - * caller does not have any required permission. - * - * @throws NullPointerException if name is null - * - * @see java.net.StandardSocketOptions - */ - public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException - { - s.setOption(name, value); - } - - /** - * Returns the value of a socket option from a {@link java.net.Socket} - * - * @param s the socket - * @param name The socket option - * - * @return The value of the socket option. - * - * @throws UnsupportedOperationException if the socket does not support - * the option. - * - * @throws IOException if an I/O error occurs - * - * @throws SecurityException if a security manager is set and the - * caller does not have any required permission. - * - * @throws NullPointerException if name is null - * - * @see java.net.StandardSocketOptions - */ - public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException - { - return s.getOption(name); - } - - /** - * Sets the value of a socket option on a {@link java.net.ServerSocket} - * - * @param s the socket - * @param name The socket option - * @param value The value of the socket option. - * - * @throws UnsupportedOperationException if the socket does not support - * the option. - * - * @throws IllegalArgumentException if the value is not valid for - * the option. - * - * @throws IOException if an I/O error occurs - * - * @throws NullPointerException if name is null - * - * @throws SecurityException if a security manager is set and the - * caller does not have any required permission. - * - * @see java.net.StandardSocketOptions - */ - public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException - { - s.setOption(name, value); - } - - /** - * Returns the value of a socket option from a {@link java.net.ServerSocket} - * - * @param s the socket - * @param name The socket option - * - * @return The value of the socket option. - * - * @throws UnsupportedOperationException if the socket does not support - * the option. - * - * @throws IOException if an I/O error occurs - * - * @throws NullPointerException if name is null - * - * @throws SecurityException if a security manager is set and the - * caller does not have any required permission. - * - * @see java.net.StandardSocketOptions - */ - public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException - { - return s.getOption(name); - } - - /** - * Sets the value of a socket option on a {@link java.net.DatagramSocket} - * or {@link java.net.MulticastSocket} - * - * @param s the socket - * @param name The socket option - * @param value The value of the socket option. - * - * @throws UnsupportedOperationException if the socket does not support - * the option. - * - * @throws IllegalArgumentException if the value is not valid for - * the option. - * - * @throws IOException if an I/O error occurs - * - * @throws NullPointerException if name is null - * - * @throws SecurityException if a security manager is set and the - * caller does not have any required permission. - * - * @see java.net.StandardSocketOptions - */ - public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException - { - s.setOption(name, value); - } - - /** - * Returns the value of a socket option from a - * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket} - * - * @param s the socket - * @param name The socket option - * - * @return The value of the socket option. - * - * @throws UnsupportedOperationException if the socket does not support - * the option. - * - * @throws IOException if an I/O error occurs - * - * @throws NullPointerException if name is null - * - * @throws SecurityException if a security manager is set and the - * caller does not have any required permission. - * - * @see java.net.StandardSocketOptions - */ - public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException - { - return s.getOption(name); - } - - /** - * Returns a set of {@link java.net.SocketOption}s supported by the - * given socket type. This set may include standard options and also - * non standard extended options. - * - * @param socketType the type of java.net socket - * - * @throws IllegalArgumentException if socketType is not a valid - * socket type from the java.net package. - */ - public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) { - Set<SocketOption<?>> set = options.get(socketType); - if (set == null) { - throw new IllegalArgumentException("unknown socket type"); - } - return set; - } - - private static void checkValueType(Object value, Class<?> type) { - if (!type.isAssignableFrom(value.getClass())) { - String s = "Found: " + value.getClass().toString() + " Expected: " - + type.toString(); - throw new IllegalArgumentException(s); - } - } - - private static volatile boolean checkedReusePort; - private static volatile boolean isReusePortAvailable; - - /** - * Tells whether SO_REUSEPORT is supported. - */ - static boolean isReusePortAvailable() { - if (!checkedReusePort) { - isReusePortAvailable = isReusePortAvailable0(); - checkedReusePort = true; - } - return isReusePortAvailable; - } - - private static void initOptionSets() { - boolean flowsupported = ExtendedOptionsImpl.flowSupported(); - boolean reuseportsupported = isReusePortAvailable(); - // Socket - - Set<SocketOption<?>> set = new HashSet<>(); - set.add(StandardSocketOptions.SO_KEEPALIVE); - set.add(StandardSocketOptions.SO_SNDBUF); - set.add(StandardSocketOptions.SO_RCVBUF); - set.add(StandardSocketOptions.SO_REUSEADDR); - if (reuseportsupported) { - set.add(StandardSocketOptions.SO_REUSEPORT); - } - set.add(StandardSocketOptions.SO_LINGER); - set.add(StandardSocketOptions.IP_TOS); - set.add(StandardSocketOptions.TCP_NODELAY); - if (flowsupported) { - set.add(ExtendedSocketOptions.SO_FLOW_SLA); - } - set = Collections.unmodifiableSet(set); - options.put(Socket.class, set); - - // ServerSocket - - set = new HashSet<>(); - set.add(StandardSocketOptions.SO_RCVBUF); - set.add(StandardSocketOptions.SO_REUSEADDR); - if (reuseportsupported) { - set.add(StandardSocketOptions.SO_REUSEPORT); - } - set.add(StandardSocketOptions.IP_TOS); - set = Collections.unmodifiableSet(set); - options.put(ServerSocket.class, set); - - // DatagramSocket - - set = new HashSet<>(); - set.add(StandardSocketOptions.SO_SNDBUF); - set.add(StandardSocketOptions.SO_RCVBUF); - set.add(StandardSocketOptions.SO_REUSEADDR); - if (reuseportsupported) { - set.add(StandardSocketOptions.SO_REUSEPORT); - } - set.add(StandardSocketOptions.IP_TOS); - if (flowsupported) { - set.add(ExtendedSocketOptions.SO_FLOW_SLA); - } - set = Collections.unmodifiableSet(set); - options.put(DatagramSocket.class, set); - - // MulticastSocket - - set = new HashSet<>(); - set.add(StandardSocketOptions.SO_SNDBUF); - set.add(StandardSocketOptions.SO_RCVBUF); - set.add(StandardSocketOptions.SO_REUSEADDR); - if (reuseportsupported) { - set.add(StandardSocketOptions.SO_REUSEPORT); - } - set.add(StandardSocketOptions.IP_TOS); - set.add(StandardSocketOptions.IP_MULTICAST_IF); - set.add(StandardSocketOptions.IP_MULTICAST_TTL); - set.add(StandardSocketOptions.IP_MULTICAST_LOOP); - if (flowsupported) { - set.add(ExtendedSocketOptions.SO_FLOW_SLA); - } - set = Collections.unmodifiableSet(set); - options.put(MulticastSocket.class, set); - } - - private static native boolean isReusePortAvailable0(); -}
--- a/src/java.base/share/classes/jdk/net/package-info.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/** - * Platform specific socket options for the {@code java.net} and {@code java.nio.channels} - * socket classes. - * - * @since 1.8 - */ - -package jdk.net;
--- a/src/java.base/share/classes/module-info.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/module-info.java Thu Apr 28 23:08:17 2016 -0700 @@ -83,8 +83,6 @@ // see JDK-8144062 exports jdk; - // see JDK-8044773 - exports jdk.net; // the service types defined by the APIs in this module @@ -168,6 +166,7 @@ java.sql, java.xml, jdk.charsets, + jdk.net, jdk.scripting.nashorn, jdk.unsupported, jdk.vm.ci; @@ -194,6 +193,8 @@ jdk.jvmstat; exports sun.net to java.httpclient; + exports sun.net.ext to + jdk.net; exports sun.net.dns to java.security.jgss, jdk.naming.dns;
--- a/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.net; - -import java.net.*; -import jdk.net.*; -import java.io.IOException; -import java.io.FileDescriptor; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.lang.reflect.Field; -import java.util.Set; -import java.util.HashSet; -import java.util.HashMap; -import java.util.Collections; - -/** - * Contains the native implementation for extended socket options - * together with some other static utilities - */ -public class ExtendedOptionsImpl { - - static { - AccessController.doPrivileged((PrivilegedAction<Void>)() -> { - System.loadLibrary("net"); - return null; - }); - init(); - } - - private ExtendedOptionsImpl() {} - - public static void checkSetOptionPermission(SocketOption<?> option) { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - String check = "setOption." + option.name(); - sm.checkPermission(new NetworkPermission(check)); - } - - public static void checkGetOptionPermission(SocketOption<?> option) { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - String check = "getOption." + option.name(); - sm.checkPermission(new NetworkPermission(check)); - } - - public static void checkValueType(Object value, Class<?> type) { - if (!type.isAssignableFrom(value.getClass())) { - String s = "Found: " + value.getClass().toString() + " Expected: " - + type.toString(); - throw new IllegalArgumentException(s); - } - } - - private static native void init(); - - /* - * Extension native implementations - * - * SO_FLOW_SLA - */ - public static native void setFlowOption(FileDescriptor fd, SocketFlow f); - public static native void getFlowOption(FileDescriptor fd, SocketFlow f); - public static native boolean flowSupported(); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.net.ext; + +import java.io.FileDescriptor; +import java.net.SocketException; +import java.net.SocketOption; +import java.util.Collections; +import java.util.Set; + +/** + * Defines the infrastructure to support extended socket options, beyond those + * defined in {@link java.net.StandardSocketOptions}. + * + * Extended socket options are accessed through the jdk.net API, which is in + * the jdk.net module. + */ +public abstract class ExtendedSocketOptions { + + private final Set<SocketOption<?>> options; + + /** Tells whether or not the option is supported. */ + public final boolean isOptionSupported(SocketOption<?> option) { + return options().contains(option); + } + + /** Return the, possibly empty, set of extended socket options available. */ + public final Set<SocketOption<?>> options() { return options; } + + /** Sets the value of a socket option, for the given socket. */ + public abstract void setOption(FileDescriptor fd, SocketOption<?> option, Object value) + throws SocketException; + + /** Returns the value of a socket option, for the given socket. */ + public abstract Object getOption(FileDescriptor fd, SocketOption<?> option) + throws SocketException; + + protected ExtendedSocketOptions(Set<SocketOption<?>> options) { + this.options = options; + } + + private static volatile ExtendedSocketOptions instance; + + public static final ExtendedSocketOptions getInstance() { return instance; } + + /** Registers support for extended socket options. Invoked by the jdk.net module. */ + public static final void register(ExtendedSocketOptions extOptions) { + if (instance != null) + throw new InternalError("Attempting to reregister extended options"); + + instance = extOptions; + } + + static { + try { + // If the class is present, it will be initialized which + // triggers registration of the extended socket options. + Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions"); + } catch (ClassNotFoundException e) { + // the jdk.net module is not present => no extended socket options + instance = new NoExtendedSocketOptions(); + } + } + + static final class NoExtendedSocketOptions extends ExtendedSocketOptions { + + NoExtendedSocketOptions() { + super(Collections.<SocketOption<?>>emptySet()); + } + + @Override + public void setOption(FileDescriptor fd, SocketOption<?> option, Object value) + throws SocketException + { + throw new UnsupportedOperationException( + "no extended options: " + option.name()); + } + + @Override + public Object getOption(FileDescriptor fd, SocketOption<?> option) + throws SocketException + { + throw new UnsupportedOperationException( + "no extended options: " + option.name()); + } + } +}
--- a/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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,7 +29,6 @@ import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; -import sun.misc.*; /**
--- a/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -39,7 +39,7 @@ import java.util.concurrent.*; import java.util.concurrent.locks.*; import sun.net.NetHooks; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; /** * Base implementation of AsynchronousSocketChannel @@ -512,9 +512,9 @@ set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.TCP_NODELAY); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } }
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -33,7 +33,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.ResourceManager; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; /** * An implementation of DatagramChannels. @@ -306,9 +306,9 @@ set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_LOOP); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } }
--- a/src/java.base/share/classes/sun/nio/ch/Net.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/Net.java Thu Apr 28 23:08:17 2016 -0700 @@ -27,15 +27,13 @@ import java.io.*; import java.net.*; -import jdk.net.*; import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; import sun.security.action.GetPropertyAction; - public class Net { private Net() { } @@ -281,6 +279,9 @@ // -- Socket options + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + static void setSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOption<?> name, Object value) throws IOException @@ -291,12 +292,8 @@ // only simple values supported by this method Class<?> type = name.type(); - if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA")); - } - ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value); + if (extendedOptions.isOptionSupported(name)) { + extendedOptions.setOption(fd, name, value); return; } @@ -353,14 +350,8 @@ { Class<?> type = name.type(); - if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA")); - } - SocketFlow flow = SocketFlow.create(); - ExtendedOptionsImpl.getFlowOption(fd, flow); - return flow; + if (extendedOptions.isOptionSupported(name)) { + return extendedOptions.getOption(fd, name); } // only simple values supported by this method
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -33,8 +33,7 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; -import sun.net.ExtendedOptionsImpl; - +import sun.net.ext.ExtendedSocketOptions; /** * An implementation of SocketChannels @@ -242,9 +241,9 @@ // additional options required by socket adaptor set.add(StandardSocketOptions.IP_TOS); set.add(ExtendedSocketOption.SO_OOBINLINE); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } }
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -209,6 +209,12 @@ Collection<SNIMatcher> sniMatchers = Collections.<SNIMatcher>emptyList(); + // Is the serverNames set to empty with SSLParameters.setServerNames()? + private boolean noSniExtension = false; + + // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()? + private boolean noSniMatcher = false; + // Configured application protocol values String[] applicationProtocols = new String[0]; @@ -642,6 +648,11 @@ } super.connect(endpoint, timeout); + + if (host == null || host.length() == 0) { + useImplicitHost(false); + } + doneConnect(); } @@ -2098,41 +2109,62 @@ outputRecord.setVersion(protocolVersion); } + // + // ONLY used by ClientHandshaker for the server hostname during handshaking + // synchronized String getHost() { // Note that the host may be null or empty for localhost. if (host == null || host.length() == 0) { - if (!trustNameService) { - // If the local name service is not trustworthy, reverse host - // name resolution should not be performed for endpoint - // identification. Use the application original specified - // hostname or IP address instead. - host = getOriginalHostname(getInetAddress()); - } else { - host = getInetAddress().getHostName(); - } + useImplicitHost(true); } return host; } /* - * Get the original application specified hostname. + * Try to set and use the implicit specified hostname */ - private static String getOriginalHostname(InetAddress inetAddress) { - /* - * Get the original hostname via jdk.internal.misc.SharedSecrets. - */ - JavaNetInetAddressAccess jna = SharedSecrets.getJavaNetInetAddressAccess(); - String originalHostname = jna.getOriginalHostName(inetAddress); + private synchronized void useImplicitHost(boolean noSniUpdate) { - /* - * If no application specified hostname, use the IP address. - */ - if (originalHostname == null || originalHostname.length() == 0) { - originalHostname = inetAddress.getHostAddress(); + // Note: If the local name service is not trustworthy, reverse + // host name resolution should not be performed for endpoint + // identification. Use the application original specified + // hostname or IP address instead. + + // Get the original hostname via jdk.internal.misc.SharedSecrets + InetAddress inetAddress = getInetAddress(); + if (inetAddress == null) { // not connected + return; } - return originalHostname; + JavaNetInetAddressAccess jna = + SharedSecrets.getJavaNetInetAddressAccess(); + String originalHostname = jna.getOriginalHostName(inetAddress); + if ((originalHostname != null) && + (originalHostname.length() != 0)) { + + host = originalHostname; + if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) { + serverNames = + Utilities.addToSNIServerNameList(serverNames, host); + + if (!roleIsServer && + (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } + } + + return; + } + + // No explicitly specified hostname, no server name indication. + if (!trustNameService) { + // The local name service is not trustworthy, use IP address. + host = inetAddress.getHostAddress(); + } else { + // Use the underlying reverse host name resolution service. + host = getInetAddress().getHostName(); + } } // ONLY used by HttpsClient to setup the URI specified hostname @@ -2144,6 +2176,10 @@ this.host = host; this.serverNames = Utilities.addToSNIServerNameList(this.serverNames, this.host); + + if (!roleIsServer && (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } } /** @@ -2533,8 +2569,21 @@ // the super implementation does not handle the following parameters params.setEndpointIdentificationAlgorithm(identificationProtocol); params.setAlgorithmConstraints(algorithmConstraints); - params.setSNIMatchers(sniMatchers); - params.setServerNames(serverNames); + + if (sniMatchers.isEmpty() && !noSniMatcher) { + // 'null' indicates none has been set + params.setSNIMatchers(null); + } else { + params.setSNIMatchers(sniMatchers); + } + + if (serverNames.isEmpty() && !noSniExtension) { + // 'null' indicates none has been set + params.setServerNames(null); + } else { + params.setServerNames(serverNames); + } + params.setUseCipherSuitesOrder(preferLocalCipherSuites); params.setMaximumPacketSize(maximumPacketSize); params.setApplicationProtocols(applicationProtocols); @@ -2568,11 +2617,13 @@ List<SNIServerName> sniNames = params.getServerNames(); if (sniNames != null) { + noSniExtension = sniNames.isEmpty(); serverNames = sniNames; } Collection<SNIMatcher> matchers = params.getSNIMatchers(); if (matchers != null) { + noSniMatcher = matchers.isEmpty(); sniMatchers = matchers; }
--- a/src/java.base/share/classes/sun/util/logging/PlatformLogger.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/classes/sun/util/logging/PlatformLogger.java Thu Apr 28 23:08:17 2016 -0700 @@ -286,12 +286,15 @@ } if (log == null) { log = new PlatformLogger(PlatformLogger.Bridge.convert( - // We pass PlatformLogger.class rather than the actual caller + // We pass PlatformLogger.class.getModule() (java.base) + // rather than the actual module of the caller // because we want PlatformLoggers to be system loggers: we // won't need to resolve any resource bundles anyway. // Note: Many unit tests depend on the fact that - // PlatformLogger.getLoggerFromFinder is not caller sensitive. - LazyLoggers.getLazyLogger(name, PlatformLogger.class))); + // PlatformLogger.getLoggerFromFinder is not caller + // sensitive, and this strategy ensure that the tests + // still pass. + LazyLoggers.getLazyLogger(name, PlatformLogger.class.getModule()))); loggers.put(name, new WeakReference<>(log)); } return log;
--- a/src/java.base/share/native/libjimage/jimage.cpp Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/native/libjimage/jimage.cpp Thu Apr 28 23:08:17 2016 -0700 @@ -207,7 +207,30 @@ if (!(*visitor)(image, module, "9", parent, base, extension, arg)) { break; } - } } +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max) { + ImageFileReader* imageFile = (ImageFileReader*) image; + + u4 offset = (u4) locationRef; + if (offset >= imageFile->locations_size()) { + return false; + } + + ImageLocation location(imageFile->get_location_offset_data(offset)); + imageFile->location_path(location, path, max); + + return true; +}
--- a/src/java.base/share/native/libjimage/jimage.hpp Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/share/native/libjimage/jimage.hpp Thu Apr 28 23:08:17 2016 -0700 @@ -37,11 +37,13 @@ typedef jlong JImageLocationRef; // Max path length limit independent of platform. Windows max path is 1024, -// other platforms use 4096. The JCK fails several tests when 1024 is used. +// other platforms use 4096. #define JIMAGE_MAX_PATH 4096 // JImage Error Codes +// Resource was not found +#define JIMAGE_NOT_FOUND (0) // The image file is not prefixed with 0xCAFEDADA #define JIMAGE_BAD_MAGIC (-1) // The image file does not have a compatible (translatable) version @@ -184,3 +186,20 @@ typedef void (*JImageResourceIterator_t)(JImageFile* jimage, JImageResourceVisitor_t visitor, void* arg); + +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max); + +typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); +
--- a/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -27,9 +27,7 @@ import java.io.IOException; import java.util.Set; import java.util.HashSet; -import java.util.Collections; -import jdk.net.*; -import static sun.net.ExtendedOptionsImpl.*; +import sun.net.ext.ExtendedSocketOptions; /* * On Unix systems we simply delegate to native methods. @@ -43,8 +41,11 @@ init(); } + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + protected <T> void setOption(SocketOption<T> name, T value) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { super.setOption(name, value); } else { @@ -55,21 +56,16 @@ } } } else { - if (!flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } if (isClosed()) { throw new SocketException("Socket closed"); } - checkSetOptionPermission(name); - checkValueType(value, SocketFlow.class); - setFlowOption(getFileDescriptor(), (SocketFlow)value); + extendedOptions.setOption(fd, name, value); } } @SuppressWarnings("unchecked") protected <T> T getOption(SocketOption<T> name) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { return super.getOption(name); } else { @@ -79,31 +75,23 @@ throw new UnsupportedOperationException("unsupported option"); } } + } else { + if (isClosed()) { + throw new SocketException("Socket closed"); + } + return (T) extendedOptions.getOption(fd, name); } - if (!flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosed()) { - throw new SocketException("Socket closed"); - } - checkGetOptionPermission(name); - SocketFlow flow = SocketFlow.create(); - getFlowOption(getFileDescriptor(), flow); - return (T)flow; } protected Set<SocketOption<?>> supportedOptions() { - HashSet<SocketOption<?>> options = new HashSet<>( - super.supportedOptions()); - - if (flowSupported()) { - options.add(ExtendedSocketOptions.SO_FLOW_SLA); - } + HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions()); + options.addAll(extendedOptions.options()); return options; } protected void socketSetOption(int opt, Object val) throws SocketException { - if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + if (opt == SocketOptions.SO_REUSEPORT && + !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { throw new UnsupportedOperationException("unsupported option"); } try {
--- a/src/java.base/unix/classes/java/net/PlainSocketImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/unix/classes/java/net/PlainSocketImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -28,10 +28,7 @@ import java.io.FileDescriptor; import java.util.Set; import java.util.HashSet; -import java.util.Collections; -import jdk.net.*; - -import static sun.net.ExtendedOptionsImpl.*; +import sun.net.ext.ExtendedSocketOptions; /* * On Unix systems we simply delegate to native methods. @@ -57,8 +54,11 @@ this.fd = fd; } + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + protected <T> void setOption(SocketOption<T> name, T value) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { super.setOption(name, value); } else { @@ -69,21 +69,19 @@ } } } else { - if (getSocket() == null || !flowSupported()) { + if (getSocket() == null) { throw new UnsupportedOperationException("unsupported option"); } if (isClosedOrPending()) { throw new SocketException("Socket closed"); } - checkSetOptionPermission(name); - checkValueType(value, SocketFlow.class); - setFlowOption(getFileDescriptor(), (SocketFlow)value); + extendedOptions.setOption(fd, name, value); } } @SuppressWarnings("unchecked") protected <T> T getOption(SocketOption<T> name) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { return super.getOption(name); } else { @@ -93,31 +91,28 @@ throw new UnsupportedOperationException("unsupported option"); } } + } else { + if (getSocket() == null) { + throw new UnsupportedOperationException("unsupported option"); + } + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + return (T) extendedOptions.getOption(fd, name); } - if (getSocket() == null || !flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosedOrPending()) { - throw new SocketException("Socket closed"); - } - checkGetOptionPermission(name); - SocketFlow flow = SocketFlow.create(); - getFlowOption(getFileDescriptor(), flow); - return (T)flow; } protected Set<SocketOption<?>> supportedOptions() { - HashSet<SocketOption<?>> options = new HashSet<>( - super.supportedOptions()); - - if (getSocket() != null && flowSupported()) { - options.add(ExtendedSocketOptions.SO_FLOW_SLA); + HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions()); + if (getSocket() != null) { + options.addAll(extendedOptions.options()); } return options; } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { - if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + if (opt == SocketOptions.SO_REUSEPORT && + !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { throw new UnsupportedOperationException("unsupported option"); } try {
--- a/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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,7 +29,6 @@ import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; -import sun.misc.*; /**
--- a/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#include <jni.h> -#include <string.h> - -#include "net_util.h" -#include "jdk_net_SocketFlow.h" - -static jclass sf_status_class; /* Status enum type */ - -static jfieldID sf_status; -static jfieldID sf_priority; -static jfieldID sf_bandwidth; - -static jfieldID sf_fd_fdID; /* FileDescriptor.fd */ - -/* References to the literal enum values */ - -static jobject sfs_NOSTATUS; -static jobject sfs_OK; -static jobject sfs_NOPERMISSION; -static jobject sfs_NOTCONNECTED; -static jobject sfs_NOTSUPPORTED; -static jobject sfs_ALREADYCREATED; -static jobject sfs_INPROGRESS; -static jobject sfs_OTHER; - -static jobject getEnumField(JNIEnv *env, char *name); -static void setStatus(JNIEnv *env, jobject obj, int errval); - -/* OS specific code is implemented in these three functions */ - -static jboolean flowSupported0() ; - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: init - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init - (JNIEnv *env, jclass UNUSED) -{ - static int initialized = 0; - jclass c; - - /* Global class references */ - - if (initialized) { - return; - } - - c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status"); - CHECK_NULL(c); - sf_status_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL(sf_status_class); - - /* int "fd" field of java.io.FileDescriptor */ - - c = (*env)->FindClass(env, "java/io/FileDescriptor"); - CHECK_NULL(c); - sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I"); - CHECK_NULL(sf_fd_fdID); - - - /* SocketFlow fields */ - - c = (*env)->FindClass(env, "jdk/net/SocketFlow"); - CHECK_NULL(c); - - /* status */ - - sf_status = (*env)->GetFieldID(env, c, "status", - "Ljdk/net/SocketFlow$Status;"); - CHECK_NULL(sf_status); - - /* priority */ - - sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); - CHECK_NULL(sf_priority); - - /* bandwidth */ - - sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); - CHECK_NULL(sf_bandwidth); - - /* Initialize the static enum values */ - - sfs_NOSTATUS = getEnumField(env, "NO_STATUS"); - CHECK_NULL(sfs_NOSTATUS); - sfs_OK = getEnumField(env, "OK"); - CHECK_NULL(sfs_OK); - sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION"); - CHECK_NULL(sfs_NOPERMISSION); - sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED"); - CHECK_NULL(sfs_NOTCONNECTED); - sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED"); - CHECK_NULL(sfs_NOTSUPPORTED); - sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED"); - CHECK_NULL(sfs_ALREADYCREATED); - sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS"); - CHECK_NULL(sfs_INPROGRESS); - sfs_OTHER = getEnumField(env, "OTHER"); - CHECK_NULL(sfs_OTHER); - initialized = JNI_TRUE; -} - -static jobject getEnumField(JNIEnv *env, char *name) -{ - jobject f; - jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name, - "Ljdk/net/SocketFlow$Status;"); - CHECK_NULL_RETURN(fID, NULL); - - f = (*env)->GetStaticObjectField(env, sf_status_class, fID); - CHECK_NULL_RETURN(f, NULL); - f = (*env)->NewGlobalRef(env, f); - CHECK_NULL_RETURN(f, NULL); - return f; -} - -/* - * Retrieve the int file-descriptor from a public socket type object. - * Gets impl, then the FileDescriptor from the impl, and then the fd - * from that. - */ -static int getFD(JNIEnv *env, jobject fileDesc) { - return (*env)->GetIntField(env, fileDesc, sf_fd_fdID); -} - -/** - * Sets the status field of a SocketFlow to one of the - * canned enum values - */ -static void setStatus (JNIEnv *env, jobject obj, int errval) -{ - switch (errval) { - case 0: /* OK */ - (*env)->SetObjectField(env, obj, sf_status, sfs_OK); - break; - case EPERM: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION); - break; - case ENOTCONN: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED); - break; - case EOPNOTSUPP: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED); - break; - case EALREADY: - (*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED); - break; - case EINPROGRESS: - (*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS); - break; - default: - (*env)->SetObjectField(env, obj, sf_status, sfs_OTHER); - break; - } -} - -#ifdef __solaris__ - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: setFlowOption - * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - sock_flow_props_t props; - jlong bandwidth; - int rv; - - jint priority = (*env)->GetIntField(env, flow, sf_priority); - memset(&props, 0, sizeof(props)); - props.sfp_version = SOCK_FLOW_PROP_VERSION1; - - if (priority != jdk_net_SocketFlow_UNSET) { - props.sfp_mask |= SFP_PRIORITY; - props.sfp_priority = priority; - } - bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth); - if (bandwidth > -1) { - props.sfp_mask |= SFP_MAXBW; - props.sfp_maxbw = (uint64_t) bandwidth; - } - rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); - if (rv < 0) { - if (errno == ENOPROTOOPT) { - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); - } else if (errno == EACCES || errno == EPERM) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "Permission denied"); - } else { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "set option SO_FLOW_SLA failed"); - } - return; - } - setStatus(env, flow, props.sfp_status); - } -} - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: getFlowOption - * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - sock_flow_props_t props; - int status; - socklen_t sz = sizeof(props); - - int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); - if (rv < 0) { - if (errno == ENOPROTOOPT) { - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); - } else if (errno == EACCES || errno == EPERM) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "Permission denied"); - } else { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "set option SO_FLOW_SLA failed"); - } - return; - } - /* first check status to see if flow exists */ - status = props.sfp_status; - setStatus(env, flow, status); - if (status == 0) { /* OK */ - /* can set the other fields now */ - if (props.sfp_mask & SFP_PRIORITY) { - (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); - } - if (props.sfp_mask & SFP_MAXBW) { - (*env)->SetLongField(env, flow, sf_bandwidth, - (jlong)props.sfp_maxbw); - } - } - } -} - -static jboolean flowsupported; -static jboolean flowsupported_set = JNI_FALSE; - -static jboolean flowSupported0() -{ - /* Do a simple dummy call, and try to figure out from that */ - sock_flow_props_t props; - int rv, s; - if (flowsupported_set) { - return flowsupported; - } - s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (s < 0) { - flowsupported = JNI_FALSE; - flowsupported_set = JNI_TRUE; - return JNI_FALSE; - } - memset(&props, 0, sizeof(props)); - props.sfp_version = SOCK_FLOW_PROP_VERSION1; - props.sfp_mask |= SFP_PRIORITY; - props.sfp_priority = SFP_PRIO_NORMAL; - rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); - if (rv != 0 && errno == ENOPROTOOPT) { - rv = JNI_FALSE; - } else { - rv = JNI_TRUE; - } - close(s); - flowsupported = rv; - flowsupported_set = JNI_TRUE; - return flowsupported; -} - -#else /* __solaris__ */ - -/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -static jboolean flowSupported0() { - return JNI_FALSE; -} - -#endif /* __solaris__ */ - -JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported - (JNIEnv *env, jclass UNUSED) -{ - return flowSupported0(); -}
--- a/src/java.base/unix/native/libnet/net_util_md.h Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.base/unix/native/libnet/net_util_md.h Thu Apr 28 23:08:17 2016 -0700 @@ -120,47 +120,6 @@ #ifdef __solaris__ int net_getParam(char *driver, char *param); - -#ifndef SO_FLOW_SLA -#define SO_FLOW_SLA 0x1018 - -#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 -#pragma pack(4) #endif -/* - * Used with the setsockopt(SO_FLOW_SLA, ...) call to set - * per socket service level properties. - * When the application uses per-socket API, we will enforce the properties - * on both outbound and inbound packets. - * - * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1. - */ -typedef struct sock_flow_props_s { - int sfp_version; - uint32_t sfp_mask; - int sfp_priority; /* flow priority */ - uint64_t sfp_maxbw; /* bandwidth limit in bps */ - int sfp_status; /* flow create status for getsockopt */ -} sock_flow_props_t; - -#define SOCK_FLOW_PROP_VERSION1 1 - -/* bit mask values for sfp_mask */ -#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */ -#define SFP_PRIORITY 0x00000008 /* Flow priority */ - -/* possible values for sfp_priority */ -#define SFP_PRIO_NORMAL 1 -#define SFP_PRIO_HIGH 2 - -#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 -#pragma pack() -#endif /* _LONG_LONG_ALIGNMENT */ - -#endif /* SO_FLOW_SLA */ -#endif /* __solaris__ */ - -JNIEXPORT jboolean JNICALL NET_IsFlowSupported(); - #endif /* NET_UTILS_MD_H */
--- a/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#include <jni.h> -#include <string.h> - -#include "net_util.h" - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: init - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init - (JNIEnv *env, jclass UNUSED) -{ -} - -/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -static jboolean flowSupported0() { - return JNI_FALSE; -} - -JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported - (JNIEnv *env, jclass UNUSED) -{ - return JNI_FALSE; -}
--- a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java Thu Apr 28 23:08:17 2016 -0700 @@ -52,7 +52,6 @@ import sun.awt.datatransfer.DataTransferer; import sun.font.FontConfigManager; import sun.java2d.SunGraphicsEnvironment; -import sun.misc.*; import sun.awt.util.PerformanceLogger; import sun.awt.util.ThreadGroupUtils; import sun.print.PrintJob2D;
--- a/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c Thu Apr 28 23:08:17 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -72,8 +72,8 @@ #include <dlfcn.h> -#if defined(__solaris__) || defined(_AIX) -/* Solaris 10 and AIX will not have these symbols at runtime */ +#if defined(__solaris__) +/* Solaris 10 will not have these symbols at compile time */ typedef Picture (*XRenderCreateLinearGradientFuncType) (Display *dpy, @@ -147,7 +147,22 @@ return JNI_FALSE; } -#if defined(__solaris__) || defined(_AIX) +#if defined(_AIX) + // On AIX we have to use a special syntax because the shared libraries are packed in + // multi-architecture archives. We first try to load the system default libXrender + // which is contained in the 'X11.base.lib' fileset starting with AIX 6.1 + xrenderlib = dlopen("libXrender.a(shr_64.o)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER); + if (xrenderlib == NULL) { + // If the latter wasn't successful, we also try to load the version under /opt/freeware + // This may be downloaded from the "AIX Toolbox for Linux Applications" even for AIX 5.3 + xrenderlib = dlopen("libXrender.a(libXrender.so.0)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER); + } + if (xrenderlib != NULL) { + dlclose(xrenderlib); + } else { + available = JNI_FALSE; + } +#elif defined(__solaris__) xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY); if (xrenderlib != NULL) {
--- a/src/java.logging/share/classes/java/util/logging/LogManager.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.logging/share/classes/java/util/logging/LogManager.java Thu Apr 28 23:08:17 2016 -0700 @@ -43,6 +43,8 @@ import jdk.internal.misc.JavaAWTAccess; import jdk.internal.misc.SharedSecrets; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; +import static jdk.internal.logger.DefaultLoggerFinder.isSystem; /** * There is a single global LogManager object that is used to @@ -503,10 +505,16 @@ // as a LogManager subclass may override the addLogger, getLogger, // readConfiguration, and other methods. Logger demandLogger(String name, String resourceBundleName, Class<?> caller) { + final Module module = caller == null ? null : caller.getModule(); + return demandLogger(name, resourceBundleName, module); + } + + Logger demandLogger(String name, String resourceBundleName, Module module) { Logger result = getLogger(name); if (result == null) { // only allocate the new logger once - Logger newLogger = new Logger(name, resourceBundleName, caller, this, false); + Logger newLogger = new Logger(name, resourceBundleName, + module == null ? null : module, this, false); do { if (addLogger(newLogger)) { // We successfully added the new Logger that we @@ -532,9 +540,14 @@ } Logger demandSystemLogger(String name, String resourceBundleName, Class<?> caller) { + final Module module = caller == null ? null : caller.getModule(); + return demandSystemLogger(name, resourceBundleName, module); + } + + Logger demandSystemLogger(String name, String resourceBundleName, Module module) { // Add a system logger in the system context's namespace final Logger sysLogger = getSystemContext() - .demandLogger(name, resourceBundleName, caller); + .demandLogger(name, resourceBundleName, module); // Add the system logger to the LogManager's namespace if not exist // so that there is only one single logger of the given name. @@ -619,11 +632,11 @@ return global; } - Logger demandLogger(String name, String resourceBundleName, Class<?> caller) { + Logger demandLogger(String name, String resourceBundleName, Module module) { // a LogManager subclass may have its own implementation to add and // get a Logger. So delegate to the LogManager to do the work. final LogManager owner = getOwner(); - return owner.demandLogger(name, resourceBundleName, caller); + return owner.demandLogger(name, resourceBundleName, module); } @@ -907,11 +920,13 @@ // one single logger of the given name. System loggers are visible // to applications unless a logger of the same name has been added. @Override - Logger demandLogger(String name, String resourceBundleName, Class<?> caller) { + Logger demandLogger(String name, String resourceBundleName, + Module module) { Logger result = findLogger(name); if (result == null) { // only allocate the new system logger once - Logger newLogger = new Logger(name, resourceBundleName, caller, getOwner(), true); + Logger newLogger = new Logger(name, resourceBundleName, + module, getOwner(), true); do { if (addLocalLogger(newLogger)) { // We successfully added the new Logger that we @@ -2622,18 +2637,18 @@ } /** - * Demands a logger on behalf of the given {@code caller}. + * Demands a logger on behalf of the given {@code module}. * <p> - * If a named logger suitable for the given caller is found + * If a named logger suitable for the given module is found * returns it. - * Otherwise, creates a new logger suitable for the given caller. + * Otherwise, creates a new logger suitable for the given module. * * @param name The logger name. - * @param caller The caller on which behalf the logger is created/retrieved. - * @return A logger for the given {@code caller}. + * @param module The module on which behalf the logger is created/retrieved. + * @return A logger for the given {@code module}. * * @throws NullPointerException if {@code name} is {@code null} - * or {@code caller} is {@code null}. + * or {@code module} is {@code null}. * @throws IllegalArgumentException if {@code manager} is not the default * LogManager. * @throws SecurityException if a security manager is present and the @@ -2641,7 +2656,7 @@ * {@link LoggingPermission LoggingPermission("demandLogger", null)}. */ @Override - public Logger demandLoggerFor(LogManager manager, String name, /* Module */ Class<?> caller) { + public Logger demandLoggerFor(LogManager manager, String name, Module module) { if (manager != getLogManager()) { // having LogManager as parameter just ensures that the // caller will have initialized the LogManager before reaching @@ -2649,15 +2664,16 @@ throw new IllegalArgumentException("manager"); } Objects.requireNonNull(name); + Objects.requireNonNull(module); SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(controlPermission); } - if (caller.getClassLoader() == null) { + if (isSystem(module)) { return manager.demandSystemLogger(name, - Logger.SYSTEM_LOGGER_RB_NAME, caller); + Logger.SYSTEM_LOGGER_RB_NAME, module); } else { - return manager.demandLogger(name, null, caller); + return manager.demandLogger(name, null, module); } }
--- a/src/java.logging/share/classes/java/util/logging/Logger.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.logging/share/classes/java/util/logging/Logger.java Thu Apr 28 23:08:17 2016 -0700 @@ -40,6 +40,7 @@ import java.util.function.Supplier; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import static jdk.internal.logger.DefaultLoggerFinder.isSystem; /** * A Logger object is used to log messages for a specific @@ -379,7 +380,8 @@ this(name, resourceBundleName, null, LogManager.getLogManager(), false); } - Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager, boolean isSystemLogger) { + Logger(String name, String resourceBundleName, Module caller, + LogManager manager, boolean isSystemLogger) { this.manager = manager; this.isSystemLogger = isSystemLogger; setupResourceInfo(resourceBundleName, caller); @@ -387,10 +389,7 @@ levelValue = Level.INFO.intValue(); } - private void setCallerModuleRef(Class<?> caller) { - Module callerModule = ((caller != null) - ? caller.getModule() - : null); + private void setCallerModuleRef(Module callerModule) { if (callerModule != null) { this.callerModuleRef = new WeakReference<>(callerModule); } @@ -618,7 +617,7 @@ // all loggers in the system context will default to // the system logger's resource bundle - therefore the caller won't // be needed and can be null. - Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, null); + Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, (Module)null); return result; } @@ -681,8 +680,10 @@ LogManager manager = LogManager.getLogManager(); // cleanup some Loggers that have been GC'ed manager.drainLoggerRefQueueBounded(); + final Class<?> callerClass = Reflection.getCallerClass(); + final Module module = callerClass.getModule(); Logger result = new Logger(null, resourceBundleName, - Reflection.getCallerClass(), manager, false); + module, manager, false); result.anonymous = true; Logger root = manager.getLogger(""); result.doSetParent(root); @@ -2046,6 +2047,11 @@ } } + private void setupResourceInfo(String name, Class<?> caller) { + final Module module = caller == null ? null : caller.getModule(); + setupResourceInfo(name, module); + } + // Private utility method to initialize our one entry // resource bundle name cache and the callers Module // Note: for consistency reasons, we are careful to check @@ -2053,7 +2059,7 @@ // resourceBundleName field. // Synchronized to prevent races in setting the fields. private synchronized void setupResourceInfo(String name, - Class<?> callerClass) { + Module callerModule) { final LoggerBundle lb = loggerBundle; if (lb.resourceBundleName != null) { // this Logger already has a ResourceBundle @@ -2072,8 +2078,9 @@ return; } - setCallerModuleRef(callerClass); - if (isSystemLogger && (callerClass != null && callerClass.getClassLoader() != null)) { + setCallerModuleRef(callerModule); + + if (isSystemLogger && (callerModule != null && !isSystem(callerModule))) { checkPermission(); }
--- a/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -32,6 +32,7 @@ import java.util.function.Supplier; import java.lang.System.LoggerFinder; import java.lang.System.Logger; +import java.lang.reflect.Module; import java.util.Objects; import java.util.logging.LogManager; import jdk.internal.logger.DefaultLoggerFinder; @@ -398,21 +399,20 @@ } /** - * Creates a java.util.logging.Logger for the given caller. + * Creates a java.util.logging.Logger for the given module. * @param name the logger name. - * @param caller the caller for which the logger should be created. - * @return a Logger suitable for use in the given caller. + * @param module the module for which the logger should be created. + * @return a Logger suitable for use in the given module. */ private static java.util.logging.Logger demandJULLoggerFor(final String name, - /* Module */ - final Class<?> caller) { + Module module) { final LogManager manager = LogManager.getLogManager(); final SecurityManager sm = System.getSecurityManager(); if (sm == null) { - return logManagerAccess.demandLoggerFor(manager, name, caller); + return logManagerAccess.demandLoggerFor(manager, name, module); } else { final PrivilegedAction<java.util.logging.Logger> pa = - () -> logManagerAccess.demandLoggerFor(manager, name, caller); + () -> logManagerAccess.demandLoggerFor(manager, name, module); return AccessController.doPrivileged(pa, null, LOGGING_CONTROL_PERMISSION); } } @@ -429,17 +429,17 @@ * {@code RuntimePermission("loggerFinder")}. */ @Override - protected Logger demandLoggerFor(String name, /* Module */ Class<?> caller) { + protected Logger demandLoggerFor(String name, Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); } - return JULWrapper.of(demandJULLoggerFor(name,caller)); + return JULWrapper.of(demandJULLoggerFor(name,module)); } public static interface LogManagerAccess { java.util.logging.Logger demandLoggerFor(LogManager manager, - String name, /* Module */ Class<?> caller); + String name, Module module); } // Hook for tests
--- a/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java Thu Apr 28 23:08:17 2016 -0700 @@ -257,11 +257,11 @@ * delegate to the {@link com.sun.jdi.connect.spi.TransportService#description() * description()} method of the underlying transport service. Both * the AttachingConnector and the ListeningConnector will have two - * Connector {@link com.sun.jdi.connect.Connector$Argument Arguments}. - * A {@link com.sun.jdi.connect.Connector$StringArgument StringArgument} + * Connector {@link com.sun.jdi.connect.Connector.Argument Arguments}. + * A {@link com.sun.jdi.connect.Connector.StringArgument StringArgument} * named {@code address} is the connector argument to specify the * address to attach too, or to listen on. A - * {@link com.sun.jdi.connect.Connector$IntegerArgument IntegerArgument} + * {@link com.sun.jdi.connect.Connector.IntegerArgument IntegerArgument} * named {@code timeout} is the connector argument to specify the * timeout when attaching, or accepting. The timeout connector may be * ignored depending on if the transport service supports an attach
--- a/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ -package jdk.tools.jimage; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Consumer; -import jdk.tools.jlink.internal.ImageFileCreator; -import jdk.tools.jlink.internal.Archive; -import jdk.tools.jlink.internal.ImagePluginStack; -import jdk.tools.jlink.internal.DirArchive; -/** - * - * Support for extracted image. - */ -public final class ExtractedImage { - - private Set<Archive> archives = new HashSet<>(); - private final ImagePluginStack plugins; - - ExtractedImage(Path dirPath, ImagePluginStack plugins, PrintWriter log, - boolean verbose) throws IOException { - if (!Files.isDirectory(dirPath)) { - throw new IOException("Not a directory"); - } - Consumer<String> cons = (String t) -> { - if (verbose) { - log.println(t); - } - }; - this.plugins = plugins; - Files.walk(dirPath, 1).forEach((p) -> { - if (!dirPath.equals(p)) { - if (Files.isDirectory(p)) { - Archive a = new DirArchive(p, cons); - archives.add(a); - } - } - }); - archives = Collections.unmodifiableSet(archives); - } - - void recreateJImage(Path path) throws IOException { - ImageFileCreator.recreateJimage(path, archives, plugins); - } - - private static String getPathName(Path path) { - return path.toString().replace(File.separatorChar, '/'); - } -}
--- a/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java Thu Apr 28 23:08:17 2016 -0700 @@ -32,7 +32,6 @@ import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.file.Files; -import java.nio.file.Path; import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.WRITE; import java.util.LinkedList; @@ -44,8 +43,6 @@ import static jdk.internal.jimage.ImageHeader.MINOR_VERSION; import jdk.internal.jimage.ImageLocation; import jdk.tools.jlink.internal.ImageResourcesTree; -import jdk.tools.jlink.internal.ImagePluginConfiguration; -import jdk.tools.jlink.internal.ImagePluginStack; import jdk.tools.jlink.internal.TaskHelper; import jdk.tools.jlink.internal.TaskHelper.BadArgs; import static jdk.tools.jlink.internal.TaskHelper.JIMAGE_BUNDLE; @@ -97,7 +94,6 @@ EXTRACT, INFO, LIST, - RECREATE, SET, VERIFY }; @@ -152,21 +148,28 @@ setLog(new PrintWriter(System.out)); } + if (args.length == 0) { + log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); + return EXIT_ABNORMAL; + } + try { List<String> unhandled = optionsHelper.handleOptions(this, args); if(!unhandled.isEmpty()) { - options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + try { + options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + } catch (IllegalArgumentException ex) { + throw taskHelper.newBadArgs("err.not.a.task", unhandled.get(0)); + } for(int i = 1; i < unhandled.size(); i++) { options.jimages.add(new File(unhandled.get(i))); } + } else { + throw taskHelper.newBadArgs("err.not.a.task", "<unspecified>"); } if (options.help) { optionsHelper.showHelp(PROGNAME); } - if(optionsHelper.listPlugins()) { - optionsHelper.listPlugins(true); - return EXIT_OK; - } if (options.version || options.fullVersion) { taskHelper.showVersion(options.fullVersion); } @@ -186,49 +189,19 @@ } } - private void recreate() throws Exception, BadArgs { - File directory = new File(options.directory); - if (!directory.isDirectory()) { - throw taskHelper.newBadArgs("err.not.a.dir", directory.getAbsolutePath()); - } - Path dirPath = directory.toPath(); - if (options.jimages.isEmpty()) { - throw taskHelper.newBadArgs("err.jimage.not.specified"); - } else if (options.jimages.size() != 1) { - throw taskHelper.newBadArgs("err.only.one.jimage"); - } - - Path jimage = options.jimages.get(0).toPath(); - - if (jimage.toFile().createNewFile()) { - ImagePluginStack pc = ImagePluginConfiguration.parseConfiguration(taskHelper. - getPluginsConfig(null, false)); - ExtractedImage img = new ExtractedImage(dirPath, pc, log, options.verbose); - img.recreateJImage(jimage); - } else { - throw taskHelper.newBadArgs("err.jimage.already.exists", jimage.getFileName()); - } - } - - private void title(File file, BasicImageReader reader) { - log.println("jimage: " + file.getName()); - } - private void listTitle(File file, BasicImageReader reader) { - title(file, reader); - - if (options.verbose) { - log.print(pad("Offset", OFFSET_WIDTH + 1)); - log.print(pad("Size", SIZE_WIDTH + 1)); - log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH + 1)); - log.println(" Entry"); - } + log.println("jimage: " + file); } private interface JImageAction { public void apply(File file, BasicImageReader reader) throws IOException, BadArgs; } + private interface ModuleAction { + public void apply(BasicImageReader reader, + String oldModule, String newModule) throws IOException, BadArgs; + } + private interface ResourceAction { public void apply(BasicImageReader reader, String name, ImageLocation location) throws IOException, BadArgs; @@ -254,23 +227,32 @@ } } - private static final int NUMBER_WIDTH = 12; - private static final int OFFSET_WIDTH = NUMBER_WIDTH; - private static final int SIZE_WIDTH = NUMBER_WIDTH; - private static final int COMPRESSEDSIZE_WIDTH = NUMBER_WIDTH; + private static final int OFFSET_WIDTH = 12; + private static final int SIZE_WIDTH = 10; + private static final int COMPRESSEDSIZE_WIDTH = 10; - private void print(String entry, ImageLocation location) { + private String trimModule(String name) { + int offset = name.indexOf('/', 1); + + if (offset != -1 && offset + 1 < name.length()) { + return name.substring(offset + 1); + } + + return name; + } + + private void print(String name, ImageLocation location) { log.print(pad(location.getContentOffset(), OFFSET_WIDTH) + " "); log.print(pad(location.getUncompressedSize(), SIZE_WIDTH) + " "); log.print(pad(location.getCompressedSize(), COMPRESSEDSIZE_WIDTH) + " "); - log.println(entry); + log.println(trimModule(name)); } - private void print(BasicImageReader reader, String entry) { + private void print(BasicImageReader reader, String name) { if (options.verbose) { - print(entry, reader.findLocation(entry)); + print(name, reader.findLocation(name)); } else { - log.println(entry); + log.println(" " + trimModule(name)); } } @@ -289,6 +271,18 @@ log.println(" Index Size: " + header.getIndexSize()); } + private void listModule(BasicImageReader reader, String oldModule, String newModule) { + log.println(); + log.println("Module: " + newModule); + + if (options.verbose) { + log.print(pad("Offset", OFFSET_WIDTH) + " "); + log.print(pad("Size", SIZE_WIDTH) + " "); + log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH) + " "); + log.println("Entry"); + } + } + private void list(BasicImageReader reader, String name, ImageLocation location) { print(reader, name); } @@ -338,7 +332,12 @@ } private void iterate(JImageAction jimageAction, + ModuleAction moduleAction, ResourceAction resourceAction) throws IOException, BadArgs { + if (options.jimages.isEmpty()) { + throw taskHelper.newBadArgs("err.no.jimage"); + } + for (File file : options.jimages) { if (!file.exists() || !file.isFile()) { throw taskHelper.newBadArgs("err.not.a.jimage", file.getName()); @@ -351,9 +350,23 @@ if (resourceAction != null) { String[] entryNames = reader.getEntryNames(); + String oldModule = ""; for (String name : entryNames) { if (!ImageResourcesTree.isTreeInfoResource(name)) { + if (moduleAction != null) { + int offset = name.indexOf('/', 1); + + String newModule = offset != -1 ? + name.substring(1, offset) : + "<unknown>"; + + if (!oldModule.equals(newModule)) { + moduleAction.apply(reader, oldModule, newModule); + oldModule = newModule; + } + } + ImageLocation location = reader.findLocation(name); resourceAction.apply(reader, name, location); } @@ -366,22 +379,19 @@ private boolean run() throws Exception, BadArgs { switch (options.task) { case EXTRACT: - iterate(null, this::extract); + iterate(null, null, this::extract); break; case INFO: - iterate(this::info, null); + iterate(this::info, null, null); break; case LIST: - iterate(this::listTitle, this::list); - break; - case RECREATE: - recreate(); + iterate(this::listTitle, this::listModule, this::list); break; case SET: - iterate(this::set, null); + iterate(this::set, null, null); break; case VERIFY: - iterate(this::title, this::verify); + iterate(this::listTitle, null, this::verify); break; default: throw taskHelper.newBadArgs("err.invalid.task", options.task.name()).showUsage(true);
--- a/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties Thu Apr 28 00:38:21 2016 -0700 +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties Thu Apr 28 23:08:17 2016 -0700 @@ -1,30 +1,25 @@ main.usage.summary=\ -Usage: {0} <extract|info|list|recreate|set|verify> <options> jimage...\n\ +Usage: {0} <extract|info|list|set|verify> <options> jimage...\n\ use --help for a list of possible options main.usage=\ -Usage: {0} <extract|info|list|recreate|set|verify> <options> jimage...\n\ +Usage: {0} <extract|info|list|set|verify> <options> jimage...\n\ \n\ \ extract - Extract all jimage entries into separate files into the directory\n\ \ specified by --dir=<directory> (default='.')\n\ \ info - Prints information specified in the jimage header.\n\ \ list - Prints the names of all the entries in the jimage. When used with\n\ \ --verbose will also print entry attributes ex. size and offset.\n\ -\ recreate - Reconstructs a jimage from an extracted directory (--dir)\n\ \ set - sets the value of specific jimage header entries\n\ \ verify - Reports errors on any .class entries that don't verify as classes.\n\ \n\ Possible options include: -main.extended.help=\ -jimage recreate is extensible by the main of plugins. Following plugins have been discovered \ -thanks to ServiceLoader and can be used when re-creating a jimage. - error.prefix=Error: warn.prefix=Warning: main.opt.dir=\ -\ --dir Target directory for extract/recreate +\ --dir Target directory for extract main.opt.flags=\ \ --flags=value Set the jimage flags to value @@ -38,14 +33,8 @@ main.opt.version=\ \ --version Version information -main.opt.configuration=\ -\ --configuration <path> Path to properties file containing defaults\ -\ options for recreate - main.command.files=\ \ @<filename> Read options from file - -err.cannot.create.dir=cannot create directory: {0} err.cannot.read.file=cannot read file: {0} err.cannot.update.file=cannot update file: {0} err.file.not.found=cannot find file: {0} @@ -53,12 +42,11 @@ err.flags.not.int=--flags value not integer: {0} err.internal.error=internal error: {0} {1} {2} err.invalid.arg.for.option=invalid argument for option: {0} -err.invalid.task=task must be extract|recreate|info|list|verify: {0} -err.jimage.already.exists=jimage already exists: {0} -err.jimage.not.specified=no jimage specified +err.invalid.task=task must be extract|info|list|verify: {0} err.missing.arg=no value given for {0} err.not.a.dir=not a directory: {0} err.not.a.jimage=not a jimage file: {0} -err.only.one.jimage=only one jimage should be specified +err.no.jimage=no jimage provided +err.not.a.task=not a valid task: {0} err.option.unsupported={0} not supported: {1} err.unknown.option=unknown option: {0}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java Thu Apr 28 23:08:17 2016 -0700 @@ -61,24 +61,32 @@ String baseName; String extensionName = ""; - int offset = fullName.indexOf('/', 1); - if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) { - moduleName = fullName.substring(1, offset); - fullName = fullName.substring(offset + 1); - } + if (fullName.startsWith("/modules/")) { + moduleName = "modules"; + baseName = fullName.substring("/modules/".length()); + } else if ( fullName.startsWith("/packages/")) { + moduleName = "packages"; + baseName = fullName.substring("/packages/".length()); + } else { + int offset = fullName.indexOf('/', 1); + if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) { + moduleName = fullName.substring(1, offset); + fullName = fullName.substring(offset + 1); + } - offset = fullName.lastIndexOf('/'); - if (1 < offset) { - parentName = fullName.substring(0, offset); - fullName = fullName.substring(offset + 1); - } + offset = fullName.lastIndexOf('/'); + if (1 < offset) { + parentName = fullName.substring(0, offset); + fullName = fullName.substring(offset + 1); + } - offset = fullName.lastIndexOf('.'); - if (offset != -1) { - baseName = fullName.substring(0, offset); - extensionName = fullName.substring(offset + 1); - } else { - baseName = fullName; + offset = fullName.lastIndexOf('.'); + if (offset != -1) { + baseName = fullName.substring(0, offset); + extensionName = fullName.substring(offset + 1); + } else { + baseName = fullName; + } } return new ImageLocationWriter(strings)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2016, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.tools.jlink.internal.packager; + + +import jdk.tools.jlink.Jlink; +import jdk.tools.jlink.builder.ImageBuilder; +import jdk.tools.jlink.plugin.Plugin; +import jdk.tools.jlink.builder.*; +import jdk.tools.jlink.plugin.Pool; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeSet; +import java.util.stream.Collectors; + +/** + * AppRuntimeImageBuilder is a private API used only by the Java Packager to generate + * a Java runtime image using jlink. AppRuntimeImageBuilder encapsulates the + * arguments that jlink requires to generate this image. To create the image call the + * build() method. + */ +public final class AppRuntimeImageBuilder { + private Path outputDir = null; + private List<Path> modulePath = null; + private Set<String> addModules = null; + private Set<String> limitModules = null; + private String excludeFileList = null; + private Map<String, String> userArguments = null; + private Boolean stripNativeCommands = null; + + public AppRuntimeImageBuilder() {} + + public void setOutputDir(Path value) { + outputDir = value; + } + + public void setModulePath(List<Path> value) { + modulePath = value; + } + + public void setAddModules(Set<String> value) { + addModules = value; + } + + public void setLimitModules(Set<String> value) { + limitModules = value; + } + + public void setExcludeFileList(String value) { + excludeFileList = value; + } + + public void setStripNativeCommands(boolean value) { + stripNativeCommands = value; + } + + public void setUserArguments(Map<String, String> value) { + userArguments = value; + } + + public void build() throws IOException { + // jlink main arguments + Jlink.JlinkConfiguration jlinkConfig = new Jlink.JlinkConfiguration( + new File("").toPath(), // Unused + modulePath, addModules, limitModules); + + // plugin configuration + List<Plugin> plugins = new ArrayList<Plugin>(); + + if (stripNativeCommands) { + plugins.add(Jlink.newPlugin( + "strip-native-commands", + Collections.singletonMap("strip-native-commands", "on"), + null)); + } + + if (excludeFileList != null && !excludeFileList.isEmpty()) { + plugins.add(Jlink.newPlugin( + "exclude-files", + Collections.singletonMap("exclude-files", excludeFileList), + null)); + } + + // add user supplied jlink arguments + for (Map.Entry<String, String> entry : userArguments.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + plugins.add(Jlink.newPlugin(key, + Collections.singletonMap(key, value), + null)); + } + + plugins.add(Jlink.newPlugin("installed-modules", Collections.emptyMap(), null)); + + // build the image + Jlink.PluginsConfiguration pluginConfig = new Jlink.PluginsConfiguration( + plugins, new DefaultImageBuilder(true, outputDir), null); + Jlink jlink = new Jlink(); + jlink.build(jlinkConfig, pluginConfig); + } +}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java Thu Apr 28 23:08:17 2016 -0700 @@ -226,7 +226,7 @@ * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file * name}</li> * <li>For other files (shared lib, launchers, config, ...):/{module name}/ - * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li> + * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name}</li> * </ul> */ public static class ModuleData {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/module-info.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,35 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +module jdk.jstatd { + requires java.rmi; + requires jdk.jvmstat; + + // RMI needs to serialize types in this package + exports sun.jvmstat.monitor.remote to java.rmi; + + provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2004, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.jvmstat.monitor.remote; + +import sun.jvmstat.monitor.*; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.io.IOException; + +/** + * Remote Interface for discovering and attaching to remote + * monitorable Java Virtual Machines. + * + * @author Brian Doherty + * @since 1.5 + */ +public interface RemoteHost extends Remote { + + /** + * Remote method to attach to a remote HotSpot Java Virtual Machine + * identified by <code>vmid</code>. + * + * @param vmid The identifier for the target virtual machine. + * @return RemoteVm - A remote object for accessing the remote Java + * Virtual Machine. + * + * @throws MonitorException Thrown when any other error is encountered + * while communicating with the target virtual + * machine. + * @throws RemoteException + * + */ + RemoteVm attachVm(int vmid, String mode) throws RemoteException, + MonitorException; + + /** + * Remote method to detach from a remote HotSpot Java Virtual Machine + * identified by <code>vmid</code>. + * + * @param rvm The remote object for the target Java Virtual + * Machine. + * + * @throws MonitorException Thrown when any other error is encountered + * while communicating with the target virtual + * machine. + * @throws RemoteException + */ + void detachVm(RemoteVm rvm) throws RemoteException, MonitorException; + + /** + * Get a list of Local Virtual Machine Identifiers for the active + * Java Virtual Machine the remote system. A Local Virtual Machine + * Identifier is also known as an <em>lvmid</em>. + * + * @return int[] - A array of <em>lvmid</em>s. + * @throws MonitorException Thrown when any other error is encountered + * while communicating with the target virtual + * machine. + * @throws RemoteException + */ + int[] activeVms() throws RemoteException, MonitorException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.jvmstat.monitor.remote; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +/** + * Interface for accessing the instrumentation exported by a + * Java Virtual Machine running on a remote host. + * + * @author Brian Doherty + * @since 1.5 + */ +public interface RemoteVm extends Remote { + + /** + * Interface to get the bytes associated with the instrumentation + * for the remote Java Virtual Machine. + * + * @return byte[] - a byte array containing the current bytes + * for the instrumentation exported by the + * remote Java Virtual Machine. + * @throws RemoteException Thrown on any communication error + */ + byte[] getBytes() throws RemoteException; + + /** + * Interface to get the size of the instrumentation buffer + * for the target Java Virtual Machine. + * + * @return int - the size of the instrumentation buffer for the + * remote Java Virtual Machine. + * @throws RemoteException Thrown on any communication error + */ + int getCapacity() throws RemoteException; + + /** + * Interface to return the Local Virtual Machine Identifier for + * the remote Java Virtual Machine. The Local Virtual Machine + * Identifier is also know as the <em>lvmid</em>. + * + * @throws RemoteException Thrown on any communication error + */ + int getLocalVmId() throws RemoteException; + + /** + * Interface to detach from the remote Java Virtual Machine. + * + * @throws RemoteException Thrown on any communication error + */ + void detach() throws RemoteException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/package.html Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,39 @@ +<!doctype html public "-//IETF//DTD HTML/EN"> +<html> +<head> +<!-- + + + Copyright (c) 2004, 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. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the LICENSE file that accompanied this code. + + 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. + + +--> +</head> +<body bgcolor="white"> +<p> +Provides interfaces supporting remote monitoring for instrumented +HotSpot Java Virtual Machines. +</p> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2004, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.jvmstat.perfdata.monitor.protocol.rmi; + +import sun.jvmstat.monitor.*; +import sun.jvmstat.monitor.event.*; +import sun.jvmstat.monitor.remote.*; +import sun.jvmstat.perfdata.monitor.*; +import java.util.*; +import java.net.*; +import java.io.*; +import java.rmi.*; +import java.util.HashMap; + +/** + * Concrete implementation of the MonitoredHost interface for the + * <em>rmi</em> protocol of the HotSpot PerfData monitoring implementation. + * + * @author Brian Doherty + * @since 1.5 + */ +public class MonitoredHostProvider extends MonitoredHost { + private static final String serverName = "/JStatRemoteHost"; + private static final int DEFAULT_POLLING_INTERVAL = 1000; + + private ArrayList<HostListener> listeners; + private NotifierTask task; + private HashSet<Integer> activeVms; + private RemoteVmManager vmManager; + private RemoteHost remoteHost; + private Timer timer; + + /** + * Create a MonitoredHostProvider instance using the given HostIdentifier. + * + * @param hostId the host identifier for this MonitoredHost + * @throws MonitorException Thrown on any error encountered while + * communicating with the remote host. + */ + public MonitoredHostProvider(HostIdentifier hostId) + throws MonitorException { + this.hostId = hostId; + this.listeners = new ArrayList<HostListener>(); + this.interval = DEFAULT_POLLING_INTERVAL; + this.activeVms = new HashSet<Integer>(); + + String rmiName; + String sn = serverName; + String path = hostId.getPath(); + + if ((path != null) && (path.length() > 0)) { + sn = path; + } + + if (hostId.getPort() != -1) { + rmiName = "rmi://" + hostId.getHost() + ":" + hostId.getPort() + sn; + } else { + rmiName = "rmi://" + hostId.getHost() + sn; + } + + try { + remoteHost = (RemoteHost)Naming.lookup(rmiName); + + } catch (RemoteException e) { + /* + * rmi registry not available + * + * Access control exceptions, where the rmi server refuses a + * connection based on policy file configuration, come through + * here on the client side. Unfortunately, the RemoteException + * doesn't contain enough information to determine the true cause + * of the exception. So, we have to output a rather generic message. + */ + String message = "RMI Registry not available at " + + hostId.getHost(); + + if (hostId.getPort() == -1) { + message = message + ":" + + java.rmi.registry.Registry.REGISTRY_PORT; + } else { + message = message + ":" + hostId.getPort(); + } + + if (e.getMessage() != null) { + throw new MonitorException(message + "\n" + e.getMessage(), e); + } else { + throw new MonitorException(message, e); + } + + } catch (NotBoundException e) { + // no server with given name + String message = e.getMessage(); + if (message == null) message = rmiName; + throw new MonitorException("RMI Server " + message + + " not available", e); + } catch (MalformedURLException e) { + // this is a programming problem + e.printStackTrace(); + throw new IllegalArgumentException("Malformed URL: " + rmiName); + } + this.vmManager = new RemoteVmManager(remoteHost); + this.timer = new Timer(true); + } + + /** + * {@inheritDoc} + */ + public MonitoredVm getMonitoredVm(VmIdentifier vmid) + throws MonitorException { + return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL); + } + + /** + * {@inheritDoc} + */ + public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval) + throws MonitorException { + VmIdentifier nvmid = null; + try { + nvmid = hostId.resolve(vmid); + RemoteVm rvm = remoteHost.attachVm(vmid.getLocalVmId(), + vmid.getMode()); + RemoteMonitoredVm rmvm = new RemoteMonitoredVm(rvm, nvmid, timer, + interval); + rmvm.attach(); + return rmvm; + + } catch (RemoteException e) { + throw new MonitorException("Remote Exception attaching to " + + nvmid.toString(), e); + } catch (URISyntaxException e) { + /* + * the VmIdentifier is expected to be a valid and should resolve + * easonably against the host identifier. A URISyntaxException + * here is most likely a programming error. + */ + throw new IllegalArgumentException("Malformed URI: " + + vmid.toString(), e); + } + } + + /** + * {@inheritDoc} + */ + public void detach(MonitoredVm vm) throws MonitorException { + RemoteMonitoredVm rmvm = (RemoteMonitoredVm)vm; + rmvm.detach(); + try { + remoteHost.detachVm(rmvm.getRemoteVm()); + + } catch (RemoteException e) { + throw new MonitorException("Remote Exception detaching from " + + vm.getVmIdentifier().toString(), e); + } + } + + /** + * {@inheritDoc} + */ + public void addHostListener(HostListener listener) { + synchronized(listeners) { + listeners.add(listener); + if (task == null) { + task = new NotifierTask(); + timer.schedule(task, 0, interval); + } + } + } + + /** + * {@inheritDoc} + */ + public void removeHostListener(HostListener listener) { + /* + * XXX: if a disconnect method is added, make sure it calls + * this method to unregister this object from the watcher. otherwise, + * an unused MonitoredHostProvider instance may go uncollected. + */ + synchronized(listeners) { + listeners.remove(listener); + if (listeners.isEmpty() && (task != null)) { + task.cancel(); + task = null; + } + } + } + + public void setInterval(int newInterval) { + synchronized(listeners) { + if (newInterval == interval) { + return; + } + + int oldInterval = interval; + super.setInterval(newInterval); + + if (task != null) { + task.cancel(); + NotifierTask oldTask = task; + task = new NotifierTask(); + CountedTimerTaskUtils.reschedule(timer, oldTask, task, + oldInterval, newInterval); + } + } + } + + /** + * {@inheritDoc} + */ + public Set<Integer> activeVms() throws MonitorException { + return vmManager.activeVms(); + } + + /** + * Fire VmStatusChangeEvent events to HostListener objects + * + * @param active Set of Integer objects containing the local + * Vm Identifiers of the active JVMs + * @param started Set of Integer objects containing the local + * Vm Identifiers of new JVMs started since last + * interval. + * @param terminated Set of Integer objects containing the local + * Vm Identifiers of terminated JVMs since last + * interval. + */ + @SuppressWarnings("unchecked") // Cast of result of clone + private void fireVmStatusChangedEvents(Set<Integer> active, Set<Integer> started, + Set<Integer> terminated) { + ArrayList<HostListener> registered = null; + VmStatusChangeEvent ev = null; + + synchronized(listeners) { + registered = (ArrayList)listeners.clone(); + } + + for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) { + HostListener l = i.next(); + if (ev == null) { + ev = new VmStatusChangeEvent(this, active, started, terminated); + } + l.vmStatusChanged(ev); + } + } + + /** + * Fire hostDisconnectEvent events. + */ + @SuppressWarnings("unchecked") // Cast of result of clone + void fireDisconnectedEvents() { + ArrayList<HostListener> registered = null; + HostEvent ev = null; + + synchronized(listeners) { + registered = (ArrayList)listeners.clone(); + } + + for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) { + HostListener l = i.next(); + if (ev == null) { + ev = new HostEvent(this); + } + l.disconnected(ev); + } + } + + /** + * class to poll the remote machine and generate local event notifications. + */ + private class NotifierTask extends CountedTimerTask { + public void run() { + super.run(); + + // save the last set of active JVMs + Set<Integer> lastActiveVms = activeVms; + + try { + // get the current set of active JVMs + activeVms = (HashSet<Integer>)vmManager.activeVms(); + + } catch (MonitorException e) { + // XXX: use logging api + System.err.println("MonitoredHostProvider: polling task " + + "caught MonitorException:"); + e.printStackTrace(); + + // mark the HostManager as errored and notify listeners + setLastException(e); + fireDisconnectedEvents(); + } + + if (activeVms.isEmpty()) { + return; + } + + Set<Integer> startedVms = new HashSet<>(); + Set<Integer> terminatedVms = new HashSet<>(); + + for (Iterator<Integer> i = activeVms.iterator(); i.hasNext(); /* empty */ ) { + Integer vmid = i.next(); + if (!lastActiveVms.contains(vmid)) { + // a new file has been detected, add to set + startedVms.add(vmid); + } + } + + for (Iterator<Integer> i = lastActiveVms.iterator(); i.hasNext(); + /* empty */ ) { + Integer o = i.next(); + if (!activeVms.contains(o)) { + // JVM has terminated, remove it from the active list + terminatedVms.add(o); + } + } + + if (!startedVms.isEmpty() || !terminatedVms.isEmpty()) { + fireVmStatusChangedEvents(activeVms, startedVms, terminatedVms); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.jvmstat.perfdata.monitor.protocol.rmi; + +import sun.jvmstat.monitor.HostIdentifier; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredHostService; + +public final class MonitoredHostRmiService implements MonitoredHostService { + + @Override + public MonitoredHost getMonitoredHost(HostIdentifier hostId) throws MonitorException { + return new MonitoredHostProvider(hostId); + } + + @Override + public String getScheme() { + return "rmi"; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2004, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.jvmstat.perfdata.monitor.protocol.rmi; + +import sun.jvmstat.monitor.*; +import sun.jvmstat.monitor.remote.*; +import sun.jvmstat.perfdata.monitor.*; +import java.io.*; +import java.rmi.RemoteException; +import java.nio.ByteBuffer; + +/** + * The concrete PerfDataBuffer implementation for the <em>rmi:</em> + * protocol for the HotSpot PerfData monitoring implementation. + * <p> + * This class is responsible for acquiring the instrumentation buffer + * data for a remote target HotSpot Java Virtual Machine. + * + * @author Brian Doherty + * @since 1.5 + */ +public class PerfDataBuffer extends AbstractPerfDataBuffer { + + private RemoteVm rvm; + + /** + * Create a PerfDataBuffer instance for accessing the specified + * instrumentation buffer. + * + * @param rvm the proxy to the remote MonitredVm object + * @param lvmid the local Java Virtual Machine Identifier of the + * remote target. + * + * @throws MonitorException + */ + public PerfDataBuffer(RemoteVm rvm, int lvmid) throws MonitorException { + + this.rvm = rvm; + try { + ByteBuffer buffer = ByteBuffer.allocate(rvm.getCapacity()); + sample(buffer); + createPerfDataBuffer(buffer, lvmid); + + } catch (RemoteException e) { + throw new MonitorException("Could not read data for remote JVM " + + lvmid, e); + } + } + + /** + * Get a copy of the remote instrumentation buffer. + *<p> + * The data in the remote instrumentation buffer is copied into + * the local byte buffer. + * + * @param buffer the buffer to receive the copy of the remote + * instrumentation buffer. + * @throws RemoteException Thrown on any communications errors with + * the remote system. + */ + public void sample(ByteBuffer buffer) throws RemoteException { + assert buffer != null; + assert rvm != null; + synchronized(buffer) { + buffer.clear(); + buffer.put(rvm.getBytes()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2004, 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.jvmstat.perfdata.monitor.protocol.rmi; + +import sun.jvmstat.monitor.*; +import sun.jvmstat.monitor.event.*; +import sun.jvmstat.monitor.remote.*; +import sun.jvmstat.perfdata.monitor.*; +import java.lang.reflect.*; +import java.util.*; +import java.io.*; +import java.nio.ByteBuffer; +import java.rmi.*; + +/** + * Concrete implementation of the AbstractMonitoredVm class for the + * <em>rmi:</em> protocol for the HotSpot PerfData monitoring implementation. + * <p> + * This class provides the ability to acquire to the instrumentation buffer + * of a live, remote target Java Virtual Machine through an RMI server. + * + * @author Brian Doherty + * @since 1.5 + */ +public class RemoteMonitoredVm extends AbstractMonitoredVm { + + private ArrayList<VmListener> listeners; + private NotifierTask notifierTask; + private SamplerTask samplerTask; + private Timer timer; + + private RemoteVm rvm; + private ByteBuffer updateBuffer; + + /** + * Create a RemoteMonitoredVm instance. + * + * @param rvm the proxy to the remote MonitoredVm instance. + * @param vmid the vm identifier specifying the remot target JVM + * @param timer the timer used to run polling tasks + * @param interval the sampling interval + */ + public RemoteMonitoredVm(RemoteVm rvm, VmIdentifier vmid, + Timer timer, int interval) + throws MonitorException { + super(vmid, interval); + this.rvm = rvm; + pdb = new PerfDataBuffer(rvm, vmid.getLocalVmId()); + this.listeners = new ArrayList<VmListener>(); + this.timer = timer; + } + + /** + * Method to attach to the remote MonitoredVm. + */ + public void attach() throws MonitorException { + updateBuffer = pdb.getByteBuffer().duplicate(); + + // if continuous sampling is requested, register with the sampler thread + if (interval > 0) { + samplerTask = new SamplerTask(); + timer.schedule(samplerTask, 0, interval); + } + } + + /** + * {@inheritDoc} + */ + public void detach() { + try { + if (interval > 0) { + if (samplerTask != null) { + samplerTask.cancel(); + samplerTask = null; + } + if (notifierTask != null) { + notifierTask.cancel(); + notifierTask = null; + } + sample(); + } + } catch (RemoteException e) { + // XXX: - use logging api? throw an exception instead? + System.err.println("Could not read data for remote JVM " + vmid); + e.printStackTrace(); + + } finally { + super.detach(); + } + } + + /** + * Get a copy of the remote instrumentation buffer. + *<p> + * The data in the remote instrumentation buffer is copied into + * a local byte buffer. + * + * @throws RemoteException Thrown on any communications errors with + * the remote system. + */ + public void sample() throws RemoteException { + assert updateBuffer != null; + ((PerfDataBuffer)pdb).sample(updateBuffer); + } + + /** + * Get the proxy to the remote MonitoredVm. + * + * @return RemoteVm - the proxy to the remote MonitoredVm. + */ + public RemoteVm getRemoteVm() { + return rvm; + } + + /** + * {@inheritDoc} + */ + public void addVmListener(VmListener l) { + synchronized(listeners) { + listeners.add(l); + if (notifierTask == null) { + notifierTask = new NotifierTask(); + timer.schedule(notifierTask, 0, interval); + } + } + } + + /** + * {@inheritDoc} + */ + public void removeVmListener(VmListener l) { + synchronized(listeners) { + listeners.remove(l); + if (listeners.isEmpty() && (notifierTask != null)) { + notifierTask.cancel(); + notifierTask = null; + } + } + } + + /** + * {@inheritDoc} + */ + public void setInterval(int newInterval) { + synchronized(listeners) { + if (newInterval == interval) { + return; + } + + int oldInterval = interval; + super.setInterval(newInterval); + + if (samplerTask != null) { + samplerTask.cancel(); + SamplerTask oldSamplerTask = samplerTask; + samplerTask = new SamplerTask(); + CountedTimerTaskUtils.reschedule(timer, oldSamplerTask, + samplerTask, oldInterval, + newInterval); + } + if (notifierTask != null) { + notifierTask.cancel(); + NotifierTask oldNotifierTask = notifierTask; + notifierTask = new NotifierTask(); + CountedTimerTaskUtils.reschedule(timer, oldNotifierTask, + notifierTask, oldInterval, + newInterval); + } + } + } + + /** + * Fire MonitoredVmStructureChanged events. + * + * @param inserted List of Monitor objects inserted. + * @param removed List of Monitor objects removed. + */ + @SuppressWarnings("unchecked") // Cast of result of clone + void fireMonitorStatusChangedEvents(List<Monitor> inserted, List<Monitor> removed) { + ArrayList<VmListener> registered = null; + MonitorStatusChangeEvent ev = null; + + synchronized(listeners) { + registered = (ArrayList)listeners.clone(); + } + + for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) { + VmListener l = i.next(); + if (ev == null) { + ev = new MonitorStatusChangeEvent(this, inserted, removed); + } + l.monitorStatusChanged(ev); + } + } + + /** + * Fire MonitoredVmStructureChanged events. + */ + @SuppressWarnings("unchecked") // Cast of result of clone + void fireMonitorsUpdatedEvents() { + ArrayList<VmListener> registered = null; + VmEvent ev = null; + + synchronized(listeners) { + registered = (ArrayList)listeners.clone(); + } + + for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) { + VmListener l = i.next(); + if (ev == null) { + ev = new VmEvent(this); + } + l.monitorsUpdated(ev); + } + } + + /* + * Timer Tasks. There are two separate timer tasks here. The SamplerTask + * is active whenever we are attached to the remote JVM with a periodic + * sampling interval > 0. The NotifierTask is only active if a VmListener + * has registered with this RemoteMonitoredVm instance. Also, in the future + * we may want to run these tasks at different intervals. Currently, + * they run at the same interval and some significant work may + * need to be done to complete the separation of these two intervals. + */ + + /** + * Class to periodically check the state of the defined monitors + * for the remote MonitoredVm instance and to notify listeners of + * any detected changes. + */ + private class NotifierTask extends CountedTimerTask { + public void run() { + super.run(); + try { + MonitorStatus status = getMonitorStatus(); + + List<Monitor> inserted = status.getInserted(); + List<Monitor> removed = status.getRemoved(); + + if (!inserted.isEmpty() || !removed.isEmpty()) { + fireMonitorStatusChangedEvents(inserted, removed); + } + } catch (MonitorException e) { + // XXX: use logging api? fire disconnect events? mark errored? + // fireDisconnectedEvents(); + System.err.println("Exception updating monitors for " + + getVmIdentifier()); + e.printStackTrace(); + // XXX: should we cancle the notifierTask here? + // this.cancel(); + } + } + } + + /** + * Class to periodically sample the remote instrumentation byte buffer + * and refresh the local copy. Registered listeners are notified of + * the completion of a sampling event. + */ + private class SamplerTask extends CountedTimerTask { + public void run() { + super.run(); + try { + sample(); + fireMonitorsUpdatedEvents(); + + } catch (RemoteException e) { + // XXX: use logging api, mark vm as errored. + System.err.println("Exception taking sample for " + + getVmIdentifier()); + e.printStackTrace(); + this.cancel(); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2004, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.jvmstat.perfdata.monitor.protocol.rmi; + +import java.util.*; +import java.util.regex.*; +import java.io.*; +import java.rmi.RemoteException; +import sun.jvmstat.monitor.*; +import sun.jvmstat.monitor.event.*; +import sun.jvmstat.monitor.remote.*; + +/** + * Class for managing the RemoteMonitoredVm instances on a remote system. + * <p> + * This class is responsible for the mechanism that detects the active + * HotSpot Java Virtual Machines on the remote host and possibly for a + * specific user. The ability to detect all possible HotSpot Java Virtual + * Machines on the remote host may be limited by the permissions of the + * principal running the RMI server application on the remote host. + * + * @author Brian Doherty + * @since 1.5 + */ +public class RemoteVmManager { + + private RemoteHost remoteHost; + private String user; + + /** + * Creates a RemoteVmManager instance for the remote system. + * <p> + * Manages RemoteMonitordVm instances for which the principal + * running the remote server has appropriate permissions. + * + * @param remoteHost the remote proxy object to the RMI server on + * the remote system. + */ + public RemoteVmManager(RemoteHost remoteHost) { + this(remoteHost, null); + } + + /** + * Creates a RemoteVmManager instance for the given user. + * <p> + * Manages RemoteMonitoredVm instances for all remote Java Virtual + * machines owned by the specified user on the remote system. The + * RMI server on the remote system must have the appropriate permissions + * to access the named users Java Virtual Machines. + * + * @param remoteHost the remote proxy object to the RMI server on + * the remote system. + * @param user the name of the user + */ + public RemoteVmManager(RemoteHost remoteHost, String user) { + this.user = user; + this.remoteHost = remoteHost; + } + + /** + * Return the current set of monitorable Java Virtual Machines. + * <p> + * The set returned by this method depends on the user name passed + * to the constructor. If no user name was specified, then this + * method will return all candidate JVMs on the system. Otherwise, + * only the JVMs for the given user will be returned. This assumes + * that the RMI server process has the appropriate permissions to + * access the target set of JVMs. + * + * @return Set - the Set of monitorable Java Virtual Machines + */ + public Set<Integer> activeVms() throws MonitorException { + int[] active = null; + + try { + active = remoteHost.activeVms(); + + } catch (RemoteException e) { + throw new MonitorException("Error communicating with remote host: " + + e.getMessage(), e); + } + + Set<Integer> activeSet = new HashSet<Integer>(active.length); + + for (int i = 0; i < active.length; i++) { + activeSet.add(active[i]); + } + + return activeSet; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,47 @@ +<!doctype html public "-//IETF//DTD HTML/EN"> +<html> +<head> +<!-- + + + Copyright (c) 2004, 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. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the LICENSE file that accompanied this code. + + 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. + +--> +</head> +<body bgcolor="white"> +<p> +Provides the implementation classes for the <em>rmi:</em> protocol for +the HotSpot PerfData instrumentation buffer monitoring implementation. +</p> +<p> +The <em>rmi:</em> protocol is the default protocol for the PerfData +implementation when a hostname is specified as part of a HostIdentifier +or VMIdentifier. It communicates with an RMI server on the remote machine +that provides functions to get a list of available Java Virtual Machines +and to acquire a copy of a Java Virtual Machine's instrumentation buffer. +The RMI server may or may not use the PerfData implementation on the +remote host to acquire this information. The <em>jstatd</em> server +provides a PerfData implementation of the RMI server. +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2004, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.tools.jstatd; + +import java.rmi.*; +import java.rmi.server.*; +import java.rmi.registry.Registry; +import java.rmi.registry.LocateRegistry; +import java.net.MalformedURLException; +import sun.jvmstat.monitor.remote.*; + +/** + * Application providing remote access to the jvmstat instrumentation + * exported by local Java Virtual Machine processes. Remote access is + * provided through an RMI interface. + * + * @author Brian Doherty + * @since 1.5 + */ +public class Jstatd { + + private static Registry registry; + private static int port = -1; + private static boolean startRegistry = true; + + private static void printUsage() { + System.err.println("usage: jstatd [-nr] [-p port] [-n rminame]"); + } + + static void bind(String name, RemoteHostImpl remoteHost) + throws RemoteException, MalformedURLException, Exception { + + try { + Naming.rebind(name, remoteHost); + } catch (java.rmi.ConnectException e) { + /* + * either the registry is not running or we cannot contact it. + * start an internal registry if requested. + */ + if (startRegistry && registry == null) { + int localport = (port < 0) ? Registry.REGISTRY_PORT : port; + registry = LocateRegistry.createRegistry(localport); + bind(name, remoteHost); + } else { + throw e; + } + } + } + + @SuppressWarnings("deprecation") // Use of RMISecurityManager + public static void main(String[] args) { + String rminame = null; + int argc = 0; + + for ( ; (argc < args.length) && (args[argc].startsWith("-")); argc++) { + String arg = args[argc]; + + if (arg.compareTo("-nr") == 0) { + startRegistry = false; + } else if (arg.startsWith("-p")) { + if (arg.compareTo("-p") != 0) { + port = Integer.parseInt(arg.substring(2)); + } else { + argc++; + if (argc >= args.length) { + printUsage(); + System.exit(1); + } + port = Integer.parseInt(args[argc]); + } + } else if (arg.startsWith("-n")) { + if (arg.compareTo("-n") != 0) { + rminame = arg.substring(2); + } else { + argc++; + if (argc >= args.length) { + printUsage(); + System.exit(1); + } + rminame = args[argc]; + } + } else { + printUsage(); + System.exit(1); + } + } + + if (argc < args.length) { + printUsage(); + System.exit(1); + } + + if (System.getSecurityManager() == null) { + System.setSecurityManager(new RMISecurityManager()); + } + + StringBuilder name = new StringBuilder(); + + if (port >= 0) { + name.append("//:").append(port); + } + + if (rminame == null) { + rminame = "JStatRemoteHost"; + } + + name.append("/").append(rminame); + + try { + // use 1.5.0 dynamically generated subs. + System.setProperty("java.rmi.server.ignoreSubClasses", "true"); + RemoteHostImpl remoteHost = new RemoteHostImpl(); + RemoteHost stub = (RemoteHost) UnicastRemoteObject.exportObject( + remoteHost, 0); + bind(name.toString(), remoteHost); + System.out.println("jstatd started (bound to " + name.toString() + ")"); + System.out.flush(); + } catch (MalformedURLException e) { + if (rminame != null) { + System.out.println("Bad RMI server name: " + rminame); + } else { + System.out.println("Bad RMI URL: " + name); + } + e.printStackTrace(System.out); + System.exit(1); + } catch (java.rmi.ConnectException e) { + // could not attach to or create a registry + System.out.println("Could not contact RMI registry"); + e.printStackTrace(System.out); + System.exit(1); + } catch (RemoteException e) { + System.out.println("Could not bind " + name + " to RMI Registry"); + e.printStackTrace(System.out); + System.exit(1); + } catch (Exception e) { + System.out.println("Could not create remote object"); + e.printStackTrace(System.out); + System.exit(1); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2004, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.tools.jstatd; + +import java.util.*; +import java.nio.*; +import java.io.*; +import java.net.*; +import java.rmi.*; +import java.rmi.server.*; +import sun.jvmstat.monitor.*; +import sun.jvmstat.monitor.event.*; +import sun.jvmstat.monitor.remote.*; + +/** + * Concrete implementation of the RemoteHost interface for the HotSpot + * PerfData <em>rmi:</em> protocol. + * <p> + * This class provides remote access to the instrumentation exported + * by HotSpot Java Virtual Machines through the PerfData shared memory + * interface. + * + * @author Brian Doherty + * @since 1.5 + */ +public class RemoteHostImpl implements RemoteHost, HostListener { + + private MonitoredHost monitoredHost; + private Set<Integer> activeVms; + + public RemoteHostImpl() throws MonitorException { + try { + monitoredHost = MonitoredHost.getMonitoredHost("localhost"); + } catch (URISyntaxException e) { } + + activeVms = monitoredHost.activeVms(); + monitoredHost.addHostListener(this); + } + + public RemoteVm attachVm(int lvmid, String mode) + throws RemoteException, MonitorException { + Integer v = lvmid; + RemoteVm stub = null; + StringBuilder sb = new StringBuilder(); + + sb.append("local://").append(lvmid).append("@localhost"); + if (mode != null) { + sb.append("?mode=").append(mode); + } + + String vmidStr = sb.toString(); + + try { + VmIdentifier vmid = new VmIdentifier(vmidStr); + MonitoredVm mvm = monitoredHost.getMonitoredVm(vmid); + RemoteVmImpl rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm); + stub = (RemoteVm) UnicastRemoteObject.exportObject(rvm, 0); + } + catch (URISyntaxException e) { + throw new RuntimeException("Malformed VmIdentifier URI: " + + vmidStr, e); + } + return stub; + } + + public void detachVm(RemoteVm rvm) throws RemoteException { + rvm.detach(); + } + + public int[] activeVms() throws MonitorException { + Object[] vms = null; + int[] vmids = null; + + vms = monitoredHost.activeVms().toArray(); + vmids = new int[vms.length]; + + for (int i = 0; i < vmids.length; i++) { + vmids[i] = ((Integer)vms[i]).intValue(); + } + return vmids; + } + + public void vmStatusChanged(VmStatusChangeEvent ev) { + synchronized(this.activeVms) { + activeVms.retainAll(ev.getActive()); + } + } + + public void disconnected(HostEvent ev) { + // we only monitor the local host, so this event shouldn't occur. + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteVmImpl.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2004, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package sun.tools.jstatd; + +import sun.jvmstat.monitor.*; +import sun.jvmstat.monitor.remote.*; + +/** + * Concrete implementation of the RemoteVm interface for the HotSpot PerfData + * shared memory implementation of the jvmstat monitoring APIs. This class + * providing remote access to the instrumentation exported by a local HotSpot + * Java Virtual Machine. The instrumentation buffer is shipped in whole to + * the remote machine, which is responsible for parsing and provide access + * to the contained data. + * + * @author Brian Doherty + * @since 1.5 + */ +public class RemoteVmImpl implements RemoteVm { + + private BufferedMonitoredVm mvm; + + RemoteVmImpl(BufferedMonitoredVm mvm) { + this.mvm = mvm; + } + + public byte[] getBytes() { + return mvm.getBytes(); + } + + public int getCapacity() { + return mvm.getCapacity(); + } + + public void detach() { + mvm.detach(); + } + + public int getLocalVmId() { + return mvm.getVmIdentifier().getLocalVmId(); + } +}
--- a/src/jdk.jvmstat.rmi/share/classes/module-info.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -module jdk.jvmstat.rmi { - requires java.rmi; - requires jdk.jvmstat; - - // RMI needs to serialize types in this package - exports sun.jvmstat.monitor.remote to java.rmi; - - provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService; -} -
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.jvmstat.monitor.remote; - -import sun.jvmstat.monitor.*; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.io.IOException; - -/** - * Remote Interface for discovering and attaching to remote - * monitorable Java Virtual Machines. - * - * @author Brian Doherty - * @since 1.5 - */ -public interface RemoteHost extends Remote { - - /** - * Remote method to attach to a remote HotSpot Java Virtual Machine - * identified by <code>vmid</code>. - * - * @param vmid The identifier for the target virtual machine. - * @return RemoteVm - A remote object for accessing the remote Java - * Virtual Machine. - * - * @throws MonitorException Thrown when any other error is encountered - * while communicating with the target virtual - * machine. - * @throws RemoteException - * - */ - RemoteVm attachVm(int vmid, String mode) throws RemoteException, - MonitorException; - - /** - * Remote method to detach from a remote HotSpot Java Virtual Machine - * identified by <code>vmid</code>. - * - * @param rvm The remote object for the target Java Virtual - * Machine. - * - * @throws MonitorException Thrown when any other error is encountered - * while communicating with the target virtual - * machine. - * @throws RemoteException - */ - void detachVm(RemoteVm rvm) throws RemoteException, MonitorException; - - /** - * Get a list of Local Virtual Machine Identifiers for the active - * Java Virtual Machine the remote system. A Local Virtual Machine - * Identifier is also known as an <em>lvmid</em>. - * - * @return int[] - A array of <em>lvmid</em>s. - * @throws MonitorException Thrown when any other error is encountered - * while communicating with the target virtual - * machine. - * @throws RemoteException - */ - int[] activeVms() throws RemoteException, MonitorException; -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.jvmstat.monitor.remote; - -import java.rmi.Remote; -import java.rmi.RemoteException; - -/** - * Interface for accessing the instrumentation exported by a - * Java Virtual Machine running on a remote host. - * - * @author Brian Doherty - * @since 1.5 - */ -public interface RemoteVm extends Remote { - - /** - * Interface to get the bytes associated with the instrumentation - * for the remote Java Virtual Machine. - * - * @return byte[] - a byte array containing the current bytes - * for the instrumentation exported by the - * remote Java Virtual Machine. - * @throws RemoteException Thrown on any communication error - */ - byte[] getBytes() throws RemoteException; - - /** - * Interface to get the size of the instrumentation buffer - * for the target Java Virtual Machine. - * - * @return int - the size of the instrumentation buffer for the - * remote Java Virtual Machine. - * @throws RemoteException Thrown on any communication error - */ - int getCapacity() throws RemoteException; - - /** - * Interface to return the Local Virtual Machine Identifier for - * the remote Java Virtual Machine. The Local Virtual Machine - * Identifier is also know as the <em>lvmid</em>. - * - * @throws RemoteException Thrown on any communication error - */ - int getLocalVmId() throws RemoteException; - - /** - * Interface to detach from the remote Java Virtual Machine. - * - * @throws RemoteException Thrown on any communication error - */ - void detach() throws RemoteException; -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/package.html Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -<!doctype html public "-//IETF//DTD HTML/EN"> -<html> -<head> -<!-- - - - Copyright (c) 2004, 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. Oracle designates this - particular file as subject to the "Classpath" exception as provided - by Oracle in the LICENSE file that accompanied this code. - - 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. - - ---> -</head> -<body bgcolor="white"> -<p> -Provides interfaces supporting remote monitoring for instrumented -HotSpot Java Virtual Machines. -</p> -</body> -</html>
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2004, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.jvmstat.perfdata.monitor.protocol.rmi; - -import sun.jvmstat.monitor.*; -import sun.jvmstat.monitor.event.*; -import sun.jvmstat.monitor.remote.*; -import sun.jvmstat.perfdata.monitor.*; -import java.util.*; -import java.net.*; -import java.io.*; -import java.rmi.*; -import java.util.HashMap; - -/** - * Concrete implementation of the MonitoredHost interface for the - * <em>rmi</em> protocol of the HotSpot PerfData monitoring implementation. - * - * @author Brian Doherty - * @since 1.5 - */ -public class MonitoredHostProvider extends MonitoredHost { - private static final String serverName = "/JStatRemoteHost"; - private static final int DEFAULT_POLLING_INTERVAL = 1000; - - private ArrayList<HostListener> listeners; - private NotifierTask task; - private HashSet<Integer> activeVms; - private RemoteVmManager vmManager; - private RemoteHost remoteHost; - private Timer timer; - - /** - * Create a MonitoredHostProvider instance using the given HostIdentifier. - * - * @param hostId the host identifier for this MonitoredHost - * @throws MonitorException Thrown on any error encountered while - * communicating with the remote host. - */ - public MonitoredHostProvider(HostIdentifier hostId) - throws MonitorException { - this.hostId = hostId; - this.listeners = new ArrayList<HostListener>(); - this.interval = DEFAULT_POLLING_INTERVAL; - this.activeVms = new HashSet<Integer>(); - - String rmiName; - String sn = serverName; - String path = hostId.getPath(); - - if ((path != null) && (path.length() > 0)) { - sn = path; - } - - if (hostId.getPort() != -1) { - rmiName = "rmi://" + hostId.getHost() + ":" + hostId.getPort() + sn; - } else { - rmiName = "rmi://" + hostId.getHost() + sn; - } - - try { - remoteHost = (RemoteHost)Naming.lookup(rmiName); - - } catch (RemoteException e) { - /* - * rmi registry not available - * - * Access control exceptions, where the rmi server refuses a - * connection based on policy file configuration, come through - * here on the client side. Unfortunately, the RemoteException - * doesn't contain enough information to determine the true cause - * of the exception. So, we have to output a rather generic message. - */ - String message = "RMI Registry not available at " - + hostId.getHost(); - - if (hostId.getPort() == -1) { - message = message + ":" - + java.rmi.registry.Registry.REGISTRY_PORT; - } else { - message = message + ":" + hostId.getPort(); - } - - if (e.getMessage() != null) { - throw new MonitorException(message + "\n" + e.getMessage(), e); - } else { - throw new MonitorException(message, e); - } - - } catch (NotBoundException e) { - // no server with given name - String message = e.getMessage(); - if (message == null) message = rmiName; - throw new MonitorException("RMI Server " + message - + " not available", e); - } catch (MalformedURLException e) { - // this is a programming problem - e.printStackTrace(); - throw new IllegalArgumentException("Malformed URL: " + rmiName); - } - this.vmManager = new RemoteVmManager(remoteHost); - this.timer = new Timer(true); - } - - /** - * {@inheritDoc} - */ - public MonitoredVm getMonitoredVm(VmIdentifier vmid) - throws MonitorException { - return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL); - } - - /** - * {@inheritDoc} - */ - public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval) - throws MonitorException { - VmIdentifier nvmid = null; - try { - nvmid = hostId.resolve(vmid); - RemoteVm rvm = remoteHost.attachVm(vmid.getLocalVmId(), - vmid.getMode()); - RemoteMonitoredVm rmvm = new RemoteMonitoredVm(rvm, nvmid, timer, - interval); - rmvm.attach(); - return rmvm; - - } catch (RemoteException e) { - throw new MonitorException("Remote Exception attaching to " - + nvmid.toString(), e); - } catch (URISyntaxException e) { - /* - * the VmIdentifier is expected to be a valid and should resolve - * easonably against the host identifier. A URISyntaxException - * here is most likely a programming error. - */ - throw new IllegalArgumentException("Malformed URI: " - + vmid.toString(), e); - } - } - - /** - * {@inheritDoc} - */ - public void detach(MonitoredVm vm) throws MonitorException { - RemoteMonitoredVm rmvm = (RemoteMonitoredVm)vm; - rmvm.detach(); - try { - remoteHost.detachVm(rmvm.getRemoteVm()); - - } catch (RemoteException e) { - throw new MonitorException("Remote Exception detaching from " - + vm.getVmIdentifier().toString(), e); - } - } - - /** - * {@inheritDoc} - */ - public void addHostListener(HostListener listener) { - synchronized(listeners) { - listeners.add(listener); - if (task == null) { - task = new NotifierTask(); - timer.schedule(task, 0, interval); - } - } - } - - /** - * {@inheritDoc} - */ - public void removeHostListener(HostListener listener) { - /* - * XXX: if a disconnect method is added, make sure it calls - * this method to unregister this object from the watcher. otherwise, - * an unused MonitoredHostProvider instance may go uncollected. - */ - synchronized(listeners) { - listeners.remove(listener); - if (listeners.isEmpty() && (task != null)) { - task.cancel(); - task = null; - } - } - } - - public void setInterval(int newInterval) { - synchronized(listeners) { - if (newInterval == interval) { - return; - } - - int oldInterval = interval; - super.setInterval(newInterval); - - if (task != null) { - task.cancel(); - NotifierTask oldTask = task; - task = new NotifierTask(); - CountedTimerTaskUtils.reschedule(timer, oldTask, task, - oldInterval, newInterval); - } - } - } - - /** - * {@inheritDoc} - */ - public Set<Integer> activeVms() throws MonitorException { - return vmManager.activeVms(); - } - - /** - * Fire VmStatusChangeEvent events to HostListener objects - * - * @param active Set of Integer objects containing the local - * Vm Identifiers of the active JVMs - * @param started Set of Integer objects containing the local - * Vm Identifiers of new JVMs started since last - * interval. - * @param terminated Set of Integer objects containing the local - * Vm Identifiers of terminated JVMs since last - * interval. - */ - @SuppressWarnings("unchecked") // Cast of result of clone - private void fireVmStatusChangedEvents(Set<Integer> active, Set<Integer> started, - Set<Integer> terminated) { - ArrayList<HostListener> registered = null; - VmStatusChangeEvent ev = null; - - synchronized(listeners) { - registered = (ArrayList)listeners.clone(); - } - - for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) { - HostListener l = i.next(); - if (ev == null) { - ev = new VmStatusChangeEvent(this, active, started, terminated); - } - l.vmStatusChanged(ev); - } - } - - /** - * Fire hostDisconnectEvent events. - */ - @SuppressWarnings("unchecked") // Cast of result of clone - void fireDisconnectedEvents() { - ArrayList<HostListener> registered = null; - HostEvent ev = null; - - synchronized(listeners) { - registered = (ArrayList)listeners.clone(); - } - - for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) { - HostListener l = i.next(); - if (ev == null) { - ev = new HostEvent(this); - } - l.disconnected(ev); - } - } - - /** - * class to poll the remote machine and generate local event notifications. - */ - private class NotifierTask extends CountedTimerTask { - public void run() { - super.run(); - - // save the last set of active JVMs - Set<Integer> lastActiveVms = activeVms; - - try { - // get the current set of active JVMs - activeVms = (HashSet<Integer>)vmManager.activeVms(); - - } catch (MonitorException e) { - // XXX: use logging api - System.err.println("MonitoredHostProvider: polling task " - + "caught MonitorException:"); - e.printStackTrace(); - - // mark the HostManager as errored and notify listeners - setLastException(e); - fireDisconnectedEvents(); - } - - if (activeVms.isEmpty()) { - return; - } - - Set<Integer> startedVms = new HashSet<>(); - Set<Integer> terminatedVms = new HashSet<>(); - - for (Iterator<Integer> i = activeVms.iterator(); i.hasNext(); /* empty */ ) { - Integer vmid = i.next(); - if (!lastActiveVms.contains(vmid)) { - // a new file has been detected, add to set - startedVms.add(vmid); - } - } - - for (Iterator<Integer> i = lastActiveVms.iterator(); i.hasNext(); - /* empty */ ) { - Integer o = i.next(); - if (!activeVms.contains(o)) { - // JVM has terminated, remove it from the active list - terminatedVms.add(o); - } - } - - if (!startedVms.isEmpty() || !terminatedVms.isEmpty()) { - fireVmStatusChangedEvents(activeVms, startedVms, terminatedVms); - } - } - } -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.jvmstat.perfdata.monitor.protocol.rmi; - -import sun.jvmstat.monitor.HostIdentifier; -import sun.jvmstat.monitor.MonitorException; -import sun.jvmstat.monitor.MonitoredHost; -import sun.jvmstat.monitor.MonitoredHostService; - -public final class MonitoredHostRmiService implements MonitoredHostService { - - @Override - public MonitoredHost getMonitoredHost(HostIdentifier hostId) throws MonitorException { - return new MonitoredHostProvider(hostId); - } - - @Override - public String getScheme() { - return "rmi"; - } - -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.jvmstat.perfdata.monitor.protocol.rmi; - -import sun.jvmstat.monitor.*; -import sun.jvmstat.monitor.remote.*; -import sun.jvmstat.perfdata.monitor.*; -import java.io.*; -import java.rmi.RemoteException; -import java.nio.ByteBuffer; - -/** - * The concrete PerfDataBuffer implementation for the <em>rmi:</em> - * protocol for the HotSpot PerfData monitoring implementation. - * <p> - * This class is responsible for acquiring the instrumentation buffer - * data for a remote target HotSpot Java Virtual Machine. - * - * @author Brian Doherty - * @since 1.5 - */ -public class PerfDataBuffer extends AbstractPerfDataBuffer { - - private RemoteVm rvm; - - /** - * Create a PerfDataBuffer instance for accessing the specified - * instrumentation buffer. - * - * @param rvm the proxy to the remote MonitredVm object - * @param lvmid the local Java Virtual Machine Identifier of the - * remote target. - * - * @throws MonitorException - */ - public PerfDataBuffer(RemoteVm rvm, int lvmid) throws MonitorException { - - this.rvm = rvm; - try { - ByteBuffer buffer = ByteBuffer.allocate(rvm.getCapacity()); - sample(buffer); - createPerfDataBuffer(buffer, lvmid); - - } catch (RemoteException e) { - throw new MonitorException("Could not read data for remote JVM " - + lvmid, e); - } - } - - /** - * Get a copy of the remote instrumentation buffer. - *<p> - * The data in the remote instrumentation buffer is copied into - * the local byte buffer. - * - * @param buffer the buffer to receive the copy of the remote - * instrumentation buffer. - * @throws RemoteException Thrown on any communications errors with - * the remote system. - */ - public void sample(ByteBuffer buffer) throws RemoteException { - assert buffer != null; - assert rvm != null; - synchronized(buffer) { - buffer.clear(); - buffer.put(rvm.getBytes()); - } - } -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2004, 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.jvmstat.perfdata.monitor.protocol.rmi; - -import sun.jvmstat.monitor.*; -import sun.jvmstat.monitor.event.*; -import sun.jvmstat.monitor.remote.*; -import sun.jvmstat.perfdata.monitor.*; -import java.lang.reflect.*; -import java.util.*; -import java.io.*; -import java.nio.ByteBuffer; -import java.rmi.*; - -/** - * Concrete implementation of the AbstractMonitoredVm class for the - * <em>rmi:</em> protocol for the HotSpot PerfData monitoring implementation. - * <p> - * This class provides the ability to acquire to the instrumentation buffer - * of a live, remote target Java Virtual Machine through an RMI server. - * - * @author Brian Doherty - * @since 1.5 - */ -public class RemoteMonitoredVm extends AbstractMonitoredVm { - - private ArrayList<VmListener> listeners; - private NotifierTask notifierTask; - private SamplerTask samplerTask; - private Timer timer; - - private RemoteVm rvm; - private ByteBuffer updateBuffer; - - /** - * Create a RemoteMonitoredVm instance. - * - * @param rvm the proxy to the remote MonitoredVm instance. - * @param vmid the vm identifier specifying the remot target JVM - * @param timer the timer used to run polling tasks - * @param interval the sampling interval - */ - public RemoteMonitoredVm(RemoteVm rvm, VmIdentifier vmid, - Timer timer, int interval) - throws MonitorException { - super(vmid, interval); - this.rvm = rvm; - pdb = new PerfDataBuffer(rvm, vmid.getLocalVmId()); - this.listeners = new ArrayList<VmListener>(); - this.timer = timer; - } - - /** - * Method to attach to the remote MonitoredVm. - */ - public void attach() throws MonitorException { - updateBuffer = pdb.getByteBuffer().duplicate(); - - // if continuous sampling is requested, register with the sampler thread - if (interval > 0) { - samplerTask = new SamplerTask(); - timer.schedule(samplerTask, 0, interval); - } - } - - /** - * {@inheritDoc} - */ - public void detach() { - try { - if (interval > 0) { - if (samplerTask != null) { - samplerTask.cancel(); - samplerTask = null; - } - if (notifierTask != null) { - notifierTask.cancel(); - notifierTask = null; - } - sample(); - } - } catch (RemoteException e) { - // XXX: - use logging api? throw an exception instead? - System.err.println("Could not read data for remote JVM " + vmid); - e.printStackTrace(); - - } finally { - super.detach(); - } - } - - /** - * Get a copy of the remote instrumentation buffer. - *<p> - * The data in the remote instrumentation buffer is copied into - * a local byte buffer. - * - * @throws RemoteException Thrown on any communications errors with - * the remote system. - */ - public void sample() throws RemoteException { - assert updateBuffer != null; - ((PerfDataBuffer)pdb).sample(updateBuffer); - } - - /** - * Get the proxy to the remote MonitoredVm. - * - * @return RemoteVm - the proxy to the remote MonitoredVm. - */ - public RemoteVm getRemoteVm() { - return rvm; - } - - /** - * {@inheritDoc} - */ - public void addVmListener(VmListener l) { - synchronized(listeners) { - listeners.add(l); - if (notifierTask == null) { - notifierTask = new NotifierTask(); - timer.schedule(notifierTask, 0, interval); - } - } - } - - /** - * {@inheritDoc} - */ - public void removeVmListener(VmListener l) { - synchronized(listeners) { - listeners.remove(l); - if (listeners.isEmpty() && (notifierTask != null)) { - notifierTask.cancel(); - notifierTask = null; - } - } - } - - /** - * {@inheritDoc} - */ - public void setInterval(int newInterval) { - synchronized(listeners) { - if (newInterval == interval) { - return; - } - - int oldInterval = interval; - super.setInterval(newInterval); - - if (samplerTask != null) { - samplerTask.cancel(); - SamplerTask oldSamplerTask = samplerTask; - samplerTask = new SamplerTask(); - CountedTimerTaskUtils.reschedule(timer, oldSamplerTask, - samplerTask, oldInterval, - newInterval); - } - if (notifierTask != null) { - notifierTask.cancel(); - NotifierTask oldNotifierTask = notifierTask; - notifierTask = new NotifierTask(); - CountedTimerTaskUtils.reschedule(timer, oldNotifierTask, - notifierTask, oldInterval, - newInterval); - } - } - } - - /** - * Fire MonitoredVmStructureChanged events. - * - * @param inserted List of Monitor objects inserted. - * @param removed List of Monitor objects removed. - */ - @SuppressWarnings("unchecked") // Cast of result of clone - void fireMonitorStatusChangedEvents(List<Monitor> inserted, List<Monitor> removed) { - ArrayList<VmListener> registered = null; - MonitorStatusChangeEvent ev = null; - - synchronized(listeners) { - registered = (ArrayList)listeners.clone(); - } - - for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) { - VmListener l = i.next(); - if (ev == null) { - ev = new MonitorStatusChangeEvent(this, inserted, removed); - } - l.monitorStatusChanged(ev); - } - } - - /** - * Fire MonitoredVmStructureChanged events. - */ - @SuppressWarnings("unchecked") // Cast of result of clone - void fireMonitorsUpdatedEvents() { - ArrayList<VmListener> registered = null; - VmEvent ev = null; - - synchronized(listeners) { - registered = (ArrayList)listeners.clone(); - } - - for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) { - VmListener l = i.next(); - if (ev == null) { - ev = new VmEvent(this); - } - l.monitorsUpdated(ev); - } - } - - /* - * Timer Tasks. There are two separate timer tasks here. The SamplerTask - * is active whenever we are attached to the remote JVM with a periodic - * sampling interval > 0. The NotifierTask is only active if a VmListener - * has registered with this RemoteMonitoredVm instance. Also, in the future - * we may want to run these tasks at different intervals. Currently, - * they run at the same interval and some significant work may - * need to be done to complete the separation of these two intervals. - */ - - /** - * Class to periodically check the state of the defined monitors - * for the remote MonitoredVm instance and to notify listeners of - * any detected changes. - */ - private class NotifierTask extends CountedTimerTask { - public void run() { - super.run(); - try { - MonitorStatus status = getMonitorStatus(); - - List<Monitor> inserted = status.getInserted(); - List<Monitor> removed = status.getRemoved(); - - if (!inserted.isEmpty() || !removed.isEmpty()) { - fireMonitorStatusChangedEvents(inserted, removed); - } - } catch (MonitorException e) { - // XXX: use logging api? fire disconnect events? mark errored? - // fireDisconnectedEvents(); - System.err.println("Exception updating monitors for " - + getVmIdentifier()); - e.printStackTrace(); - // XXX: should we cancle the notifierTask here? - // this.cancel(); - } - } - } - - /** - * Class to periodically sample the remote instrumentation byte buffer - * and refresh the local copy. Registered listeners are notified of - * the completion of a sampling event. - */ - private class SamplerTask extends CountedTimerTask { - public void run() { - super.run(); - try { - sample(); - fireMonitorsUpdatedEvents(); - - } catch (RemoteException e) { - // XXX: use logging api, mark vm as errored. - System.err.println("Exception taking sample for " - + getVmIdentifier()); - e.printStackTrace(); - this.cancel(); - } - } - } -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.jvmstat.perfdata.monitor.protocol.rmi; - -import java.util.*; -import java.util.regex.*; -import java.io.*; -import java.rmi.RemoteException; -import sun.jvmstat.monitor.*; -import sun.jvmstat.monitor.event.*; -import sun.jvmstat.monitor.remote.*; - -/** - * Class for managing the RemoteMonitoredVm instances on a remote system. - * <p> - * This class is responsible for the mechanism that detects the active - * HotSpot Java Virtual Machines on the remote host and possibly for a - * specific user. The ability to detect all possible HotSpot Java Virtual - * Machines on the remote host may be limited by the permissions of the - * principal running the RMI server application on the remote host. - * - * @author Brian Doherty - * @since 1.5 - */ -public class RemoteVmManager { - - private RemoteHost remoteHost; - private String user; - - /** - * Creates a RemoteVmManager instance for the remote system. - * <p> - * Manages RemoteMonitordVm instances for which the principal - * running the remote server has appropriate permissions. - * - * @param remoteHost the remote proxy object to the RMI server on - * the remote system. - */ - public RemoteVmManager(RemoteHost remoteHost) { - this(remoteHost, null); - } - - /** - * Creates a RemoteVmManager instance for the given user. - * <p> - * Manages RemoteMonitoredVm instances for all remote Java Virtual - * machines owned by the specified user on the remote system. The - * RMI server on the remote system must have the appropriate permissions - * to access the named users Java Virtual Machines. - * - * @param remoteHost the remote proxy object to the RMI server on - * the remote system. - * @param user the name of the user - */ - public RemoteVmManager(RemoteHost remoteHost, String user) { - this.user = user; - this.remoteHost = remoteHost; - } - - /** - * Return the current set of monitorable Java Virtual Machines. - * <p> - * The set returned by this method depends on the user name passed - * to the constructor. If no user name was specified, then this - * method will return all candidate JVMs on the system. Otherwise, - * only the JVMs for the given user will be returned. This assumes - * that the RMI server process has the appropriate permissions to - * access the target set of JVMs. - * - * @return Set - the Set of monitorable Java Virtual Machines - */ - public Set<Integer> activeVms() throws MonitorException { - int[] active = null; - - try { - active = remoteHost.activeVms(); - - } catch (RemoteException e) { - throw new MonitorException("Error communicating with remote host: " - + e.getMessage(), e); - } - - Set<Integer> activeSet = new HashSet<Integer>(active.length); - - for (int i = 0; i < active.length; i++) { - activeSet.add(active[i]); - } - - return activeSet; - } -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -<!doctype html public "-//IETF//DTD HTML/EN"> -<html> -<head> -<!-- - - - Copyright (c) 2004, 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. Oracle designates this - particular file as subject to the "Classpath" exception as provided - by Oracle in the LICENSE file that accompanied this code. - - 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. - ---> -</head> -<body bgcolor="white"> -<p> -Provides the implementation classes for the <em>rmi:</em> protocol for -the HotSpot PerfData instrumentation buffer monitoring implementation. -</p> -<p> -The <em>rmi:</em> protocol is the default protocol for the PerfData -implementation when a hostname is specified as part of a HostIdentifier -or VMIdentifier. It communicates with an RMI server on the remote machine -that provides functions to get a list of available Java Virtual Machines -and to acquire a copy of a Java Virtual Machine's instrumentation buffer. -The RMI server may or may not use the PerfData implementation on the -remote host to acquire this information. The <em>jstatd</em> server -provides a PerfData implementation of the RMI server. -</body> -</html>
--- a/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/Jstatd.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.tools.jstatd; - -import java.rmi.*; -import java.rmi.server.*; -import java.rmi.registry.Registry; -import java.rmi.registry.LocateRegistry; -import java.net.MalformedURLException; -import sun.jvmstat.monitor.remote.*; - -/** - * Application providing remote access to the jvmstat instrumentation - * exported by local Java Virtual Machine processes. Remote access is - * provided through an RMI interface. - * - * @author Brian Doherty - * @since 1.5 - */ -public class Jstatd { - - private static Registry registry; - private static int port = -1; - private static boolean startRegistry = true; - - private static void printUsage() { - System.err.println("usage: jstatd [-nr] [-p port] [-n rminame]"); - } - - static void bind(String name, RemoteHostImpl remoteHost) - throws RemoteException, MalformedURLException, Exception { - - try { - Naming.rebind(name, remoteHost); - } catch (java.rmi.ConnectException e) { - /* - * either the registry is not running or we cannot contact it. - * start an internal registry if requested. - */ - if (startRegistry && registry == null) { - int localport = (port < 0) ? Registry.REGISTRY_PORT : port; - registry = LocateRegistry.createRegistry(localport); - bind(name, remoteHost); - } else { - throw e; - } - } - } - - @SuppressWarnings("deprecation") // Use of RMISecurityManager - public static void main(String[] args) { - String rminame = null; - int argc = 0; - - for ( ; (argc < args.length) && (args[argc].startsWith("-")); argc++) { - String arg = args[argc]; - - if (arg.compareTo("-nr") == 0) { - startRegistry = false; - } else if (arg.startsWith("-p")) { - if (arg.compareTo("-p") != 0) { - port = Integer.parseInt(arg.substring(2)); - } else { - argc++; - if (argc >= args.length) { - printUsage(); - System.exit(1); - } - port = Integer.parseInt(args[argc]); - } - } else if (arg.startsWith("-n")) { - if (arg.compareTo("-n") != 0) { - rminame = arg.substring(2); - } else { - argc++; - if (argc >= args.length) { - printUsage(); - System.exit(1); - } - rminame = args[argc]; - } - } else { - printUsage(); - System.exit(1); - } - } - - if (argc < args.length) { - printUsage(); - System.exit(1); - } - - if (System.getSecurityManager() == null) { - System.setSecurityManager(new RMISecurityManager()); - } - - StringBuilder name = new StringBuilder(); - - if (port >= 0) { - name.append("//:").append(port); - } - - if (rminame == null) { - rminame = "JStatRemoteHost"; - } - - name.append("/").append(rminame); - - try { - // use 1.5.0 dynamically generated subs. - System.setProperty("java.rmi.server.ignoreSubClasses", "true"); - RemoteHostImpl remoteHost = new RemoteHostImpl(); - RemoteHost stub = (RemoteHost) UnicastRemoteObject.exportObject( - remoteHost, 0); - bind(name.toString(), remoteHost); - System.out.println("jstatd started (bound to " + name.toString() + ")"); - System.out.flush(); - } catch (MalformedURLException e) { - if (rminame != null) { - System.out.println("Bad RMI server name: " + rminame); - } else { - System.out.println("Bad RMI URL: " + name); - } - e.printStackTrace(System.out); - System.exit(1); - } catch (java.rmi.ConnectException e) { - // could not attach to or create a registry - System.out.println("Could not contact RMI registry"); - e.printStackTrace(System.out); - System.exit(1); - } catch (RemoteException e) { - System.out.println("Could not bind " + name + " to RMI Registry"); - e.printStackTrace(System.out); - System.exit(1); - } catch (Exception e) { - System.out.println("Could not create remote object"); - e.printStackTrace(System.out); - System.exit(1); - } - } -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteHostImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.tools.jstatd; - -import java.util.*; -import java.nio.*; -import java.io.*; -import java.net.*; -import java.rmi.*; -import java.rmi.server.*; -import sun.jvmstat.monitor.*; -import sun.jvmstat.monitor.event.*; -import sun.jvmstat.monitor.remote.*; - -/** - * Concrete implementation of the RemoteHost interface for the HotSpot - * PerfData <em>rmi:</em> protocol. - * <p> - * This class provides remote access to the instrumentation exported - * by HotSpot Java Virtual Machines through the PerfData shared memory - * interface. - * - * @author Brian Doherty - * @since 1.5 - */ -public class RemoteHostImpl implements RemoteHost, HostListener { - - private MonitoredHost monitoredHost; - private Set<Integer> activeVms; - - public RemoteHostImpl() throws MonitorException { - try { - monitoredHost = MonitoredHost.getMonitoredHost("localhost"); - } catch (URISyntaxException e) { } - - activeVms = monitoredHost.activeVms(); - monitoredHost.addHostListener(this); - } - - public RemoteVm attachVm(int lvmid, String mode) - throws RemoteException, MonitorException { - Integer v = lvmid; - RemoteVm stub = null; - StringBuilder sb = new StringBuilder(); - - sb.append("local://").append(lvmid).append("@localhost"); - if (mode != null) { - sb.append("?mode=").append(mode); - } - - String vmidStr = sb.toString(); - - try { - VmIdentifier vmid = new VmIdentifier(vmidStr); - MonitoredVm mvm = monitoredHost.getMonitoredVm(vmid); - RemoteVmImpl rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm); - stub = (RemoteVm) UnicastRemoteObject.exportObject(rvm, 0); - } - catch (URISyntaxException e) { - throw new RuntimeException("Malformed VmIdentifier URI: " - + vmidStr, e); - } - return stub; - } - - public void detachVm(RemoteVm rvm) throws RemoteException { - rvm.detach(); - } - - public int[] activeVms() throws MonitorException { - Object[] vms = null; - int[] vmids = null; - - vms = monitoredHost.activeVms().toArray(); - vmids = new int[vms.length]; - - for (int i = 0; i < vmids.length; i++) { - vmids[i] = ((Integer)vms[i]).intValue(); - } - return vmids; - } - - public void vmStatusChanged(VmStatusChangeEvent ev) { - synchronized(this.activeVms) { - activeVms.retainAll(ev.getActive()); - } - } - - public void disconnected(HostEvent ev) { - // we only monitor the local host, so this event shouldn't occur. - } -}
--- a/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteVmImpl.java Thu Apr 28 00:38:21 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package sun.tools.jstatd; - -import sun.jvmstat.monitor.*; -import sun.jvmstat.monitor.remote.*; - -/** - * Concrete implementation of the RemoteVm interface for the HotSpot PerfData - * shared memory implementation of the jvmstat monitoring APIs. This class - * providing remote access to the instrumentation exported by a local HotSpot - * Java Virtual Machine. The instrumentation buffer is shipped in whole to - * the remote machine, which is responsible for parsing and provide access - * to the contained data. - * - * @author Brian Doherty - * @since 1.5 - */ -public class RemoteVmImpl implements RemoteVm { - - private BufferedMonitoredVm mvm; - - RemoteVmImpl(BufferedMonitoredVm mvm) { - this.mvm = mvm; - } - - public byte[] getBytes() { - return mvm.getBytes(); - } - - public int getCapacity() { - return mvm.getCapacity(); - } - - public void detach() { - mvm.detach(); - } - - public int getLocalVmId() { - return mvm.getVmIdentifier().getLocalVmId(); - } -}
--- a/src/jdk.jvmstat/share/classes/module-info.java Thu Apr 28 00:38:21 2016 -0700 +++ b/src/jdk.jvmstat/share/classes/module-info.java Thu Apr 28 23:08:17 2016 -0700 @@ -28,12 +28,12 @@ jdk.attach, jdk.jcmd, jdk.jconsole, - jdk.jvmstat.rmi; + jdk.jstatd; exports sun.jvmstat.monitor.event to jdk.jcmd, - jdk.jvmstat.rmi; + jdk.jstatd; exports sun.jvmstat.perfdata.monitor to - jdk.jvmstat.rmi; + jdk.jstatd; uses sun.jvmstat.monitor.MonitoredHostService; provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.file.MonitoredHostFileService;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.net; + +import java.io.FileDescriptor; +import java.net.SocketException; +import java.net.SocketOption; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.Set; +import jdk.internal.misc.JavaIOFileDescriptorAccess; +import jdk.internal.misc.SharedSecrets; + +/** + * Defines extended socket options, beyond those defined in + * {@link java.net.StandardSocketOptions}. These options may be platform + * specific. + * + * @since 1.8 + */ +public final class ExtendedSocketOptions { + + private static class ExtSocketOption<T> implements SocketOption<T> { + private final String name; + private final Class<T> type; + ExtSocketOption(String name, Class<T> type) { + this.name = name; + this.type = type; + } + @Override public String name() { return name; } + @Override public Class<T> type() { return type; } + @Override public String toString() { return name; } + } + + private ExtendedSocketOptions() { } + + /** + * Service level properties. When a security manager is installed, + * setting or getting this option requires a {@link NetworkPermission} + * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"} + * respectively. + */ + public static final SocketOption<SocketFlow> SO_FLOW_SLA = new + ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class); + + + private static final PlatformSocketOptions platformSocketOptions = + PlatformSocketOptions.get(); + + private static final boolean flowSupported = + platformSocketOptions.flowSupported(); + + private static final Set<SocketOption<?>> extendedOptions = options(); + + static Set<SocketOption<?>> options() { + if (flowSupported) + return Set.of(SO_FLOW_SLA); + else + return Collections.<SocketOption<?>>emptySet(); + } + + static { + // Registers the extended socket options with the base module. + sun.net.ext.ExtendedSocketOptions.register( + new sun.net.ext.ExtendedSocketOptions(extendedOptions) { + + @Override + public void setOption(FileDescriptor fd, + SocketOption<?> option, + Object value) + throws SocketException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new NetworkPermission("setOption." + option.name())); + + if (fd == null || !fd.valid()) + throw new SocketException("socket closed"); + + if (option == SO_FLOW_SLA) { + assert flowSupported; + SocketFlow flow = checkValueType(value, option.type()); + setFlowOption(fd, flow); + } else { + throw new InternalError("Unexpected option " + option); + } + } + + @Override + public Object getOption(FileDescriptor fd, + SocketOption<?> option) + throws SocketException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new NetworkPermission("getOption." + option.name())); + + if (fd == null || !fd.valid()) + throw new SocketException("socket closed"); + + if (option == SO_FLOW_SLA) { + assert flowSupported; + SocketFlow flow = SocketFlow.create(); + getFlowOption(fd, flow); + return flow; + } else { + throw new InternalError("Unexpected option " + option); + } + } + }); + } + + @SuppressWarnings("unchecked") + private static <T> T checkValueType(Object value, Class<?> type) { + if (!type.isAssignableFrom(value.getClass())) { + String s = "Found: " + value.getClass() + ", Expected: " + type; + throw new IllegalArgumentException(s); + } + return (T) value; + } + + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + + private static void setFlowOption(FileDescriptor fd, SocketFlow f) + throws SocketException + { + int status = platformSocketOptions.setFlowOption(fdAccess.get(fd), + f.priority(), + f.bandwidth()); + f.status(status); // augment the given flow with the status + } + + private static void getFlowOption(FileDescriptor fd, SocketFlow f) + throws SocketException + { + int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f); + f.status(status); // augment the given flow with the status + } + + static class PlatformSocketOptions { + + protected PlatformSocketOptions() {} + + @SuppressWarnings("unchecked") + private static PlatformSocketOptions newInstance(String cn) { + Class<PlatformSocketOptions> c; + try { + c = (Class<PlatformSocketOptions>)Class.forName(cn); + return c.getConstructor(new Class<?>[] { }).newInstance(); + } catch (ReflectiveOperationException x) { + throw new AssertionError(x); + } + } + + private static PlatformSocketOptions create() { + String osname = AccessController.doPrivileged( + new PrivilegedAction<String>() { + public String run() { + return System.getProperty("os.name"); + } + }); + if ("SunOS".equals(osname)) + return newInstance("jdk.net.SolarisSocketOptions"); + return new PlatformSocketOptions(); + } + + private static final PlatformSocketOptions instance = create(); + + static PlatformSocketOptions get() { + return instance; + } + + int setFlowOption(int fd, int priority, long bandwidth) + throws SocketException + { + throw new UnsupportedOperationException("unsupported socket option"); + } + + int getFlowOption(int fd, SocketFlow f) throws SocketException { + throw new UnsupportedOperationException("unsupported socket option"); + } + + boolean flowSupported() { + return false; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.net/share/classes/jdk/net/NetworkPermission.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.net; + +import java.security.BasicPermission; + +/** + * Represents permission to access the extended networking capabilities + * defined in the jdk.net package. These permissions contain a target + * name, but no actions list. Callers either possess the permission or not. + * <p> + * The following targets are defined: + * + * <table border=1 cellpadding=5 summary="permission target name, + * what the target allows,and associated risks"> + * <tr> + * <th>Permission Target Name</th> + * <th>What the Permission Allows</th> + * <th>Risks of Allowing this Permission</th> + * </tr> + * <tr> + * <td>setOption.SO_FLOW_SLA</td> + * <td>set the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option + * on any socket that supports it</td> + * <td>allows caller to set a higher priority or bandwidth allocation + * to sockets it creates, than they might otherwise be allowed.</td> + * </tr> + * <tr> + * <td>getOption.SO_FLOW_SLA</td> + * <td>retrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} + * setting from any socket that supports the option</td> + * <td>allows caller access to SLA information that it might not + * otherwise have</td> + * </tr></table> + * + * @see jdk.net.ExtendedSocketOptions + * + * @since 1.8 + */ + +public final class NetworkPermission extends BasicPermission { + + private static final long serialVersionUID = -2012939586906722291L; + + /** + * Creates a NetworkPermission with the given target name. + * + * @param name the permission target name + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. + */ + public NetworkPermission(String name) + { + super(name); + } + + /** + * Creates a NetworkPermission with the given target name. + * + * @param name the permission target name + * @param actions should be {@code null}. Is ignored if not. + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. + */ + public NetworkPermission(String name, String actions) + { + super(name, actions); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.net/share/classes/jdk/net/SocketFlow.java Thu Apr 28 23:08:17 2016 -0700 @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.net; + +import java.lang.annotation.Native; + +/** + * Represents the service level properties for the platform specific socket + * option {@link ExtendedSocketOptions#SO_FLOW_SLA}. + * <p> + * The priority and bandwidth parameters must be set before + * setting the socket option. + * <p> + * When the {@code SO_FLOW_SLA} option is set then it may not take effect + * immediately. If the value of the socket option is obtained with + * {@code getOption()} then the status may be returned as {@code INPROGRESS} + * until it takes effect. The priority and bandwidth values are only valid when + * the status is returned as OK. + * <p> + * When a security manager is installed, a {@link NetworkPermission} + * is required to set or get this option. + * + * @since 1.8 + */ +public class SocketFlow { + + @Native public static final int UNSET = -1; + @Native public static final int NORMAL_PRIORITY = 1; + @Native public static final int HIGH_PRIORITY = 2; + + @Native private static final int NO_STATUS_VALUE = 0; + @Native private static final int OK_VALUE = 1; + @Native private static final int NO_PERMISSION_VALUE = 2; + @Native private static final int NOT_CONNECTED_VALUE = 3; + @Native private static final int NOT_SUPPORTED_VALUE = 4; + @Native private static final int ALREADY_CREATED_VALUE = 5; + @Native private static final int IN_PROGRESS_VALUE = 6; + @Native private static final int OTHER_VALUE = 7; + + /** + * Enumeration of the return values from the SO_FLOW_SLA + * socket option. Both setting and getting the option return + * one of these statuses, which reflect the state of socket's + * flow. + * + * @since 1.8 + */ + public enum Status { + /** + * Set or get socket option has not been called yet. Status + * values can only be retrieved after calling set or get. + */ + NO_STATUS(NO_STATUS_VALUE), + /** + * Flow successfully created. + */ + OK(OK_VALUE), + /** + * Caller has no permission to create flow. + */ + NO_PERMISSION(NO_PERMISSION_VALUE), + /** + * Flow can not be created because socket is not connected. + */ + NOT_CONNECTED(NOT_CONNECTED_VALUE), + /** + * Flow creation not supported for this socket. + */ + NOT_SUPPORTED(NOT_SUPPORTED_VALUE), + /** + * A flow already exists with identical attributes. + */ + ALREADY_CREATED(ALREADY_CREATED_VALUE), + /** + * A flow is being created. + */ + IN_PROGRESS(IN_PROGRESS_VALUE), + /** + * Some other unspecified error. + */ + OTHER(OTHER_VALUE); + + private final int value; + Status(int value) { this.value = value; } + + static Status from(int value) { + if (value == NO_STATUS.value) return NO_STATUS; + else if (value == OK.value) return OK; + else if (