OpenJDK / bsd-port / jdk9 / jdk
changeset 16660:955d8b6ded80
Merge
author | jwilhelm |
---|---|
date | Tue, 24 Jan 2017 00:30:25 +0100 |
parents | 33e6f9b9e3b5 fb36a29be4a3 |
children | 0eb0f644345d ba1d4f8c77de 07739d8a2680 |
files | src/java.base/share/classes/module-info.java src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java src/linux/doc/man/ja/jvisualvm.1 src/linux/doc/man/jvisualvm.1 src/solaris/doc/sun/man/man1/ja/jvisualvm.1 src/solaris/doc/sun/man/man1/jvisualvm.1 test/ProblemList.txt test/java/lang/SecurityManager/RestrictedPackages.java test/java/rmi/registry/readTest/readTest.java test/java/rmi/registry/readTest/readTest.sh test/lib/security/SecurityTools.java test/tools/jar/mmrjar/ConcealedPackage.java test/tools/jmod/hashes/src/m1/module-info.java test/tools/jmod/hashes/src/m1/org/m1/Main.java test/tools/jmod/hashes/src/m2/module-info.java test/tools/jmod/hashes/src/m2/org/m2/Util.java test/tools/jmod/hashes/src/m3/module-info.java test/tools/jmod/hashes/src/m3/org/m3/Name.java test/tools/jmod/hashes/src/org.bar/module-info.java test/tools/jmod/hashes/src/org.foo/module-info.java test/tools/launcher/VersionCheck.java |
diffstat | 402 files changed, 15020 insertions(+), 10812 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed Jan 25 15:31:01 2017 +0530 +++ b/.hgtags Tue Jan 24 00:30:25 2017 +0100 @@ -394,3 +394,5 @@ 5a846396a24c7aff01d6a8feaa7afc0a6369f04d jdk-9+149 71e198ef3839045e829a879af1d709be16ab0f88 jdk-9+150 d27bab22ff62823902d93d1d35ca397cfd50d059 jdk-9+151 +a20f2cf90762673e1bc4980fd6597e70a2578045 jdk-9+152 +1c4411322327aea3f91011ec3977a12a05b09629 jdk-9+153
--- a/make/CompileModuleTools.gmk Wed Jan 25 15:31:01 2017 +0530 +++ b/make/CompileModuleTools.gmk Tue Jan 24 00:30:25 2017 +0100 @@ -37,6 +37,5 @@ build/tools/jigsaw, \ BIN := $(TOOLS_CLASSES_DIR), \ ADD_JAVAC_FLAGS := \ - --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \ --add-exports java.base/jdk.internal.module=ALL-UNNAMED \ ))
--- a/make/ModuleTools.gmk Wed Jan 25 15:31:01 2017 +0530 +++ b/make/ModuleTools.gmk Tue Jan 24 00:30:25 2017 +0100 @@ -39,7 +39,6 @@ build.tools.jigsaw.GenGraphs TOOL_MODULESUMMARY := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \ - --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \ build.tools.jigsaw.ModuleSummary TOOL_ADD_PACKAGES_ATTRIBUTE := $(BUILD_JAVA) $(JAVA_FLAGS_SMALL) \
--- a/make/data/fontconfig/solaris.fontconfig.properties Wed Jan 25 15:31:01 2017 +0530 +++ b/make/data/fontconfig/solaris.fontconfig.properties Tue Jan 24 00:30:25 2017 +0100 @@ -436,15 +436,15 @@ filename.-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arial.ttf filename.-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/ariali.ttf -filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialb.ttf +filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbd.ttf filename.-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbi.ttf filename.-monotype-courier_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cour.ttf filename.-monotype-courier_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/couri.ttf -filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courb.ttf +filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbd.ttf filename.-monotype-courier_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbi.ttf filename.-monotype-times_new_roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/times.ttf filename.-monotype-times_new_roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesi.ttf -filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesb.ttf +filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbd.ttf filename.-monotype-times_new_roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbi.ttf filename.-monotype-angsana_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsa.ttf
--- a/make/lib/Awt2dLibraries.gmk Wed Jan 25 15:31:01 2017 +0530 +++ b/make/lib/Awt2dLibraries.gmk Tue Jan 24 00:30:25 2017 +0100 @@ -222,6 +222,8 @@ # applies to debug builds. ifeq ($(TOOLCHAIN_TYPE), gcc) BUILD_LIBAWT_debug_mem.c_CFLAGS := -w + # This option improves performance of MaskFill in Java2D by 20% for some gcc + LIBAWT_CFLAGS += -fgcse-after-reload endif $(eval $(call SetupNativeCompilation,BUILD_LIBAWT, \
--- a/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Tue Jan 24 00:30:25 2017 +0100 @@ -69,6 +69,10 @@ /** * Returns the server's X.509 certificate chain, or null if * the server did not authenticate. + * <P> + * Note: The returned value may not be a valid certificate chain + * and should not be relied on for trust decisions. + * * @return the server certificate chain */ public abstract Certificate[] getServerCertificates()
--- a/src/java.base/share/classes/java/io/File.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/io/File.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2017, 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 @@ -1962,6 +1962,9 @@ name = sb.toString(); } + // Normalize the path component + name = fs.normalize(name); + File f = new File(dir, name); if (!name.equals(f.getName()) || f.isInvalid()) { if (System.getSecurityManager() != null)
--- a/src/java.base/share/classes/java/lang/Class.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/lang/Class.java Tue Jan 24 00:30:25 2017 +0100 @@ -508,8 +508,9 @@ public T newInstance() throws InstantiationException, IllegalAccessException { - if (System.getSecurityManager() != null) { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false); } // NOTE: the following code may not be strictly correct under @@ -1223,38 +1224,27 @@ // Perform access check final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass(); - enclosingCandidate.checkMemberAccess(Member.DECLARED, - Reflection.getCallerClass(), true); - // Client is ok to access declared methods but j.l.Class might not be. - Method[] candidates = AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public Method[] run() { - return enclosingCandidate.getDeclaredMethods(); - } - }); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + enclosingCandidate.checkMemberAccess(sm, Member.DECLARED, + Reflection.getCallerClass(), true); + } + Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false); + /* * Loop over all declared methods; match method name, * number of and type of parameters, *and* return * type. Matching return type is also necessary * because of covariant returns, etc. */ - for(Method m: candidates) { - if (m.getName().equals(enclosingInfo.getName()) ) { - Class<?>[] candidateParamClasses = m.getParameterTypes(); - if (candidateParamClasses.length == parameterClasses.length) { - boolean matches = true; - for(int i = 0; i < candidateParamClasses.length; i++) { - if (!candidateParamClasses[i].equals(parameterClasses[i])) { - matches = false; - break; - } - } - - if (matches) { // finally, check return type - if (m.getReturnType().equals(returnType) ) - return m; - } + ReflectionFactory fact = getReflectionFactory(); + for (Method m : candidates) { + if (m.getName().equals(enclosingInfo.getName()) && + arrayContentsEq(parameterClasses, + fact.getExecutableSharedParameterTypes(m))) { + // finally, check return type + if (m.getReturnType().equals(returnType)) { + return fact.copyMethod(m); } } } @@ -1390,33 +1380,23 @@ // Perform access check final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass(); - enclosingCandidate.checkMemberAccess(Member.DECLARED, - Reflection.getCallerClass(), true); - // Client is ok to access declared methods but j.l.Class might not be. - Constructor<?>[] candidates = AccessController.doPrivileged( - new PrivilegedAction<>() { - @Override - public Constructor<?>[] run() { - return enclosingCandidate.getDeclaredConstructors(); - } - }); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + enclosingCandidate.checkMemberAccess(sm, Member.DECLARED, + Reflection.getCallerClass(), true); + } + + Constructor<?>[] candidates = enclosingCandidate + .privateGetDeclaredConstructors(false); /* * Loop over all declared constructors; match number * of and type of parameters. */ - for(Constructor<?> c: candidates) { - Class<?>[] candidateParamClasses = c.getParameterTypes(); - if (candidateParamClasses.length == parameterClasses.length) { - boolean matches = true; - for(int i = 0; i < candidateParamClasses.length; i++) { - if (!candidateParamClasses[i].equals(parameterClasses[i])) { - matches = false; - break; - } - } - - if (matches) - return c; + ReflectionFactory fact = getReflectionFactory(); + for (Constructor<?> c : candidates) { + if (arrayContentsEq(parameterClasses, + fact.getExecutableSharedParameterTypes(c))) { + return fact.copyConstructor(c); } } @@ -1446,9 +1426,13 @@ public Class<?> getDeclaringClass() throws SecurityException { final Class<?> candidate = getDeclaringClass0(); - if (candidate != null) - candidate.checkPackageAccess( + if (candidate != null) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + candidate.checkPackageAccess(sm, ClassLoader.getClassLoader(Reflection.getCallerClass()), true); + } + } return candidate; } @@ -1496,9 +1480,13 @@ enclosingCandidate = enclosingClass; } - if (enclosingCandidate != null) - enclosingCandidate.checkPackageAccess( + if (enclosingCandidate != null) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + enclosingCandidate.checkPackageAccess(sm, ClassLoader.getClassLoader(Reflection.getCallerClass()), true); + } + } return enclosingCandidate; } @@ -1688,7 +1676,10 @@ */ @CallerSensitive public Class<?>[] getClasses() { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false); + } // Privileged so this implementation can look at DECLARED classes, // something the caller might not have privilege to do. The code here @@ -1754,7 +1745,10 @@ */ @CallerSensitive public Field[] getFields() throws SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); + } return copyFields(privateGetPublicFields(null)); } @@ -1841,7 +1835,10 @@ */ @CallerSensitive public Method[] getMethods() throws SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); + } return copyMethods(privateGetPublicMethods()); } @@ -1877,7 +1874,10 @@ */ @CallerSensitive public Constructor<?>[] getConstructors() throws SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); + } return copyConstructors(privateGetDeclaredConstructors(true)); } @@ -1928,7 +1928,10 @@ public Field getField(String name) throws NoSuchFieldException, SecurityException { Objects.requireNonNull(name); - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); + } Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); @@ -2034,10 +2037,13 @@ public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { Objects.requireNonNull(name); - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); + } Method method = getMethod0(name, parameterTypes); if (method == null) { - throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); + throw new NoSuchMethodException(methodToString(name, parameterTypes)); } return getReflectionFactory().copyMethod(method); } @@ -2092,8 +2098,12 @@ */ @CallerSensitive public Constructor<T> getConstructor(Class<?>... parameterTypes) - throws NoSuchMethodException, SecurityException { - checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); + throws NoSuchMethodException, SecurityException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true); + } return getReflectionFactory().copyConstructor( getConstructor0(parameterTypes, Member.PUBLIC)); } @@ -2136,7 +2146,10 @@ */ @CallerSensitive public Class<?>[] getDeclaredClasses() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), false); + } return getDeclaredClasses0(); } @@ -2185,7 +2198,10 @@ */ @CallerSensitive public Field[] getDeclaredFields() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); + } return copyFields(privateGetDeclaredFields(false)); } @@ -2244,7 +2260,10 @@ */ @CallerSensitive public Method[] getDeclaredMethods() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); + } return copyMethods(privateGetDeclaredMethods(false)); } @@ -2289,7 +2308,10 @@ */ @CallerSensitive public Constructor<?>[] getDeclaredConstructors() throws SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); + } return copyConstructors(privateGetDeclaredConstructors(false)); } @@ -2338,7 +2360,10 @@ public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException { Objects.requireNonNull(name); - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); + } Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); @@ -2399,10 +2424,13 @@ public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { Objects.requireNonNull(name); - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); + } Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { - throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); + throw new NoSuchMethodException(methodToString(name, parameterTypes)); } return getReflectionFactory().copyMethod(method); } @@ -2448,8 +2476,13 @@ */ @CallerSensitive public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) - throws NoSuchMethodException, SecurityException { - checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); + throws NoSuchMethodException, SecurityException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true); + } + return getReflectionFactory().copyConstructor( getConstructor0(parameterTypes, Member.DECLARED)); } @@ -2697,51 +2730,49 @@ * * <p> Default policy: allow all clients access with normal Java access * control. + * + * <p> NOTE: should only be called if a SecurityManager is installed */ - private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) { - final SecurityManager s = System.getSecurityManager(); - if (s != null) { - /* Default policy allows access to all {@link Member#PUBLIC} members, - * as well as access to classes that have the same class loader as the caller. - * In all other cases, it requires RuntimePermission("accessDeclaredMembers") - * permission. - */ - final ClassLoader ccl = ClassLoader.getClassLoader(caller); + private void checkMemberAccess(SecurityManager sm, int which, + Class<?> caller, boolean checkProxyInterfaces) { + /* Default policy allows access to all {@link Member#PUBLIC} members, + * as well as access to classes that have the same class loader as the caller. + * In all other cases, it requires RuntimePermission("accessDeclaredMembers") + * permission. + */ + final ClassLoader ccl = caller.getClassLoader0(); + if (which != Member.PUBLIC) { final ClassLoader cl = getClassLoader0(); - if (which != Member.PUBLIC) { - if (ccl != cl) { - s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); - } + if (ccl != cl) { + sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); } - this.checkPackageAccess(ccl, checkProxyInterfaces); } + this.checkPackageAccess(sm, ccl, checkProxyInterfaces); } /* * Checks if a client loaded in ClassLoader ccl is allowed to access this * class under the current package access policy. If access is denied, * throw a SecurityException. + * + * NOTE: this method should only be called if a SecurityManager is active */ - private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) { - final SecurityManager s = System.getSecurityManager(); - if (s != null) { - final ClassLoader cl = getClassLoader0(); - - if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { - String name = this.getName(); - int i = name.lastIndexOf('.'); - if (i != -1) { - // skip the package access check on a proxy class in default proxy package - String pkg = name.substring(0, i); - if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { - s.checkPackageAccess(pkg); - } + private void checkPackageAccess(SecurityManager sm, final ClassLoader ccl, + boolean checkProxyInterfaces) { + final ClassLoader cl = getClassLoader0(); + + if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { + String pkg = this.getPackageName(); + if (pkg != null && !pkg.isEmpty()) { + // skip the package access check on a proxy class in default proxy package + if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { + sm.checkPackageAccess(pkg); } } - // check package access on the proxy interfaces - if (checkProxyInterfaces && Proxy.isProxyClass(this)) { - ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); - } + } + // check package access on the proxy interfaces + if (checkProxyInterfaces && Proxy.isProxyClass(this)) { + ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); } } @@ -2755,11 +2786,9 @@ while (c.isArray()) { c = c.getComponentType(); } - String baseName = c.getName(); - int index = baseName.lastIndexOf('.'); - if (index != -1) { - name = baseName.substring(0, index).replace('.', '/') - +"/"+name; + String baseName = c.getPackageName(); + if (baseName != null && !baseName.isEmpty()) { + name = baseName.replace('.', '/') + "/" + name; } } else { name = name.substring(1); @@ -3233,7 +3262,7 @@ return constructor; } } - throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); + throw new NoSuchMethodException(methodToString("<init>", parameterTypes)); } // @@ -3294,8 +3323,11 @@ private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly); private native Class<?>[] getDeclaredClasses0(); - private static String argumentTypesToString(Class<?>[] argTypes) { - StringJoiner sj = new StringJoiner(", ", "(", ")"); + /** + * Helper method to get the method name from arguments. + */ + private String methodToString(String name, Class<?>[] argTypes) { + StringJoiner sj = new StringJoiner(", ", getName() + "." + name + "(", ")"); if (argTypes != null) { for (int i = 0; i < argTypes.length; i++) { Class<?> c = argTypes[i];
--- a/src/java.base/share/classes/java/lang/SecurityManager.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/lang/SecurityManager.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2017, 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 @@ -25,18 +25,30 @@ package java.lang; -import java.security.*; +import java.lang.RuntimePermission; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Exports; +import java.lang.module.ModuleDescriptor.Opens; +import java.lang.reflect.Layer; +import java.lang.reflect.Member; +import java.lang.reflect.Module; import java.io.FileDescriptor; import java.io.File; import java.io.FilePermission; +import java.net.InetAddress; +import java.net.SocketPermission; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; +import java.security.Security; +import java.security.SecurityPermission; +import java.util.HashSet; +import java.util.Objects; import java.util.PropertyPermission; -import java.lang.RuntimePermission; -import java.net.SocketPermission; -import java.net.NetPermission; -import java.util.Hashtable; -import java.net.InetAddress; -import java.lang.reflect.*; -import java.net.URL; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import jdk.internal.reflect.CallerSensitive; import sun.security.util.SecurityConstants; @@ -1415,46 +1427,108 @@ } } - if (packages == null) + if (packages == null) { packages = new String[0]; + } return packages; } + // The non-exported packages of the modules in the boot layer that are + // loaded by the platform class loader or its ancestors. A non-exported + // package is a package that either is not exported at all by its containing + // module or is exported in a qualified fashion by its containing module. + private static final Set<String> nonExportedPkgs; + + static { + // Get the modules in the boot layer + Stream<Module> bootLayerModules = Layer.boot().modules().stream(); + + // Filter out the modules loaded by the boot or platform loader + PrivilegedAction<Set<Module>> pa = () -> + bootLayerModules.filter(SecurityManager::isBootOrPlatformModule) + .collect(Collectors.toSet()); + Set<Module> modules = AccessController.doPrivileged(pa); + + // Filter out the non-exported packages + nonExportedPkgs = modules.stream() + .map(Module::getDescriptor) + .map(SecurityManager::nonExportedPkgs) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + } + /** - * Throws a <code>SecurityException</code> if the - * calling thread is not allowed to access the package specified by - * the argument. + * Returns true if the module's loader is the boot or platform loader. + */ + private static boolean isBootOrPlatformModule(Module m) { + return m.getClassLoader() == null || + m.getClassLoader() == ClassLoader.getPlatformClassLoader(); + } + + /** + * Returns the non-exported packages of the specified module. + */ + private static Set<String> nonExportedPkgs(ModuleDescriptor md) { + // start with all packages in the module + Set<String> pkgs = new HashSet<>(md.packages()); + + // remove the non-qualified exported packages + md.exports().stream() + .filter(p -> !p.isQualified()) + .map(Exports::source) + .forEach(pkgs::remove); + + // remove the non-qualified open packages + md.opens().stream() + .filter(p -> !p.isQualified()) + .map(Opens::source) + .forEach(pkgs::remove); + + return pkgs; + } + + /** + * Throws a {@code SecurityException} if the calling thread is not allowed + * to access the specified package. * <p> - * This method is used by the <code>loadClass</code> method of class - * loaders. + * This method is called by the {@code loadClass} method of class loaders. * <p> - * This method first gets a list of - * restricted packages by obtaining a comma-separated list from - * a call to - * <code>java.security.Security.getProperty("package.access")</code>, - * and checks to see if <code>pkg</code> starts with or equals - * any of the restricted packages. If it does, then - * <code>checkPermission</code> gets called with the - * <code>RuntimePermission("accessClassInPackage."+pkg)</code> - * permission. + * This method checks if the specified package starts with or equals + * any of the packages in the {@code package.access} Security Property. + * An implementation may also check the package against an additional + * list of restricted packages as noted below. If the package is restricted, + * {@link #checkPermission(Permission)} is called with a + * {@code RuntimePermission("accessClassInPackage."+pkg)} permission. * <p> - * If this method is overridden, then - * <code>super.checkPackageAccess</code> should be called - * as the first line in the overridden method. + * If this method is overridden, then {@code super.checkPackageAccess} + * should be called as the first line in the overridden method. + * + * @implNote + * This implementation also restricts all non-exported packages of modules + * loaded by {@linkplain ClassLoader#getPlatformClassLoader + * the platform class loader} or its ancestors. A "non-exported package" + * refers to a package that is not exported to all modules. Specifically, + * it refers to a package that either is not exported at all by its + * containing module or is exported in a qualified fashion by its + * containing module. * * @param pkg the package name. - * @exception SecurityException if the calling thread does not have + * @throws SecurityException if the calling thread does not have * permission to access the specified package. - * @exception NullPointerException if the package name argument is - * <code>null</code>. - * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) - * loadClass + * @throws NullPointerException if the package name argument is + * {@code null}. + * @see java.lang.ClassLoader#loadClass(String, boolean) loadClass * @see java.security.Security#getProperty getProperty - * @see #checkPermission(java.security.Permission) checkPermission + * @see #checkPermission(Permission) checkPermission */ public void checkPackageAccess(String pkg) { - if (pkg == null) { - throw new NullPointerException("package name can't be null"); + Objects.requireNonNull(pkg, "package name can't be null"); + + // check if pkg is not exported to all modules + if (nonExportedPkgs.contains(pkg)) { + checkPermission( + new RuntimePermission("accessClassInPackage." + pkg)); + return; } String[] restrictedPkgs; @@ -1512,36 +1586,48 @@ } /** - * Throws a <code>SecurityException</code> if the - * calling thread is not allowed to define classes in the package - * specified by the argument. + * Throws a {@code SecurityException} if the calling thread is not + * allowed to define classes in the specified package. * <p> - * This method is used by the <code>loadClass</code> method of some + * This method is called by the {@code loadClass} method of some * class loaders. * <p> - * This method first gets a list of restricted packages by - * obtaining a comma-separated list from a call to - * <code>java.security.Security.getProperty("package.definition")</code>, - * and checks to see if <code>pkg</code> starts with or equals - * any of the restricted packages. If it does, then - * <code>checkPermission</code> gets called with the - * <code>RuntimePermission("defineClassInPackage."+pkg)</code> - * permission. + * This method checks if the specified package starts with or equals + * any of the packages in the {@code package.definition} Security + * Property. An implementation may also check the package against an + * additional list of restricted packages as noted below. If the package + * is restricted, {@link #checkPermission(Permission)} is called with a + * {@code RuntimePermission("defineClassInPackage."+pkg)} permission. * <p> - * If this method is overridden, then - * <code>super.checkPackageDefinition</code> should be called - * as the first line in the overridden method. + * If this method is overridden, then {@code super.checkPackageDefinition} + * should be called as the first line in the overridden method. + * + * @implNote + * This implementation also restricts all non-exported packages of modules + * loaded by {@linkplain ClassLoader#getPlatformClassLoader + * the platform class loader} or its ancestors. A "non-exported package" + * refers to a package that is not exported to all modules. Specifically, + * it refers to a package that either is not exported at all by its + * containing module or is exported in a qualified fashion by its + * containing module. * * @param pkg the package name. - * @exception SecurityException if the calling thread does not have + * @throws SecurityException if the calling thread does not have * permission to define classes in the specified package. - * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) + * @throws NullPointerException if the package name argument is + * {@code null}. + * @see java.lang.ClassLoader#loadClass(String, boolean) * @see java.security.Security#getProperty getProperty - * @see #checkPermission(java.security.Permission) checkPermission + * @see #checkPermission(Permission) checkPermission */ public void checkPackageDefinition(String pkg) { - if (pkg == null) { - throw new NullPointerException("package name can't be null"); + Objects.requireNonNull(pkg, "package name can't be null"); + + // check if pkg is not exported to all modules + if (nonExportedPkgs.contains(pkg)) { + checkPermission( + new RuntimePermission("defineClassInPackage." + pkg)); + return; } String[] pkgs;
--- a/src/java.base/share/classes/java/lang/System.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/lang/System.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2017, 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 @@ -310,12 +310,13 @@ * @see SecurityManager#checkPermission * @see java.lang.RuntimePermission */ - public static - void setSecurityManager(final SecurityManager s) { - try { - s.checkPackageAccess("java.lang"); - } catch (Exception e) { - // no-op + public static void setSecurityManager(final SecurityManager s) { + if (s != null) { + try { + s.checkPackageAccess("java.lang"); + } catch (Exception e) { + // no-op + } } setSecurityManager0(s); }
--- a/src/java.base/share/classes/java/lang/invoke/CallSite.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/lang/invoke/CallSite.java Tue Jan 24 00:30:25 2017 +0100 @@ -28,6 +28,8 @@ import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; +import jdk.internal.vm.annotation.Stable; + /** * A {@code CallSite} is a holder for a variable {@link MethodHandle}, * which is called its {@code target}. @@ -215,19 +217,36 @@ public abstract MethodHandle dynamicInvoker(); /*non-public*/ MethodHandle makeDynamicInvoker() { - MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this); + MethodHandle getTarget = getTargetHandle().bindArgumentL(0, this); MethodHandle invoker = MethodHandles.exactInvoker(this.type()); return MethodHandles.foldArguments(invoker, getTarget); } - private static final MethodHandle GET_TARGET; - private static final MethodHandle THROW_UCS; - static { + private static @Stable MethodHandle GET_TARGET; + private static MethodHandle getTargetHandle() { + MethodHandle handle = GET_TARGET; + if (handle != null) { + return handle; + } try { - GET_TARGET = IMPL_LOOKUP. - findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); - THROW_UCS = IMPL_LOOKUP. - findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class)); + return GET_TARGET = IMPL_LOOKUP. + findVirtual(CallSite.class, "getTarget", + MethodType.methodType(MethodHandle.class)); + } catch (ReflectiveOperationException e) { + throw newInternalError(e); + } + } + + private static @Stable MethodHandle THROW_UCS; + private static MethodHandle uninitializedCallSiteHandle() { + MethodHandle handle = THROW_UCS; + if (handle != null) { + return handle; + } + try { + return THROW_UCS = IMPL_LOOKUP. + findStatic(CallSite.class, "uninitializedCallSite", + MethodType.methodType(Object.class, Object[].class)); } catch (ReflectiveOperationException e) { throw newInternalError(e); } @@ -242,7 +261,7 @@ MethodType basicType = targetType.basicType(); MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS); if (invoker == null) { - invoker = THROW_UCS.asType(basicType); + invoker = uninitializedCallSiteHandle().asType(basicType); invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker); } // unchecked view is OK since no values will be received or returned @@ -250,12 +269,16 @@ } // unsafe stuff: - private static final long TARGET_OFFSET; - private static final long CONTEXT_OFFSET; - static { + private static @Stable long TARGET_OFFSET; + private static long getTargetOffset() { + long offset = TARGET_OFFSET; + if (offset > 0) { + return offset; + } try { - TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target")); - CONTEXT_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("context")); + offset = TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target")); + assert(offset > 0); + return offset; } catch (Exception ex) { throw newInternalError(ex); } } @@ -265,7 +288,7 @@ } /*package-private*/ MethodHandle getTargetVolatile() { - return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET); + return (MethodHandle) UNSAFE.getObjectVolatile(this, getTargetOffset()); } /*package-private*/ void setTargetVolatile(MethodHandle newTarget) { @@ -324,7 +347,7 @@ final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type) if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY) throw new BootstrapMethodError("too many bootstrap method arguments"); - MethodType bsmType = bootstrapMethod.type(); + MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length); MethodHandle typedBSM = bootstrapMethod.asType(invocationType); MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -846,8 +846,11 @@ // 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.") && !name.startsWith("java.util.concurrent.")) || - (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { + if ((name.startsWith("java.") && + !name.equals("java.lang.Thread") && + !name.startsWith("java.util.concurrent.")) || + (name.startsWith("sun.") && + !name.startsWith("sun.invoke."))) { throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); } }
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java Tue Jan 24 00:30:25 2017 +0100 @@ -1128,7 +1128,7 @@ public String toMethodDescriptorString() { String desc = methodDescriptor; if (desc == null) { - desc = BytecodeDescriptor.unparse(this); + desc = BytecodeDescriptor.unparseMethod(this.rtype, this.ptypes); methodDescriptor = desc; } return desc; @@ -1256,7 +1256,7 @@ private final ReferenceQueue<T> stale; public ConcurrentWeakInternSet() { - this.map = new ConcurrentHashMap<>(); + this.map = new ConcurrentHashMap<>(512); this.stale = new ReferenceQueue<>(); }
--- a/src/java.base/share/classes/java/net/SocketInputStream.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/net/SocketInputStream.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -155,11 +155,12 @@ } // bounds check - if (length <= 0 || off < 0 || off + length > b.length) { + if (length <= 0 || off < 0 || length > b.length - off) { if (length == 0) { return 0; } - throw new ArrayIndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException("length == " + length + + " off == " + off + " buffer length == " + b.length); } boolean gotReset = false;
--- a/src/java.base/share/classes/java/net/SocketOutputStream.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/net/SocketOutputStream.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -97,11 +97,13 @@ */ private void socketWrite(byte b[], int off, int len) throws IOException { - if (len <= 0 || off < 0 || off + len > b.length) { + + if (len <= 0 || off < 0 || len > b.length - off) { if (len == 0) { return; } - throw new ArrayIndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException("len == " + len + + " off == " + off + " buffer length == " + b.length); } FileDescriptor fd = impl.acquireFD();
--- a/src/java.base/share/classes/java/net/URL.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/net/URL.java Tue Jan 24 00:30:25 2017 +0100 @@ -1556,9 +1556,6 @@ path = file; } - if (port == -1) { - port = 0; - } // Set the object fields. this.protocol = protocol; this.host = host;
--- a/src/java.base/share/classes/java/net/URLClassLoader.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/net/URLClassLoader.java Tue Jan 24 00:30:25 2017 +0100 @@ -115,8 +115,8 @@ if (security != null) { security.checkCreateClassLoader(); } - this.ucp = new URLClassPath(urls); this.acc = AccessController.getContext(); + this.ucp = new URLClassPath(urls, acc); } URLClassLoader(String name, URL[] urls, ClassLoader parent, @@ -127,8 +127,8 @@ if (security != null) { security.checkCreateClassLoader(); } - this.ucp = new URLClassPath(urls); this.acc = acc; + this.ucp = new URLClassPath(urls, acc); } /** @@ -159,8 +159,8 @@ if (security != null) { security.checkCreateClassLoader(); } - this.ucp = new URLClassPath(urls); this.acc = AccessController.getContext(); + this.ucp = new URLClassPath(urls, acc); } URLClassLoader(URL[] urls, AccessControlContext acc) { @@ -170,8 +170,8 @@ if (security != null) { security.checkCreateClassLoader(); } - this.ucp = new URLClassPath(urls); this.acc = acc; + this.ucp = new URLClassPath(urls, acc); } /** @@ -203,8 +203,8 @@ if (security != null) { security.checkCreateClassLoader(); } - this.ucp = new URLClassPath(urls, factory); this.acc = AccessController.getContext(); + this.ucp = new URLClassPath(urls, factory, acc); } @@ -238,8 +238,8 @@ if (security != null) { security.checkCreateClassLoader(); } - this.ucp = new URLClassPath(urls); this.acc = AccessController.getContext(); + this.ucp = new URLClassPath(urls, acc); } /** @@ -271,8 +271,8 @@ if (security != null) { security.checkCreateClassLoader(); } - this.ucp = new URLClassPath(urls, factory); this.acc = AccessController.getContext(); + this.ucp = new URLClassPath(urls, factory, acc); } /* A map (used as a set) to keep track of closeable local resources
--- a/src/java.base/share/classes/java/net/URLConnection.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/net/URLConnection.java Tue Jan 24 00:30:25 2017 +0100 @@ -30,8 +30,10 @@ import java.io.OutputStream; import java.security.PrivilegedAction; import java.util.Hashtable; +import java.util.concurrent.ConcurrentHashMap; import java.util.Date; import java.util.Iterator; +import java.util.Locale; import java.util.Objects; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; @@ -231,7 +233,7 @@ */ protected boolean allowUserInteraction = defaultAllowUserInteraction; - private static boolean defaultUseCaches = true; + private static volatile boolean defaultUseCaches = true; /** * If {@code true}, the protocol is allowed to use caching @@ -243,12 +245,18 @@ * <p> * Its default value is the value given in the last invocation of the * {@code setDefaultUseCaches} method. + * <p> + * The default setting may be overridden per protocol with + * {@link #setDefaultUseCaches(String,boolean)}. * * @see java.net.URLConnection#setUseCaches(boolean) * @see java.net.URLConnection#getUseCaches() * @see java.net.URLConnection#setDefaultUseCaches(boolean) */ - protected boolean useCaches = defaultUseCaches; + protected boolean useCaches; + + private static final ConcurrentHashMap<String,Boolean> defaultCaching = + new ConcurrentHashMap<>(); /** * Some protocols support skipping the fetching of the object unless @@ -460,6 +468,11 @@ */ protected URLConnection(URL url) { this.url = url; + if (url == null) { + this.useCaches = defaultUseCaches; + } else { + this.useCaches = getDefaultUseCaches(url.getProtocol()); + } } /** @@ -981,7 +994,8 @@ * is true, the connection is allowed to use whatever caches it can. * If false, caches are to be ignored. * The default value comes from DefaultUseCaches, which defaults to - * true. + * true. A default value can also be set per-protocol using + * {@link #setDefaultUseCaches(String,boolean)}. * * @param usecaches a {@code boolean} indicating whether * or not to allow caching @@ -1032,9 +1046,10 @@ * Returns the default value of a {@code URLConnection}'s * {@code useCaches} flag. * <p> - * Ths default is "sticky", being a part of the static state of all + * This default is "sticky", being a part of the static state of all * URLConnections. This flag applies to the next, and all following - * URLConnections that are created. + * URLConnections that are created. This default value can be over-ridden + * per protocol using {@link #setDefaultUseCaches(String,boolean)} * * @return the default value of a {@code URLConnection}'s * {@code useCaches} flag. @@ -1046,7 +1061,8 @@ /** * Sets the default value of the {@code useCaches} field to the - * specified value. + * specified value. This default value can be over-ridden + * per protocol using {@link #setDefaultUseCaches(String,boolean)} * * @param defaultusecaches the new value. * @see #getDefaultUseCaches() @@ -1055,6 +1071,43 @@ defaultUseCaches = defaultusecaches; } + /** + * Sets the default value of the {@code useCaches} field for the named + * protocol to the given value. This value overrides any default setting + * set by {@link #setDefaultUseCaches(boolean)} for the given protocol. + * Successive calls to this method change the setting and affect the + * default value for all future connections of that protocol. The protocol + * name is case insensitive. + * + * @param protocol the protocol to set the default for + * @param defaultVal whether caching is enabled by default for the given protocol + * @since 9 + */ + public static void setDefaultUseCaches(String protocol, boolean defaultVal) { + protocol = protocol.toLowerCase(Locale.US); + defaultCaching.put(protocol, defaultVal); + } + + /** + * Returns the default value of the {@code useCaches} flag for the given protocol. If + * {@link #setDefaultUseCaches(String,boolean)} was called for the given protocol, + * then that value is returned. Otherwise, if {@link #setDefaultUseCaches(boolean)} + * was called, then that value is returned. If neither method was called, + * the return value is {@code true}. The protocol name is case insensitive. + * + * @param protocol the protocol whose defaultUseCaches setting is required + * @return the default value of the {@code useCaches} flag for the given protocol. + * @since 9 + */ + public static boolean getDefaultUseCaches(String protocol) { + Boolean protoDefault = defaultCaching.get(protocol.toLowerCase(Locale.US)); + if (protoDefault != null) { + return protoDefault.booleanValue(); + } else { + return defaultUseCaches; + } + } + /** * Sets the general request property. If a property with the key already * exists, overwrite its value with the new value.
--- a/src/java.base/share/classes/java/net/URLStreamHandler.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/net/URLStreamHandler.java Tue Jan 24 00:30:25 2017 +0100 @@ -161,9 +161,9 @@ (spec.charAt(start + 1) == '/')) { start += 2; i = spec.indexOf('/', start); - if (i < 0) { + if (i < 0 || i > limit) { i = spec.indexOf('?', start); - if (i < 0) + if (i < 0 || i > limit) i = limit; } @@ -171,8 +171,14 @@ int ind = authority.indexOf('@'); if (ind != -1) { - userInfo = authority.substring(0, ind); - host = authority.substring(ind+1); + if (ind != authority.lastIndexOf('@')) { + // more than one '@' in authority. This is not server based + userInfo = null; + host = null; + } else { + userInfo = authority.substring(0, ind); + host = authority.substring(ind+1); + } } else { userInfo = null; }
--- a/src/java.base/share/classes/java/util/Collections.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/Collections.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -4354,6 +4354,11 @@ private Object readResolve() { return EMPTY_SET; } + + @Override + public int hashCode() { + return 0; + } } /** @@ -4786,6 +4791,10 @@ public boolean removeIf(Predicate<? super E> filter) { throw new UnsupportedOperationException(); } + @Override + public int hashCode() { + return Objects.hashCode(element); + } } /** @@ -4848,6 +4857,10 @@ public Spliterator<E> spliterator() { return singletonSpliterator(element); } + @Override + public int hashCode() { + return 31 + Objects.hashCode(element); + } } /** @@ -4970,6 +4983,11 @@ BiFunction<? super V, ? super V, ? extends V> remappingFunction) { throw new UnsupportedOperationException(); } + + @Override + public int hashCode() { + return Objects.hashCode(k) ^ Objects.hashCode(v); + } } // Miscellaneous
--- a/src/java.base/share/classes/java/util/Date.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/Date.java Tue Jan 24 00:30:25 2017 +0100 @@ -82,17 +82,19 @@ * well; for example, the time scale used by the satellite-based * global positioning system (GPS) is synchronized to UTC but is * <i>not</i> adjusted for leap seconds. An interesting source of - * further information is the U.S. Naval Observatory, particularly - * the Directorate of Time at: + * further information is the United States Naval Observatory (USNO): * <blockquote><pre> - * <a href="http://www.usno.navy.mil">http://www.usno.navy.mil</a> + * <a href="http://www.usno.navy.mil/USNO">http://www.usno.navy.mil/USNO</a> * </pre></blockquote> * <p> - * and their definitions of "Systems of Time" at: + * and the material regarding "Systems of Time" at: * <blockquote><pre> * <a href="http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time">http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time</a> * </pre></blockquote> * <p> + * which has descriptions of various different time systems including + * UT, UT1, and UTC. + * <p> * In all methods of class {@code Date} that accept or return * year, month, date, hours, minutes, and seconds values, the * following representations are used:
--- a/src/java.base/share/classes/java/util/ImmutableCollections.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -35,6 +35,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; +import jdk.internal.vm.annotation.Stable; /** * Container class for immutable collections. Not part of the public API. @@ -105,6 +106,11 @@ return null; // but the compiler doesn't know this } + @Override + public Iterator<E> iterator() { + return Collections.emptyIterator(); + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("not serial proxy"); } @@ -112,9 +118,26 @@ private Object writeReplace() { return new CollSer(CollSer.IMM_LIST); } + + @Override + public boolean contains(Object o) { + Objects.requireNonNull(o); + return false; + } + + @Override + public boolean containsAll(Collection<?> o) { + return o.isEmpty(); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return 1; + } } static final class List1<E> extends AbstractImmutableList<E> { + @Stable private final E e0; List1(E e0) { @@ -129,7 +152,6 @@ @Override public E get(int index) { Objects.checkIndex(index, 1); - // assert index == 0 return e0; } @@ -140,10 +162,22 @@ private Object writeReplace() { return new CollSer(CollSer.IMM_LIST, e0); } + + @Override + public boolean contains(Object o) { + return o.equals(e0); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return 31 + e0.hashCode(); + } } static final class List2<E> extends AbstractImmutableList<E> { + @Stable private final E e0; + @Stable private final E e1; List2(E e0, E e1) { @@ -166,6 +200,17 @@ } } + @Override + public boolean contains(Object o) { + return o.equals(e0) || o.equals(e1); // implicit nullcheck of o + } + + @Override + public int hashCode() { + int hash = 31 + e0.hashCode(); + return 31 * hash + e1.hashCode(); + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("not serial proxy"); } @@ -176,6 +221,7 @@ } static final class ListN<E> extends AbstractImmutableList<E> { + @Stable private final E[] elements; @SafeVarargs @@ -200,6 +246,25 @@ return elements[index]; } + @Override + public boolean contains(Object o) { + for (E e : elements) { + if (o.equals(e)) { // implicit nullcheck of o + return true; + } + } + return false; + } + + @Override + public int hashCode() { + int hash = 1; + for (E e : elements) { + hash = 31 * hash + e.hashCode(); + } + return hash; + } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("not serial proxy"); } @@ -238,7 +303,13 @@ @Override public boolean contains(Object o) { - return super.contains(Objects.requireNonNull(o)); + Objects.requireNonNull(o); + return false; + } + + @Override + public boolean containsAll(Collection<?> o) { + return o.isEmpty(); // implicit nullcheck of o } @Override @@ -253,9 +324,15 @@ private Object writeReplace() { return new CollSer(CollSer.IMM_SET); } + + @Override + public int hashCode() { + return 0; + } } static final class Set1<E> extends AbstractImmutableSet<E> { + @Stable private final E e0; Set1(E e0) { @@ -269,7 +346,7 @@ @Override public boolean contains(Object o) { - return super.contains(Objects.requireNonNull(o)); + return o.equals(e0); // implicit nullcheck of o } @Override @@ -284,17 +361,21 @@ private Object writeReplace() { return new CollSer(CollSer.IMM_SET, e0); } + + @Override + public int hashCode() { + return e0.hashCode(); + } } static final class Set2<E> extends AbstractImmutableSet<E> { - private final E e0; - private final E e1; + @Stable + final E e0; + @Stable + final E e1; Set2(E e0, E e1) { - Objects.requireNonNull(e0); - Objects.requireNonNull(e1); - - if (e0.equals(e1)) { + if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0 throw new IllegalArgumentException("duplicate element: " + e0); } @@ -314,7 +395,12 @@ @Override public boolean contains(Object o) { - return super.contains(Objects.requireNonNull(o)); + return o.equals(e0) || o.equals(e1); // implicit nullcheck of o + } + + @Override + public int hashCode() { + return e0.hashCode() + e1.hashCode(); } @Override @@ -358,8 +444,10 @@ * @param <E> the element type */ static final class SetN<E> extends AbstractImmutableSet<E> { - private final E[] elements; - private final int size; + @Stable + final E[] elements; + @Stable + final int size; @SafeVarargs @SuppressWarnings("unchecked") @@ -368,8 +456,8 @@ elements = (E[])new Object[EXPAND_FACTOR * input.length]; for (int i = 0; i < input.length; i++) { - E e = Objects.requireNonNull(input[i]); - int idx = probe(e); + E e = input[i]; + int idx = probe(e); // implicit nullcheck of e if (idx >= 0) { throw new IllegalArgumentException("duplicate element: " + e); } else { @@ -385,8 +473,7 @@ @Override public boolean contains(Object o) { - Objects.requireNonNull(o); - return probe(o) >= 0; + return probe(o) >= 0; // implicit nullcheck of o } @Override @@ -414,8 +501,21 @@ }; } + @Override + public int hashCode() { + int h = 0; + for (E e : elements) { + if (e != null) { + h += e.hashCode(); + } + } + return h; + } + // returns index at which element is present; or if absent, - // (-i - 1) where i is location where element should be inserted + // (-i - 1) where i is location where element should be inserted. + // Callers are relying on this method to perform an implicit nullcheck + // of pe private int probe(Object pe) { int idx = Math.floorMod(pe.hashCode() ^ SALT, elements.length); while (true) { @@ -481,12 +581,14 @@ @Override public boolean containsKey(Object o) { - return super.containsKey(Objects.requireNonNull(o)); + Objects.requireNonNull(o); + return false; } @Override public boolean containsValue(Object o) { - return super.containsValue(Objects.requireNonNull(o)); + Objects.requireNonNull(o); + return false; } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { @@ -496,10 +598,17 @@ private Object writeReplace() { return new CollSer(CollSer.IMM_MAP); } + + @Override + public int hashCode() { + return 0; + } } static final class Map1<K,V> extends AbstractImmutableMap<K,V> { + @Stable private final K k0; + @Stable private final V v0; Map1(K k0, V v0) { @@ -514,12 +623,12 @@ @Override public boolean containsKey(Object o) { - return super.containsKey(Objects.requireNonNull(o)); + return o.equals(k0); // implicit nullcheck of o } @Override public boolean containsValue(Object o) { - return super.containsValue(Objects.requireNonNull(o)); + return o.equals(v0); // implicit nullcheck of o } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { @@ -529,6 +638,11 @@ private Object writeReplace() { return new CollSer(CollSer.IMM_MAP, k0, v0); } + + @Override + public int hashCode() { + return k0.hashCode() ^ v0.hashCode(); + } } /** @@ -541,12 +655,13 @@ * @param <V> the value type */ static final class MapN<K,V> extends AbstractImmutableMap<K,V> { - private final Object[] table; // pairs of key, value - private final int size; // number of pairs + @Stable + final Object[] table; // pairs of key, value + @Stable + final int size; // number of pairs MapN(Object... input) { - Objects.requireNonNull(input); - if ((input.length & 1) != 0) { + if ((input.length & 1) != 0) { // implicit nullcheck of input throw new InternalError("length is odd"); } size = input.length >> 1; @@ -573,12 +688,30 @@ @Override public boolean containsKey(Object o) { - return probe(Objects.requireNonNull(o)) >= 0; + return probe(o) >= 0; // implicit nullcheck of o } @Override public boolean containsValue(Object o) { - return super.containsValue(Objects.requireNonNull(o)); + for (int i = 1; i < table.length; i += 2) { + Object v = table[i]; + if (v != null && o.equals(v)) { // implicit nullcheck of o + return true; + } + } + return false; + } + + @Override + public int hashCode() { + int hash = 0; + for (int i = 0; i < table.length; i += 2) { + Object k = table[i]; + if (k != null) { + hash += k.hashCode() ^ table[i + 1].hashCode(); + } + } + return hash; } @Override @@ -638,7 +771,9 @@ } // returns index at which the probe key is present; or if absent, - // (-i - 1) where i is location where element should be inserted + // (-i - 1) where i is location where element should be inserted. + // Callers are relying on this method to perform an implicit nullcheck + // of pk. private int probe(Object pk) { int idx = Math.floorMod(pk.hashCode() ^ SALT, table.length >> 1) << 1; while (true) {
--- a/src/java.base/share/classes/java/util/KeyValueHolder.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/KeyValueHolder.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -25,6 +25,8 @@ package java.util; +import jdk.internal.vm.annotation.Stable; + /** * An immutable container for a key and a value, suitable for use * in creating and populating {@code Map} instances. @@ -48,7 +50,9 @@ * @since 9 */ final class KeyValueHolder<K,V> implements Map.Entry<K,V> { + @Stable final K key; + @Stable final V value; KeyValueHolder(K k, V v) {
--- a/src/java.base/share/classes/java/util/List.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/List.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -1027,8 +1027,7 @@ @SafeVarargs @SuppressWarnings("varargs") static <E> List<E> of(E... elements) { - Objects.requireNonNull(elements); - switch (elements.length) { + switch (elements.length) { // implicit null check of elements case 0: return ImmutableCollections.List0.instance(); case 1:
--- a/src/java.base/share/classes/java/util/Map.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/Map.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -1602,8 +1602,7 @@ @SafeVarargs @SuppressWarnings("varargs") static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { - Objects.requireNonNull(entries); - if (entries.length == 0) { + if (entries.length == 0) { // implicit null check of entries return ImmutableCollections.Map0.instance(); } else if (entries.length == 1) { return new ImmutableCollections.Map1<>(entries[0].getKey(),
--- a/src/java.base/share/classes/java/util/ResourceBundle.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/ResourceBundle.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; @@ -365,7 +366,7 @@ @Override public ResourceBundle getBundle(String baseName, Locale locale, Module module) { // use the given module as the caller to bypass the access check - return getBundleImpl(module, module, getLoader(module), + return getBundleImpl(module, module, baseName, locale, Control.INSTANCE); } @@ -537,63 +538,19 @@ return locale; } - /* - * Automatic determination of the ClassLoader to be used to load - * resources on behalf of the client. - */ - private static ClassLoader getLoader(Class<?> caller) { - ClassLoader cl = caller == null ? null : caller.getClassLoader(); - if (cl == null) { - // When the caller's loader is the boot class loader, cl is null - // here. In that case, ClassLoader.getSystemClassLoader() may - // return the same class loader that the application is - // using. We therefore use a wrapper ClassLoader to create a - // separate scope for bundles loaded on behalf of the Java - // runtime so that these bundles cannot be returned from the - // cache to the application (5048280). - cl = RBClassLoader.INSTANCE; - } - return cl; - } - private static ClassLoader getLoader(Module module) { PrivilegedAction<ClassLoader> pa = module::getClassLoader; return AccessController.doPrivileged(pa); } /** - * A wrapper of ClassLoader.getSystemClassLoader(). + * @param module a non-null-screened module form the {@link CacheKey#getModule()}. + * @return the ClassLoader to use in {@link Control#needsReload} + * and {@link Control#newBundle} */ - private static class RBClassLoader extends ClassLoader { - private static final RBClassLoader INSTANCE = AccessController.doPrivileged( - new PrivilegedAction<RBClassLoader>() { - public RBClassLoader run() { - return new RBClassLoader(); - } - }); - private RBClassLoader() { - } - public Class<?> loadClass(String name) throws ClassNotFoundException { - ClassLoader loader = ClassLoader.getSystemClassLoader(); - if (loader != null) { - return loader.loadClass(name); - } - return Class.forName(name); - } - public URL getResource(String name) { - ClassLoader loader = ClassLoader.getSystemClassLoader(); - if (loader != null) { - return loader.getResource(name); - } - return ClassLoader.getSystemResource(name); - } - public InputStream getResourceAsStream(String name) { - ClassLoader loader = ClassLoader.getSystemClassLoader(); - if (loader != null) { - return loader.getResourceAsStream(name); - } - return ClassLoader.getSystemResourceAsStream(name); - } + private static ClassLoader getLoaderForControl(Module module) { + ClassLoader loader = getLoader(module); + return loader == null ? ClassLoader.getSystemClassLoader() : loader; } /** @@ -610,23 +567,23 @@ /** * Key used for cached resource bundles. The key checks the base - * name, the locale, the class loader, and the caller module + * name, the locale, the bundle module, and the caller module * to determine if the resource is a match to the requested one. - * The loader may be null, but the base name, the locale and - * module must have a non-null value. + * The base name, the locale and both modules must have a non-null value. */ - private static class CacheKey implements Cloneable { + private static final class CacheKey { // These four are the actual keys for lookup in Map. - private String name; - private Locale locale; - private KeyElementReference<ClassLoader> loaderRef; - private KeyElementReference<Module> moduleRef; - private KeyElementReference<Module> callerRef; - + private final String name; + private volatile Locale locale; + private final KeyElementReference<Module> moduleRef; + private final KeyElementReference<Module> callerRef; + // this is the part of hashCode that pertains to module and callerModule + // which can be GCed.. + private final int modulesHash; // bundle format which is necessary for calling // Control.needsReload(). - private String format; + private volatile String format; // These time values are in CacheKey so that NONEXISTENT_BUNDLE // doesn't need to be cloned for caching. @@ -639,63 +596,55 @@ private volatile long expirationTime; // Placeholder for an error report by a Throwable - private Throwable cause; - - // Hash code value cache to avoid recalculating the hash code - // of this instance. - private int hashCodeCache; + private volatile Throwable cause; // ResourceBundleProviders for loading ResourceBundles - private ServiceLoader<ResourceBundleProvider> providers; - private boolean providersChecked; + private volatile ServiceLoader<ResourceBundleProvider> providers; + private volatile boolean providersChecked; // Boolean.TRUE if the factory method caller provides a ResourceBundleProvier. - private Boolean callerHasProvider; + private volatile Boolean callerHasProvider; - CacheKey(String baseName, Locale locale, ClassLoader loader, Module module, Module caller) { + CacheKey(String baseName, Locale locale, Module module, Module caller) { Objects.requireNonNull(module); + Objects.requireNonNull(caller); this.name = baseName; this.locale = locale; - if (loader == null) { - this.loaderRef = null; - } else { - this.loaderRef = new KeyElementReference<>(loader, referenceQueue, this); - } this.moduleRef = new KeyElementReference<>(module, referenceQueue, this); this.callerRef = new KeyElementReference<>(caller, referenceQueue, this); + this.modulesHash = module.hashCode() ^ caller.hashCode(); + } - calculateHashCode(); + CacheKey(CacheKey src) { + // Create References to src's modules + this.moduleRef = new KeyElementReference<>( + Objects.requireNonNull(src.getModule()), referenceQueue, this); + this.callerRef = new KeyElementReference<>( + Objects.requireNonNull(src.getCallerModule()), referenceQueue, this); + // Copy fields from src. ResourceBundleProviders related fields + // and "cause" should not be copied. + this.name = src.name; + this.locale = src.locale; + this.modulesHash = src.modulesHash; + this.format = src.format; + this.loadTime = src.loadTime; + this.expirationTime = src.expirationTime; } String getName() { return name; } - CacheKey setName(String baseName) { - if (!this.name.equals(baseName)) { - this.name = baseName; - calculateHashCode(); - } - return this; - } - Locale getLocale() { return locale; } CacheKey setLocale(Locale locale) { - if (!this.locale.equals(locale)) { - this.locale = locale; - calculateHashCode(); - } + this.locale = locale; return this; } - ClassLoader getLoader() { - return (loaderRef != null) ? loaderRef.get() : null; - } - Module getModule() { return moduleRef.get(); } @@ -728,7 +677,7 @@ try { final CacheKey otherEntry = (CacheKey)other; //quick check to see if they are not equal - if (hashCodeCache != otherEntry.hashCodeCache) { + if (modulesHash != otherEntry.modulesHash) { return false; } //are the names the same? @@ -739,24 +688,11 @@ if (!locale.equals(otherEntry.locale)) { return false; } - //are refs (both non-null) or (both null)? - if (loaderRef == null) { - return otherEntry.loaderRef == null; - } - ClassLoader loader = getLoader(); + // are modules and callerModules the same and non-null? Module module = getModule(); Module caller = getCallerModule(); - - return (otherEntry.loaderRef != null) - // with a null reference we can no longer find - // out which class loader or module was referenced; so - // treat it as unequal - && (loader != null) - && (loader == otherEntry.getLoader()) - && (module != null) - && (module.equals(otherEntry.getModule())) - && (caller != null) - && (caller.equals(otherEntry.getCallerModule())); + return ((module != null) && (module.equals(otherEntry.getModule())) && + (caller != null) && (caller.equals(otherEntry.getCallerModule()))); } catch (NullPointerException | ClassCastException e) { } return false; @@ -764,51 +700,7 @@ @Override public int hashCode() { - return hashCodeCache; - } - - private void calculateHashCode() { - hashCodeCache = name.hashCode() << 3; - hashCodeCache ^= locale.hashCode(); - ClassLoader loader = getLoader(); - if (loader != null) { - hashCodeCache ^= loader.hashCode(); - } - Module module = getModule(); - if (module != null) { - hashCodeCache ^= module.hashCode(); - } - Module caller = getCallerModule(); - if (caller != null) { - hashCodeCache ^= caller.hashCode(); - } - } - - @Override - public Object clone() { - try { - CacheKey clone = (CacheKey) super.clone(); - if (loaderRef != null) { - clone.loaderRef = new KeyElementReference<>(getLoader(), - referenceQueue, clone); - } - clone.moduleRef = new KeyElementReference<>(getModule(), - referenceQueue, clone); - clone.callerRef = new KeyElementReference<>(getCallerModule(), - referenceQueue, clone); - - // Clear the reference to ResourceBundleProviders and the flag - clone.providers = null; - clone.providersChecked = false; - // Clear the reference to a Throwable - clone.cause = null; - // Clear callerHasProvider - clone.callerHasProvider = null; - return clone; - } catch (CloneNotSupportedException e) { - //this should never happen - throw new InternalError(e); - } + return (name.hashCode() << 3) ^ locale.hashCode() ^ modulesHash; } String getFormat() { @@ -845,8 +737,12 @@ l = "\"\""; } } - return "CacheKey[" + name + ", lc=" + l + ", ldr=" + getLoader() - + "(format=" + format + ")]"; + return "CacheKey[" + name + + ", locale=" + l + + ", module=" + getModule() + + ", callerModule=" + getCallerModule() + + ", format=" + format + + "]"; } } @@ -1568,7 +1464,7 @@ Locale locale, Class<?> caller, Control control) { - return getBundleImpl(baseName, locale, caller, getLoader(caller), control); + return getBundleImpl(baseName, locale, caller, caller.getClassLoader(), control); } /** @@ -1587,26 +1483,25 @@ Class<?> caller, ClassLoader loader, Control control) { - if (caller != null && caller.getModule().isNamed()) { - Module module = caller.getModule(); - ClassLoader ml = getLoader(module); - // get resource bundles for a named module only - // if loader is the module's class loader - if (loader == ml || (ml == null && loader == RBClassLoader.INSTANCE)) { - return getBundleImpl(module, module, loader, baseName, locale, control); - } - } - // find resource bundles from unnamed module - Module unnamedModule = loader != null - ? loader.getUnnamedModule() - : ClassLoader.getSystemClassLoader().getUnnamedModule(); - if (caller == null) { throw new InternalError("null caller"); } + Module callerModule = caller.getModule(); - Module callerModule = caller.getModule(); - return getBundleImpl(callerModule, unnamedModule, loader, baseName, locale, control); + // get resource bundles for a named module only if loader is the module's class loader + if (callerModule.isNamed() && loader == getLoader(callerModule)) { + return getBundleImpl(callerModule, callerModule, baseName, locale, control); + } + + // find resource bundles from unnamed module of given class loader + // Java agent can add to the bootclasspath e.g. via + // java.lang.instrument.Instrumentation and load classes in unnamed module. + // It may call RB::getBundle that will end up here with loader == null. + Module unnamedModule = loader != null + ? loader.getUnnamedModule() + : BootLoader.getUnnamedModule(); + + return getBundleImpl(callerModule, unnamedModule, baseName, locale, control); } private static ResourceBundle getBundleFromModule(Class<?> caller, @@ -1622,12 +1517,11 @@ sm.checkPermission(GET_CLASSLOADER_PERMISSION); } } - return getBundleImpl(callerModule, module, getLoader(module), baseName, locale, control); + return getBundleImpl(callerModule, module, baseName, locale, control); } private static ResourceBundle getBundleImpl(Module callerModule, Module module, - ClassLoader loader, String baseName, Locale locale, Control control) { @@ -1636,10 +1530,10 @@ } // We create a CacheKey here for use by this call. The base name - // loader, and module will never change during the bundle loading + // and modules will never change during the bundle loading // process. We have to make sure that the locale is set before // using it as a cache key. - CacheKey cacheKey = new CacheKey(baseName, locale, loader, module, callerModule); + CacheKey cacheKey = new CacheKey(baseName, locale, module, callerModule); ResourceBundle bundle = null; // Quick lookup of the cache. @@ -1708,6 +1602,11 @@ bundle = baseBundle; } + // keep callerModule and module reachable for as long as we are operating + // with WeakReference(s) to them (in CacheKey)... + Reference.reachabilityFence(callerModule); + Reference.reachabilityFence(module); + return bundle; } @@ -1745,7 +1644,7 @@ } // Before we do the real loading work, see whether we need to - // do some housekeeping: If references to class loaders or + // do some housekeeping: If references to modules or // resource bundles have been nulled out, remove all related // information from the cache. Object ref; @@ -1781,31 +1680,24 @@ } if (bundle != NONEXISTENT_BUNDLE) { - CacheKey constKey = (CacheKey) cacheKey.clone(); trace("findBundle: %d %s %s formats: %s%n", index, candidateLocales, cacheKey, formats); - try { - if (module.isNamed()) { - bundle = loadBundle(cacheKey, formats, control, module, callerModule); - } else { - bundle = loadBundle(cacheKey, formats, control, expiredBundle); + if (module.isNamed()) { + bundle = loadBundle(cacheKey, formats, control, module, callerModule); + } else { + bundle = loadBundle(cacheKey, formats, control, expiredBundle); + } + if (bundle != null) { + if (bundle.parent == null) { + bundle.setParent(parent); } - if (bundle != null) { - if (bundle.parent == null) { - bundle.setParent(parent); - } - bundle.locale = targetLocale; - bundle = putBundleInCache(cacheKey, bundle, control); - return bundle; - } + bundle.locale = targetLocale; + bundle = putBundleInCache(cacheKey, bundle, control); + return bundle; + } - // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle - // instance for the locale. - putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control); - } finally { - if (constKey.getCause() instanceof InterruptedException) { - Thread.currentThread().interrupt(); - } - } + // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle + // instance for the locale. + putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control); } return parent; } @@ -1991,12 +1883,20 @@ // specified by the getFormats() value. Locale targetLocale = cacheKey.getLocale(); + Module module = cacheKey.getModule(); + if (module == null) { + // should not happen + throw new InternalError( + "Module for cache key: " + cacheKey + " has been GCed."); + } + ClassLoader loader = getLoaderForControl(module); + ResourceBundle bundle = null; for (String format : formats) { try { // ResourceBundle.Control.newBundle may be overridden bundle = control.newBundle(cacheKey.getName(), targetLocale, format, - cacheKey.getLoader(), reload); + loader, reload); } catch (LinkageError | Exception error) { // We need to handle the LinkageError case due to // inconsistent case-sensitivity in ClassLoader. @@ -2138,12 +2038,15 @@ if (!bundle.expired && expirationTime >= 0 && expirationTime <= System.currentTimeMillis()) { try { - bundle.expired = control.needsReload(key.getName(), - key.getLocale(), - key.getFormat(), - key.getLoader(), - bundle, - key.loadTime); + Module module = cacheKey.getModule(); + bundle.expired = + module == null || // already GCed + control.needsReload(key.getName(), + key.getLocale(), + key.getFormat(), + getLoaderForControl(module), + bundle, + key.loadTime); } catch (Exception e) { cacheKey.setCause(e); } @@ -2185,7 +2088,7 @@ Control control) { setExpirationTime(cacheKey, control); if (cacheKey.expirationTime != Control.TTL_DONT_CACHE) { - CacheKey key = (CacheKey) cacheKey.clone(); + CacheKey key = new CacheKey(cacheKey); BundleReference bundleRef = new BundleReference(bundle, referenceQueue, key); bundle.cacheKey = key; @@ -2231,7 +2134,7 @@ /** * Removes all resource bundles from the cache that have been loaded - * by the caller's module using the caller's class loader. + * by the caller's module. * * @since 1.6 * @see ResourceBundle.Control#getTimeToLive(String,Locale) @@ -2239,47 +2142,29 @@ @CallerSensitive public static final void clearCache() { Class<?> caller = Reflection.getCallerClass(); - clearCache(getLoader(caller), caller.getModule()); + cacheList.keySet().removeIf( + key -> key.getCallerModule() == caller.getModule() + ); } /** * Removes all resource bundles from the cache that have been loaded - * by the caller's module using the given class loader. + * by the given class loader. * * @param loader the class loader * @exception NullPointerException if <code>loader</code> is null * @since 1.6 * @see ResourceBundle.Control#getTimeToLive(String,Locale) */ - @CallerSensitive public static final void clearCache(ClassLoader loader) { Objects.requireNonNull(loader); - clearCache(loader, Reflection.getCallerClass().getModule()); - } - - /** - * Removes all resource bundles from the cache that have been loaded by the - * given {@code module}. - * - * @param module the module - * @throws NullPointerException - * if {@code module} is {@code null} - * @throws SecurityException - * if the caller doesn't have the permission to - * {@linkplain Module#getClassLoader() get the class loader} - * of the given {@code module} - * @since 9 - * @see ResourceBundle.Control#getTimeToLive(String,Locale) - */ - public static final void clearCache(Module module) { - clearCache(module.getClassLoader(), module); - } - - private static void clearCache(ClassLoader loader, Module module) { - Set<CacheKey> set = cacheList.keySet(); - set.stream() - .filter((key) -> (key.getLoader() == loader && key.getModule() == module)) - .forEach(set::remove); + cacheList.keySet().removeIf( + key -> { + Module m; + return (m = key.getModule()) != null && + getLoader(m) == loader; + } + ); } /**
--- a/src/java.base/share/classes/java/util/Set.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/Set.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -689,8 +689,7 @@ @SafeVarargs @SuppressWarnings("varargs") static <E> Set<E> of(E... elements) { - Objects.requireNonNull(elements); - switch (elements.length) { + switch (elements.length) { // implicit null check of elements case 0: return ImmutableCollections.Set0.instance(); case 1:
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Tue Jan 24 00:30:25 2017 +0100 @@ -185,7 +185,14 @@ static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread { /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */ private static final ThreadGroup innocuousThreadGroup = - ThreadLocalRandom.createThreadGroup("InnocuousForkJoinWorkerThreadGroup"); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction<>() { + public ThreadGroup run() { + ThreadGroup group = Thread.currentThread().getThreadGroup(); + for (ThreadGroup p; (p = group.getParent()) != null; ) + group = p; + return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup"); + }}); /** An AccessControlContext supporting no privileges */ private static final AccessControlContext INNOCUOUS_ACC = @@ -215,6 +222,5 @@ public void setContextClassLoader(ClassLoader cl) { throw new SecurityException("setContextClassLoader"); } - } }
--- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Tue Jan 24 00:30:25 2017 +0100 @@ -985,34 +985,6 @@ U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc); } - /** - * Returns a new group with the system ThreadGroup (the - * topmost, parent-less group) as parent. Uses Unsafe to - * traverse Thread.group and ThreadGroup.parent fields. - */ - static final ThreadGroup createThreadGroup(String name) { - if (name == null) - throw new NullPointerException(); - try { - long tg = U.objectFieldOffset - (Thread.class.getDeclaredField("group")); - long gp = U.objectFieldOffset - (ThreadGroup.class.getDeclaredField("parent")); - ThreadGroup group = (ThreadGroup) - U.getObject(Thread.currentThread(), tg); - while (group != null) { - ThreadGroup parent = (ThreadGroup)U.getObject(group, gp); - if (parent == null) - return new ThreadGroup(group, name); - group = parent; - } - } catch (ReflectiveOperationException e) { - throw new Error(e); - } - // fall through if null as cannot-happen safeguard - throw new Error("Cannot create ThreadGroup"); - } - // Serialization support private static final long serialVersionUID = -5851777807851030925L; @@ -1087,17 +1059,17 @@ static { try { SEED = U.objectFieldOffset - (Thread.class.getDeclaredField("threadLocalRandomSeed")); + (Thread.class.getDeclaredField("threadLocalRandomSeed")); PROBE = U.objectFieldOffset - (Thread.class.getDeclaredField("threadLocalRandomProbe")); + (Thread.class.getDeclaredField("threadLocalRandomProbe")); SECONDARY = U.objectFieldOffset - (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed")); + (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed")); THREADLOCALS = U.objectFieldOffset - (Thread.class.getDeclaredField("threadLocals")); + (Thread.class.getDeclaredField("threadLocals")); INHERITABLETHREADLOCALS = U.objectFieldOffset - (Thread.class.getDeclaredField("inheritableThreadLocals")); + (Thread.class.getDeclaredField("inheritableThreadLocals")); INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset - (Thread.class.getDeclaredField("inheritedAccessControlContext")); + (Thread.class.getDeclaredField("inheritedAccessControlContext")); } catch (ReflectiveOperationException e) { throw new Error(e); } @@ -1123,7 +1095,7 @@ // at end of <clinit> to survive static initialization circularity static { if (java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Boolean>() { + new java.security.PrivilegedAction<>() { public Boolean run() { return Boolean.getBoolean("java.util.secureRandomSeed"); }})) {
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Tue Jan 24 00:30:25 2017 +0100 @@ -40,6 +40,7 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Objects; import java.util.function.IntBinaryOperator; import java.util.function.IntUnaryOperator; import jdk.internal.misc.Unsafe; @@ -411,7 +412,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.offset = U.objectFieldOffset(field); } @@ -433,6 +444,15 @@ } /** + * Returns true if the two classes have the same class loader and + * package qualifier + */ + private static boolean isSamePackage(Class<?> class1, Class<?> class2) { + return class1.getClassLoader() == class2.getClassLoader() + && Objects.equals(class1.getPackageName(), class2.getPackageName()); + } + + /** * Checks that target argument is instance of cclass. On * failure, throws cause. */
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Tue Jan 24 00:30:25 2017 +0100 @@ -40,6 +40,7 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Objects; import java.util.function.LongBinaryOperator; import java.util.function.LongUnaryOperator; import jdk.internal.misc.Unsafe; @@ -409,7 +410,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.offset = U.objectFieldOffset(field); } @@ -540,7 +551,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.offset = U.objectFieldOffset(field); } @@ -621,4 +642,13 @@ } while (acl != null); return false; } + + /** + * Returns true if the two classes have the same class loader and + * package qualifier + */ + static boolean isSamePackage(Class<?> class1, Class<?> class2) { + return class1.getClassLoader() == class2.getClassLoader() + && Objects.equals(class1.getPackageName(), class2.getPackageName()); + } }
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Tue Jan 24 00:30:25 2017 +0100 @@ -40,6 +40,7 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Objects; import java.util.function.BinaryOperator; import java.util.function.UnaryOperator; import jdk.internal.misc.Unsafe; @@ -351,7 +352,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.vclass = vclass; this.offset = U.objectFieldOffset(field); @@ -374,6 +385,15 @@ } /** + * Returns true if the two classes have the same class loader and + * package qualifier + */ + private static boolean isSamePackage(Class<?> class1, Class<?> class2) { + return class1.getClassLoader() == class2.getClassLoader() + && Objects.equals(class1.getPackageName(), class2.getPackageName()); + } + + /** * Checks that target argument is instance of cclass. On * failure, throws cause. */
--- a/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Tue Jan 24 00:30:25 2017 +0100 @@ -41,7 +41,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.function.DoubleBinaryOperator; import java.util.function.LongBinaryOperator; -import jdk.internal.misc.Unsafe; /** * A package-local class holding common representation and mechanics @@ -191,7 +190,7 @@ * Duplicated from ThreadLocalRandom because of packaging restrictions. */ static final int getProbe() { - return U.getInt(Thread.currentThread(), PROBE); + return (int) THREAD_PROBE.get(Thread.currentThread()); } /** @@ -203,7 +202,7 @@ probe ^= probe << 13; // xorshift probe ^= probe >>> 17; probe ^= probe << 5; - U.putInt(Thread.currentThread(), PROBE, probe); + THREAD_PROBE.set(Thread.currentThread(), probe); return probe; } @@ -373,18 +372,28 @@ } } - // Unsafe and VarHandle mechanics - private static final Unsafe U = Unsafe.getUnsafe(); + // VarHandle mechanics private static final VarHandle BASE; private static final VarHandle CELLSBUSY; - private static final long PROBE; + private static final VarHandle THREAD_PROBE; static { try { MethodHandles.Lookup l = MethodHandles.lookup(); - BASE = l.findVarHandle(Striped64.class, "base", long.class); - CELLSBUSY = l.findVarHandle(Striped64.class, "cellsBusy", int.class); - PROBE = U.objectFieldOffset - (Thread.class.getDeclaredField("threadLocalRandomProbe")); + BASE = l.findVarHandle(Striped64.class, + "base", long.class); + CELLSBUSY = l.findVarHandle(Striped64.class, + "cellsBusy", int.class); + l = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction<>() { + public MethodHandles.Lookup run() { + try { + return MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup()); + } catch (ReflectiveOperationException e) { + throw new Error(e); + } + }}); + THREAD_PROBE = l.findVarHandle(Thread.class, + "threadLocalRandomProbe", int.class); } catch (ReflectiveOperationException e) { throw new Error(e); }
--- a/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Tue Jan 24 00:30:25 2017 +0100 @@ -425,11 +425,11 @@ static { try { PARKBLOCKER = U.objectFieldOffset - (Thread.class.getDeclaredField("parkBlocker")); + (Thread.class.getDeclaredField("parkBlocker")); SECONDARY = U.objectFieldOffset - (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed")); + (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed")); TID = U.objectFieldOffset - (Thread.class.getDeclaredField("tid")); + (Thread.class.getDeclaredField("tid")); } catch (ReflectiveOperationException e) { throw new Error(e);
--- a/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -120,6 +120,9 @@ * Note: This method can be used only when using certificate-based * cipher suites; using it with non-certificate-based cipher suites, * such as Kerberos, will throw an SSLPeerUnverifiedException. + * <P> + * Note: The returned value may not be a valid certificate chain + * and should not be relied on for trust decisions. * * @return an ordered array of the peer certificates, * with the peer's own certificate first followed by @@ -140,6 +143,9 @@ * Note: This method can be used only when using certificate-based * cipher suites; using it with non-certificate-based cipher suites, * such as Kerberos, will throw an SSLPeerUnverifiedException. + * <P> + * Note: The returned value may not be a valid certificate chain + * and should not be relied on for trust decisions. * * <p><em>Note: this method exists for compatibility with previous * releases. New applications should use
--- a/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -104,6 +104,9 @@ * Note: This method can be used only when using certificate-based * cipher suites; using it with non-certificate-based cipher suites, * such as Kerberos, will throw an SSLPeerUnverifiedException. + * <P> + * Note: The returned value may not be a valid certificate chain + * and should not be relied on for trust decisions. * * @return an ordered array of server certificates, * with the peer's own certificate first followed by
--- a/src/java.base/share/classes/javax/net/ssl/SSLSession.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/javax/net/ssl/SSLSession.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -219,6 +219,9 @@ * Note: This method can be used only when using certificate-based * cipher suites; using it with non-certificate-based cipher suites, * such as Kerberos, will throw an SSLPeerUnverifiedException. + * <P> + * Note: The returned value may not be a valid certificate chain + * and should not be relied on for trust decisions. * * @return an ordered array of peer certificates, * with the peer's own certificate first followed by any @@ -259,6 +262,9 @@ * Note: This method can be used only when using certificate-based * cipher suites; using it with non-certificate-based cipher suites, * such as Kerberos, will throw an SSLPeerUnverifiedException. + * <P> + * Note: The returned value may not be a valid certificate chain + * and should not be relied on for trust decisions. * * <p><em>Note: this method exists for compatibility with previous * releases. New applications should use
--- a/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Tue Jan 24 00:30:25 2017 +0100 @@ -38,6 +38,7 @@ import java.net.URLConnection; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; +import java.security.AccessControlContext; import java.security.AccessControlException; import java.security.AccessController; import java.security.CodeSigner; @@ -83,6 +84,7 @@ private static final String JAVA_VERSION; private static final boolean DEBUG; private static final boolean DISABLE_JAR_CHECKING; + private static final boolean DISABLE_ACC_CHECKING; static { Properties props = GetPropertyAction.privilegedGetProperties(); @@ -90,6 +92,9 @@ DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null); String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking"); DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false; + + p = props.getProperty("jdk.net.URLClassPath.disableRestrictedPermissions"); + DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false; } /* The original search path of URLs. */ @@ -110,6 +115,11 @@ /* Whether this URLClassLoader has been closed yet */ private boolean closed = false; + /* The context to be used when loading classes and resources. If non-null + * this is the context that was captured during the creation of the + * URLClassLoader. null implies no additional security restrictions. */ + private final AccessControlContext acc; + /** * Creates a new URLClassPath for the given URLs. The URLs will be * searched in the order specified for classes and resources. A URL @@ -119,8 +129,12 @@ * @param urls the directory and JAR file URLs to search for classes * and resources * @param factory the URLStreamHandlerFactory to use when creating new URLs + * @param acc the context to be used when loading classes and resources, may + * be null */ - public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) { + public URLClassPath(URL[] urls, + URLStreamHandlerFactory factory, + AccessControlContext acc) { for (int i = 0; i < urls.length; i++) { path.add(urls[i]); } @@ -128,10 +142,22 @@ if (factory != null) { jarHandler = factory.createURLStreamHandler("jar"); } + if (DISABLE_ACC_CHECKING) + this.acc = null; + else + this.acc = acc; } + /** + * Constructs a URLClassPath with no additional security restrictions. + * Used by code that implements the class path. + */ public URLClassPath(URL[] urls) { - this(urls, null); + this(urls, null, null); + } + + public URLClassPath(URL[] urls, AccessControlContext acc) { + this(urls, null, acc); } public synchronized List<IOException> closeLoaders() { @@ -356,6 +382,14 @@ } catch (IOException e) { // Silently ignore for now... continue; + } catch (SecurityException se) { + // Always silently ignore. The context, if there is one, that + // this URLClassPath was given during construction will never + // have permission to access the URL. + if (DEBUG) { + System.err.println("Failed to access " + url + ", " + se ); + } + continue; } // Finally, add the Loader to the search path. loaders.add(loader); @@ -378,7 +412,7 @@ && file != null && (file.indexOf("!/") == file.length() - 2)) { // extract the nested URL URL nestedUrl = new URL(file.substring(0, file.length() - 2)); - return new JarLoader(nestedUrl, jarHandler, lmap); + return new JarLoader(nestedUrl, jarHandler, lmap, acc); } else if (file != null && file.endsWith("/")) { if ("file".equals(protocol)) { return new FileLoader(url); @@ -386,10 +420,10 @@ return new Loader(url); } } else { - return new JarLoader(url, jarHandler, lmap); + return new JarLoader(url, jarHandler, lmap, acc); } } - }); + }, acc); } catch (java.security.PrivilegedActionException pae) { throw (IOException)pae.getException(); } @@ -585,10 +619,11 @@ */ static class JarLoader extends Loader { private JarFile jar; - private URL csu; + private final URL csu; private JarIndex index; private URLStreamHandler handler; - private HashMap<String, Loader> lmap; + private final HashMap<String, Loader> lmap; + private final AccessControlContext acc; private boolean closed = false; private static final JavaUtilZipFileAccess zipAccess = SharedSecrets.getJavaUtilZipFileAccess(); @@ -598,13 +633,15 @@ * a JAR file. */ JarLoader(URL url, URLStreamHandler jarHandler, - HashMap<String, Loader> loaderMap) + HashMap<String, Loader> loaderMap, + AccessControlContext acc) throws IOException { super(new URL("jar", "", -1, url + "!/", jarHandler)); csu = url; handler = jarHandler; lmap = loaderMap; + this.acc = acc; ensureOpen(); } @@ -663,8 +700,7 @@ } return null; } - } - ); + }, acc); } catch (java.security.PrivilegedActionException pae) { throw (IOException)pae.getException(); } @@ -859,9 +895,9 @@ new PrivilegedExceptionAction<>() { public JarLoader run() throws IOException { return new JarLoader(url, handler, - lmap); + lmap, acc); } - }); + }, acc); /* this newly opened jar file has its own index, * merge it into the parent's index, taking into
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java Tue Jan 24 00:30:25 2017 +0100 @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2017, 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.internal.module; + +import java.io.PrintStream; +import java.lang.module.Configuration; +import java.lang.module.ResolvedModule; +import java.net.URI; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; +import static java.util.stream.Collectors.*; + +/** + * A Builder to compute ModuleHashes from a given configuration + */ +public class ModuleHashesBuilder { + private final Configuration configuration; + private final Set<String> hashModuleCandidates; + + /** + * Constructs a ModuleHashesBuilder that finds the packaged modules + * from the location of ModuleReference found from the given Configuration. + * + * @param config Configuration for building module hashes + * @param modules the candidate modules to be hashed + */ + public ModuleHashesBuilder(Configuration config, Set<String> modules) { + this.configuration = config; + this.hashModuleCandidates = modules; + } + + /** + * Returns a map of a module M to ModuleHashes for the modules + * that depend upon M directly or indirectly. + * + * The key for each entry in the returned map is a module M that has + * no outgoing edges to any of the candidate modules to be hashed + * i.e. M is a leaf node in a connected subgraph containing M and + * other candidate modules from the module graph filtering + * the outgoing edges from M to non-candidate modules. + */ + public Map<String, ModuleHashes> computeHashes(Set<String> roots) { + // build a graph containing the the packaged modules and + // its transitive dependences matching --hash-modules + Graph.Builder<String> builder = new Graph.Builder<>(); + Deque<ResolvedModule> deque = new ArrayDeque<>(configuration.modules()); + Set<ResolvedModule> visited = new HashSet<>(); + while (!deque.isEmpty()) { + ResolvedModule rm = deque.pop(); + if (!visited.contains(rm)) { + visited.add(rm); + builder.addNode(rm.name()); + for (ResolvedModule dm : rm.reads()) { + if (!visited.contains(dm)) { + deque.push(dm); + } + builder.addEdge(rm.name(), dm.name()); + } + } + } + + // each node in a transposed graph is a matching packaged module + // in which the hash of the modules that depend upon it is recorded + Graph<String> transposedGraph = builder.build().transpose(); + + // traverse the modules in topological order that will identify + // the modules to record the hashes - it is the first matching + // module and has not been hashed during the traversal. + Set<String> mods = new HashSet<>(); + Map<String, ModuleHashes> hashes = new HashMap<>(); + builder.build() + .orderedNodes() + .filter(mn -> roots.contains(mn) && !mods.contains(mn)) + .forEach(mn -> { + // Compute hashes of the modules that depend on mn directly and + // indirectly excluding itself. + Set<String> ns = transposedGraph.dfs(mn) + .stream() + .filter(n -> !n.equals(mn) && hashModuleCandidates.contains(n)) + .collect(toSet()); + mods.add(mn); + mods.addAll(ns); + + if (!ns.isEmpty()) { + Map<String, Path> moduleToPath = ns.stream() + .collect(toMap(Function.identity(), this::moduleToPath)); + hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256")); + } + }); + return hashes; + } + + private Path moduleToPath(String name) { + ResolvedModule rm = configuration.findModule(name).orElseThrow( + () -> new InternalError("Selected module " + name + " not on module path")); + + URI uri = rm.reference().location().get(); + Path path = Paths.get(uri); + String fn = path.getFileName().toString(); + if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) { + throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file"); + } + return path; + } + + /* + * Utilty class + */ + static class Graph<T> { + private final Set<T> nodes; + private final Map<T, Set<T>> edges; + + public Graph(Set<T> nodes, Map<T, Set<T>> edges) { + this.nodes = Collections.unmodifiableSet(nodes); + this.edges = Collections.unmodifiableMap(edges); + } + + public Set<T> nodes() { + return nodes; + } + + public Map<T, Set<T>> edges() { + return edges; + } + + public Set<T> adjacentNodes(T u) { + return edges.get(u); + } + + public boolean contains(T u) { + return nodes.contains(u); + } + + /** + * Returns nodes sorted in topological order. + */ + public Stream<T> orderedNodes() { + TopoSorter<T> sorter = new TopoSorter<>(this); + return sorter.result.stream(); + } + + /** + * Traverse this graph and performs the given action in topological order + */ + public void ordered(Consumer<T> action) { + TopoSorter<T> sorter = new TopoSorter<>(this); + sorter.ordered(action); + } + + /** + * Traverses this graph and performs the given action in reverse topological order + */ + public void reverse(Consumer<T> action) { + TopoSorter<T> sorter = new TopoSorter<>(this); + sorter.reverse(action); + } + + /** + * Returns a transposed graph from this graph + */ + public Graph<T> transpose() { + Builder<T> builder = new Builder<>(); + nodes.stream().forEach(builder::addNode); + // reverse edges + edges.keySet().forEach(u -> { + edges.get(u).stream() + .forEach(v -> builder.addEdge(v, u)); + }); + return builder.build(); + } + + /** + * Returns all nodes reachable from the given root. + */ + public Set<T> dfs(T root) { + return dfs(Set.of(root)); + } + + /** + * Returns all nodes reachable from the given set of roots. + */ + public Set<T> dfs(Set<T> roots) { + Deque<T> deque = new LinkedList<>(roots); + Set<T> visited = new HashSet<>(); + while (!deque.isEmpty()) { + T u = deque.pop(); + if (!visited.contains(u)) { + visited.add(u); + if (contains(u)) { + adjacentNodes(u).stream() + .filter(v -> !visited.contains(v)) + .forEach(deque::push); + } + } + } + return visited; + } + + public void printGraph(PrintStream out) { + out.println("graph for " + nodes); + nodes.stream() + .forEach(u -> adjacentNodes(u).stream() + .forEach(v -> out.format(" %s -> %s%n", u, v))); + } + + static class Builder<T> { + final Set<T> nodes = new HashSet<>(); + final Map<T, Set<T>> edges = new HashMap<>(); + + public void addNode(T node) { + if (nodes.contains(node)) { + return; + } + nodes.add(node); + edges.computeIfAbsent(node, _e -> new HashSet<>()); + } + + public void addEdge(T u, T v) { + addNode(u); + addNode(v); + edges.get(u).add(v); + } + + public Graph<T> build() { + return new Graph<T>(nodes, edges); + } + } + } + + /** + * Topological sort + */ + private static class TopoSorter<T> { + final Deque<T> result = new LinkedList<>(); + final Deque<T> nodes; + final Graph<T> graph; + + TopoSorter(Graph<T> graph) { + this.graph = graph; + this.nodes = new LinkedList<>(graph.nodes); + sort(); + } + + public void ordered(Consumer<T> action) { + result.iterator().forEachRemaining(action); + } + + public void reverse(Consumer<T> action) { + result.descendingIterator().forEachRemaining(action); + } + + private void sort() { + Deque<T> visited = new LinkedList<>(); + Deque<T> done = new LinkedList<>(); + T node; + while ((node = nodes.poll()) != null) { + if (!visited.contains(node)) { + visit(node, visited, done); + } + } + } + + private void visit(T node, Deque<T> visited, Deque<T> done) { + if (visited.contains(node)) { + if (!done.contains(node)) { + throw new IllegalArgumentException("Cyclic detected: " + + node + " " + graph.edges().get(node)); + } + return; + } + visited.add(node); + graph.edges().get(node).stream() + .forEach(x -> visit(x, visited, done)); + done.add(node); + result.addLast(node); + } + } +}
--- a/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java Tue Jan 24 00:30:25 2017 +0100 @@ -29,6 +29,7 @@ import java.util.*; import java.util.jar.*; import java.util.zip.*; +import static sun.security.action.GetPropertyAction.privilegedGetProperty; /** * This class is used to maintain mappings from packages, classes @@ -72,7 +73,7 @@ * be added to the index. Otherwise, just the directory names are added. */ private static final boolean metaInfFilenames = - "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames")); + "true".equals(privilegedGetProperty("sun.misc.JarIndex.metaInfFilenames")); /** * Constructs a new, empty jar index.
--- a/src/java.base/share/classes/module-info.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/module-info.java Tue Jan 24 00:30:25 2017 +0100 @@ -249,7 +249,6 @@ jdk.crypto.token; exports sun.security.jca to java.smartcardio, - java.xml.crypto, jdk.crypto.ec, jdk.crypto.token, jdk.naming.dns; @@ -279,6 +278,7 @@ java.security.jgss, java.security.sasl, java.smartcardio, + java.xml.crypto, jdk.crypto.ec, jdk.crypto.token, jdk.jartool, @@ -290,6 +290,8 @@ jdk.crypto.token, jdk.jartool, jdk.security.auth; + exports sun.security.validator to + jdk.jartool; exports sun.text.resources to jdk.localedata; exports sun.util.cldr to @@ -308,7 +310,6 @@ // JDK-internal service types uses jdk.internal.logger.DefaultLoggerFinder; uses sun.security.ssl.ClientKeyExchangeService; - uses sun.security.util.AuthResourcesProvider; uses sun.text.spi.JavaTimeDateTimePatternProvider; uses sun.util.spi.CalendarProvider; uses sun.util.locale.provider.LocaleDataMetaInfo; @@ -320,6 +321,4 @@ provides java.nio.file.spi.FileSystemProvider with jdk.internal.jrtfs.JrtFileSystemProvider; - provides sun.security.util.AuthResourcesProvider with - sun.security.util.AuthResourcesProviderImpl; }
--- a/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java Tue Jan 24 00:30:25 2017 +0100 @@ -96,7 +96,7 @@ final Class<?> declaringClass = m.getDeclaringClass(); - checkPackageAccess(declaringClass); + privateCheckPackageAccess(sm, declaringClass); if (Modifier.isPublic(m.getModifiers()) && Modifier.isPublic(declaringClass.getModifiers())) @@ -114,9 +114,27 @@ * also check the package access on the proxy interfaces. */ public static void checkPackageAccess(Class<?> clazz) { - checkPackageAccess(clazz.getName()); + SecurityManager s = System.getSecurityManager(); + if (s != null) { + privateCheckPackageAccess(s, clazz); + } + } + + /** + * NOTE: should only be called if a SecurityManager is installed + */ + private static void privateCheckPackageAccess(SecurityManager s, Class<?> clazz) { + while (clazz.isArray()) { + clazz = clazz.getComponentType(); + } + + String pkg = clazz.getPackageName(); + if (pkg != null && !pkg.isEmpty()) { + s.checkPackageAccess(pkg); + } + if (isNonPublicProxyClass(clazz)) { - checkProxyPackageAccess(clazz); + privateCheckProxyPackageAccess(s, clazz); } } @@ -195,15 +213,21 @@ public static void checkProxyPackageAccess(Class<?> clazz) { SecurityManager s = System.getSecurityManager(); if (s != null) { - // check proxy interfaces if the given class is a proxy class - if (Proxy.isProxyClass(clazz)) { - for (Class<?> intf : clazz.getInterfaces()) { - checkPackageAccess(intf); - } + privateCheckProxyPackageAccess(s, clazz); + } + } + + /** + * NOTE: should only be called if a SecurityManager is installed + */ + private static void privateCheckProxyPackageAccess(SecurityManager s, Class<?> clazz) { + // check proxy interfaces if the given class is a proxy class + if (Proxy.isProxyClass(clazz)) { + for (Class<?> intf : clazz.getInterfaces()) { + privateCheckPackageAccess(s, intf); } } } - /** * Access check on the interfaces that a proxy class implements and throw * {@code SecurityException} if it accesses a restricted package from @@ -220,7 +244,7 @@ for (Class<?> intf : interfaces) { ClassLoader cl = intf.getClassLoader(); if (needsPackageAccessCheck(ccl, cl)) { - checkPackageAccess(intf); + privateCheckPackageAccess(sm, intf); } } } @@ -236,10 +260,11 @@ * package that bypasses checkPackageAccess. */ public static boolean isNonPublicProxyClass(Class<?> cls) { - String name = cls.getName(); - int i = name.lastIndexOf('.'); - String pkg = (i != -1) ? name.substring(0, i) : ""; - return Proxy.isProxyClass(cls) && !pkg.startsWith(PROXY_PACKAGE); + if (!Proxy.isProxyClass(cls)) { + return false; + } + String pkg = cls.getPackageName(); + return pkg == null || !pkg.startsWith(PROXY_PACKAGE); } /** @@ -255,7 +280,7 @@ // check if it is a valid proxy instance if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) { throw new IllegalArgumentException("Not a Proxy instance"); -} + } if (Modifier.isStatic(method.getModifiers())) { throw new IllegalArgumentException("Can't handle static method"); }
--- a/src/java.base/share/classes/sun/security/provider/ConfigFile.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/provider/ConfigFile.java Tue Jan 24 00:30:25 2017 +0100 @@ -331,9 +331,8 @@ if (debugConfig != null) { debugConfig.println(fnfe.toString()); } - throw new IOException(ResourcesMgr.getString - ("Configuration.Error.No.such.file.or.directory", - "sun.security.util.AuthResources")); + throw new IOException(ResourcesMgr.getAuthResourceString + ("Configuration.Error.No.such.file.or.directory")); } } @@ -661,8 +660,8 @@ } private IOException ioException(String resourceKey, Object... args) { - MessageFormat form = new MessageFormat(ResourcesMgr.getString - (resourceKey, "sun.security.util.AuthResources")); + MessageFormat form = new MessageFormat( + ResourcesMgr.getAuthResourceString(resourceKey)); return new IOException(form.format(args)); } }
--- a/src/java.base/share/classes/sun/security/provider/DSA.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/provider/DSA.java Tue Jan 24 00:30:25 2017 +0100 @@ -322,19 +322,20 @@ } else { // first decode the signature. try { - DerInputStream in = new DerInputStream(signature, offset, - length); + // Enforce strict DER checking for signatures + DerInputStream in = + new DerInputStream(signature, offset, length, false); DerValue[] values = in.getSequence(2); + // check number of components in the read sequence + // and trailing data + if ((values.length != 2) || (in.available() != 0)) { + throw new IOException("Invalid encoding for signature"); + } r = values[0].getBigInteger(); s = values[1].getBigInteger(); - - // Check for trailing signature data - if (in.available() != 0) { - throw new IOException("Incorrect signature length"); - } } catch (IOException e) { - throw new SignatureException("invalid encoding for signature"); + throw new SignatureException("Invalid encoding for signature", e); } } @@ -427,13 +428,49 @@ return t5.mod(q); } - // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1. protected BigInteger generateK(BigInteger q) { + // Implementation defined in FIPS 186-4 AppendixB.2.1. SecureRandom random = getSigningRandom(); byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8]; random.nextBytes(kValue); - return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE); + BigInteger k = new BigInteger(1, kValue).mod( + q.subtract(BigInteger.ONE)).add(BigInteger.ONE); + + // Using an equivalent exponent of fixed length (same as q or 1 bit + // less than q) to keep the kG timing relatively constant. + // + // Note that this is an extra step on top of the approach defined in + // FIPS 186-4 AppendixB.2.1 so as to make a fixed length K. + k = k.add(q).divide(BigInteger.TWO); + + // An alternative implementation based on FIPS 186-4 AppendixB2.2 + // with fixed-length K. + // + // Please keep it here as we may need to switch to it in the future. + // + // SecureRandom random = getSigningRandom(); + // byte[] kValue = new byte[(q.bitLength() + 7)/8]; + // BigInteger d = q.subtract(BigInteger.TWO); + // BigInteger k; + // do { + // random.nextBytes(kValue); + // BigInteger c = new BigInteger(1, kValue); + // if (c.compareTo(d) <= 0) { + // k = c.add(BigInteger.ONE); + // // Using an equivalent exponent of fixed length to keep + // // the g^k timing relatively constant. + // // + // // Note that this is an extra step on top of the approach + // // defined in FIPS 186-4 AppendixB.2.2 so as to make a + // // fixed length K. + // if (k.bitLength() >= q.bitLength()) { + // break; + // } + // } + // } while (true); + + return k; } // Use the application-specified SecureRandom Object if provided.
--- a/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java Tue Jan 24 00:30:25 2017 +0100 @@ -34,6 +34,7 @@ import javax.security.auth.Subject; import sun.security.provider.PolicyParser.PrincipalEntry; +import sun.security.util.ResourcesMgr; /** * <p> This <code>SubjectCodeSource</code> class contains @@ -47,15 +48,6 @@ private static final long serialVersionUID = 6039418085604715275L; - private static final java.util.ResourceBundle rb = - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction<java.util.ResourceBundle>() { - public java.util.ResourceBundle run() { - return (java.util.ResourceBundle.getBundle - ("sun.security.util.AuthResources")); - } - }); - private Subject subject; private LinkedList<PrincipalEntry> principals; private static final Class<?>[] PARAMS = { String.class }; @@ -391,7 +383,7 @@ ListIterator<PrincipalEntry> li = principals.listIterator(); while (li.hasNext()) { PrincipalEntry pppe = li.next(); - returnMe = returnMe + rb.getString("NEWLINE") + + returnMe = returnMe + ResourcesMgr.getAuthResourceString("NEWLINE") + pppe.getPrincipalClass() + " " + pppe.getPrincipalName(); }
--- a/src/java.base/share/classes/sun/security/rsa/RSASignature.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/rsa/RSASignature.java Tue Jan 24 00:30:25 2017 +0100 @@ -226,9 +226,10 @@ * Decode the signature data. Verify that the object identifier matches * and return the message digest. */ - public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature) + public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig) throws IOException { - DerInputStream in = new DerInputStream(signature); + // Enforce strict DER checking for signatures + DerInputStream in = new DerInputStream(sig, 0, sig.length, false); DerValue[] values = in.getSequence(2); if ((values.length != 2) || (in.available() != 0)) { throw new IOException("SEQUENCE length error");
--- a/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Tue Jan 24 00:30:25 2017 +0100 @@ -673,8 +673,11 @@ } else { // we wanted to resume, but the server refused // - // Invalidate the session in case of reusing next time. - session.invalidate(); + // Invalidate the session for initial handshake in case + // of reusing next time. + if (isInitialHandshake) { + session.invalidate(); + } session = null; if (!enableNewSession) { throw new SSLException("New session creation is disabled");
--- a/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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 @@ -818,6 +818,11 @@ checker.init(false); } catch (CertPathValidatorException cpve) { // unlikely to happen + if (useDebug) { + debug.println( + "Cannot initialize algorithm constraints checker: " + cpve); + } + return false; } @@ -828,6 +833,11 @@ // We don't care about the unresolved critical extensions. checker.check(cert, Collections.<String>emptySet()); } catch (CertPathValidatorException cpve) { + if (useDebug) { + debug.println("Certificate (" + cert + + ") does not conform to algorithm constraints: " + cpve); + } + return false; } }
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -3522,7 +3522,8 @@ System.err.flush(); reply = (new BufferedReader(new InputStreamReader (System.in))).readLine(); - if (collator.compare(reply, "") == 0 || + if (reply == null || + collator.compare(reply, "") == 0 || collator.compare(reply, rb.getString("n")) == 0 || collator.compare(reply, rb.getString("no")) == 0) { reply = "NO";
--- a/src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java Wed Jan 25 15:31:01 2017 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +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 sun.security.util; - -public interface AuthResourcesProvider extends java.util.spi.ResourceBundleProvider { -}
--- a/src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java Wed Jan 25 15:31:01 2017 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +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 sun.security.util; - -import java.util.spi.AbstractResourceBundleProvider; - -public final class AuthResourcesProviderImpl extends AbstractResourceBundleProvider - implements AuthResourcesProvider { - public AuthResourcesProviderImpl() { - super("java.class"); - } -} \ No newline at end of file
--- a/src/java.base/share/classes/sun/security/util/DerInputBuffer.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/util/DerInputBuffer.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -147,6 +147,11 @@ System.arraycopy(buf, pos, bytes, 0, len); skip(len); + // check to make sure no extra leading 0s for DER + if (len >= 2 && (bytes[0] == 0) && (bytes[1] >= 0)) { + throw new IOException("Invalid encoding: redundant leading 0s"); + } + if (makePositive) { return new BigInteger(1, bytes); } else {
--- a/src/java.base/share/classes/sun/security/util/DerInputStream.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/util/DerInputStream.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -77,7 +77,7 @@ * @param data the buffer from which to create the string (CONSUMED) */ public DerInputStream(byte[] data) throws IOException { - init(data, 0, data.length); + init(data, 0, data.length, true); } /** @@ -92,23 +92,48 @@ * starting at "offset" */ public DerInputStream(byte[] data, int offset, int len) throws IOException { - init(data, offset, len); + init(data, offset, len, true); + } + + /** + * Create a DER input stream from part of a data buffer with + * additional arg to indicate whether to allow constructed + * indefinite-length encoding. + * The buffer is not copied, it is shared. Accordingly, the + * buffer should be treated as read-only. + * + * @param data the buffer from which to create the string (CONSUMED) + * @param offset the first index of <em>data</em> which will + * be read as DER input in the new stream + * @param len how long a chunk of the buffer to use, + * starting at "offset" + * @param allowIndefiniteLength whether to allow constructed + * indefinite-length encoding + */ + public DerInputStream(byte[] data, int offset, int len, + boolean allowIndefiniteLength) throws IOException { + init(data, offset, len, allowIndefiniteLength); } /* * private helper routine */ - private void init(byte[] data, int offset, int len) throws IOException { + private void init(byte[] data, int offset, int len, + boolean allowIndefiniteLength) throws IOException { if ((offset+2 > data.length) || (offset+len > data.length)) { throw new IOException("Encoding bytes too short"); } // check for indefinite length encoding if (DerIndefLenConverter.isIndefinite(data[offset+1])) { - byte[] inData = new byte[len]; - System.arraycopy(data, offset, inData, 0, len); + if (!allowIndefiniteLength) { + throw new IOException("Indefinite length BER encoding found"); + } else { + byte[] inData = new byte[len]; + System.arraycopy(data, offset, inData, 0, len); - DerIndefLenConverter derIn = new DerIndefLenConverter(); - buffer = new DerInputBuffer(derIn.convert(inData)); + DerIndefLenConverter derIn = new DerIndefLenConverter(); + buffer = new DerInputBuffer(derIn.convert(inData)); + } } else buffer = new DerInputBuffer(data, offset, len); buffer.mark(Integer.MAX_VALUE); @@ -239,15 +264,19 @@ * representation. */ length--; - int validBits = length*8 - buffer.read(); + int excessBits = buffer.read(); + if (excessBits < 0) { + throw new IOException("Unused bits of bit string invalid"); + } + int validBits = length*8 - excessBits; if (validBits < 0) { - throw new IOException("valid bits of bit string invalid"); + throw new IOException("Valid bits of bit string invalid"); } byte[] repn = new byte[length]; if ((length != 0) && (buffer.read(repn) != length)) { - throw new IOException("short read of DER bit string"); + throw new IOException("Short read of DER bit string"); } return new BitArray(validBits, repn); @@ -263,7 +292,7 @@ int length = getDefiniteLength(buffer); byte[] retval = new byte[length]; if ((length != 0) && (buffer.read(retval) != length)) - throw new IOException("short read of DER octet string"); + throw new IOException("Short read of DER octet string"); return retval; } @@ -273,7 +302,7 @@ */ public void getBytes(byte[] val) throws IOException { if ((val.length != 0) && (buffer.read(val) != val.length)) { - throw new IOException("short read of DER octet string"); + throw new IOException("Short read of DER octet string"); } } @@ -357,7 +386,7 @@ DerInputStream newstr; byte lenByte = (byte)buffer.read(); - int len = getLength((lenByte & 0xff), buffer); + int len = getLength(lenByte, buffer); if (len == -1) { // indefinite length encoding found @@ -403,7 +432,7 @@ } while (newstr.available() > 0); if (newstr.available() != 0) - throw new IOException("extra data at end of vector"); + throw new IOException("Extra data at end of vector"); /* * Now stick them into the array we're returning. @@ -494,7 +523,7 @@ int length = getDefiniteLength(buffer); byte[] retval = new byte[length]; if ((length != 0) && (buffer.read(retval) != length)) - throw new IOException("short read of DER " + + throw new IOException("Short read of DER " + stringName + " string"); return new String(retval, enc); @@ -555,7 +584,11 @@ */ static int getLength(int lenByte, InputStream in) throws IOException { int value, tmp; + if (lenByte == -1) { + throw new IOException("Short read of DER length"); + } + String mdName = "DerInputStream.getLength(): "; tmp = lenByte; if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum value = tmp; @@ -569,17 +602,23 @@ if (tmp == 0) return -1; if (tmp < 0 || tmp > 4) - throw new IOException("DerInputStream.getLength(): lengthTag=" - + tmp + ", " + throw new IOException(mdName + "lengthTag=" + tmp + ", " + ((tmp < 0) ? "incorrect DER encoding." : "too big.")); - for (value = 0; tmp > 0; tmp --) { + value = 0x0ff & in.read(); + tmp--; + if (value == 0) { + // DER requires length value be encoded in minimum number of bytes + throw new IOException(mdName + "Redundant length bytes found"); + } + while (tmp-- > 0) { value <<= 8; value += 0x0ff & in.read(); } if (value < 0) { - throw new IOException("DerInputStream.getLength(): " - + "Invalid length bytes"); + throw new IOException(mdName + "Invalid length bytes"); + } else if (value <= 127) { + throw new IOException(mdName + "Should use short form for length"); } } return value;
--- a/src/java.base/share/classes/sun/security/util/DerValue.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/util/DerValue.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -248,7 +248,7 @@ tag = (byte)in.read(); byte lenByte = (byte)in.read(); - length = DerInputStream.getLength((lenByte & 0xff), in); + length = DerInputStream.getLength(lenByte, in); if (length == -1) { // indefinite length encoding found DerInputBuffer inbuf = in.dup(); int readLen = inbuf.available(); @@ -361,7 +361,7 @@ tag = (byte)in.read(); byte lenByte = (byte)in.read(); - length = DerInputStream.getLength((lenByte & 0xff), in); + length = DerInputStream.getLength(lenByte, in); if (length == -1) { // indefinite length encoding found int readLen = in.available(); int offset = 2; // for tag and length bytes
--- a/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Tue Jan 24 00:30:25 2017 +0100 @@ -255,7 +255,13 @@ + " (tag = " + type_id + ")" ); - encoding = new byte[in.getDefiniteLength()]; + int len = in.getDefiniteLength(); + if (len > in.available()) { + throw new IOException("ObjectIdentifier() -- length exceeds" + + "data available. Length: " + len + ", Available: " + + in.available()); + } + encoding = new byte[len]; in.getBytes(encoding); check(encoding); }
--- a/src/java.base/share/classes/sun/security/util/ResourcesMgr.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/classes/sun/security/util/ResourcesMgr.java Tue Jan 24 00:30:25 2017 +0100 @@ -25,18 +25,22 @@ package sun.security.util; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.concurrent.ConcurrentHashMap; +import jdk.internal.misc.VM; + /** */ public class ResourcesMgr { + // intended for java.security, javax.security and sun.security resources + private final static String RESOURCES = "sun.security.util.Resources"; + private final static String AUTH_RESOURCES = "sun.security.util.AuthResources"; - // intended for java.security, javax.security and sun.security resources - private static java.util.ResourceBundle bundle; - - // intended for com.sun.security resources - private static java.util.ResourceBundle altBundle; + private final static Map<String, ResourceBundle> bundles = new ConcurrentHashMap<>(); public static String getString(String s) { - + ResourceBundle bundle = bundles.get(RESOURCES); if (bundle == null) { // only load if/when needed @@ -52,19 +56,15 @@ return bundle.getString(s); } - public static String getString(String s, final String altBundleName) { - - if (altBundle == null) { - - // only load if/when needed - altBundle = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<java.util.ResourceBundle>() { - public java.util.ResourceBundle run() { - return (java.util.ResourceBundle.getBundle(altBundleName)); - } - }); + public static String getAuthResourceString(String s) { + if (VM.initLevel() == 3) { + // cannot trigger loading of any resource bundle as + // it depends on the system class loader fully initialized. + throw new InternalError("system class loader is being initialized"); } - return altBundle.getString(s); + return bundles.computeIfAbsent(AUTH_RESOURCES, ResourceBundle::getBundle) + .getString(s); } + }
--- a/src/java.base/share/conf/security/java.security Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/conf/security/java.security Tue Jan 24 00:30:25 2017 +0100 @@ -298,111 +298,24 @@ # # List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageAccess unless the -# corresponding RuntimePermission ("accessClassInPackage."+package) has -# been granted. -package.access=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.dom3.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.sun.tools.script.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - jdk.tools.jimage.,\ - com.sun.activation.registries.,\ - com.sun.java.accessibility.util.internal.,\ -#ifdef windows - com.sun.java.accessibility.internal.,\ -#endif -#ifdef macosx - apple.,\ -#endif +# will cause a security exception to be thrown when passed to the +# SecurityManager::checkPackageAccess method unless the corresponding +# RuntimePermission("accessClassInPackage."+package) has been granted. +# +package.access=sun.misc.,\ + sun.reflect.,\ # # List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageDefinition unless the -# corresponding RuntimePermission ("defineClassInPackage."+package) has -# been granted. +# will cause a security exception to be thrown when passed to the +# SecurityManager::checkPackageDefinition method unless the corresponding +# RuntimePermission("defineClassInPackage."+package) has been granted. # -# by default, none of the class loaders supplied with the JDK call +# By default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.dom3.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.sun.tools.script.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - jdk.tools.jimage.,\ - com.sun.activation.registries.,\ - com.sun.java.accessibility.util.internal.,\ -#ifdef windows - com.sun.java.accessibility.internal.,\ -#endif -#ifdef macosx - apple.,\ -#endif +package.definition=sun.misc.,\ + sun.reflect.,\ # # Determines whether this properties file can be appended to @@ -658,6 +571,36 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & denyAfter 2017-01-01, \ RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224 +# +# RMI Registry Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI Registry. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +#sun.rmi.registry.registryFilter=pattern;pattern +# +# RMI Distributed Garbage Collector (DGC) Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI DGC. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# The builtin DGC filter can approximately be represented as the filter pattern: +# +#sun.rmi.transport.dgcFilter=\ +# java.rmi.server.ObjID;\ +# java.rmi.server.UID;\ +# java.rmi.dgc.VMID;\ +# java.rmi.dgc.Lease;\ +# maxdepth=5;maxarray=10000 + # Algorithm restrictions for signed JAR files # # In some environments, certain algorithms or key lengths may be undesirable @@ -720,7 +663,7 @@ # Note: The algorithm restrictions do not apply to trust anchors or # self-signed certificates. # -# Note: This property is currently used by Oracle's JSSE implementation. +# Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # # Example: @@ -740,7 +683,7 @@ # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # -# The syntax of the disabled algorithm string is described as this Java +# The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " @@ -776,7 +719,7 @@ # javax.net.ssl.SSLParameters.setAlgorithmConstraints()), # then the algorithm is completely disabled and will not be negotiated. # -# Note: This property is currently used by Oracle's JSSE implementation. +# Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. @@ -789,7 +732,8 @@ DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ DH_RSA_EXPORT, RSA_EXPORT, \ DH_anon, ECDH_anon, \ - RC4_128, RC4_40, DES_CBC, DES40_CBC + RC4_128, RC4_40, DES_CBC, DES40_CBC, \ + 3DES_EDE_CBC # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. @@ -912,7 +856,7 @@ # Constraint {"," Constraint } # Constraint: # AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | -# ReferenceUriSchemeConstraint | OtherConstraint +# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint # AlgConstraint # "disallowAlg" Uri # MaxTransformsConstraint: @@ -921,12 +865,16 @@ # "maxReferences" Integer # ReferenceUriSchemeConstraint: # "disallowReferenceUriSchemes" String { String } +# KeySizeConstraint: +# "minKeySize" KeyAlg Integer # OtherConstraint: # "noDuplicateIds" | "noRetrievalMethodLoops" # # For AlgConstraint, Uri is the algorithm URI String that is not allowed. # See the XML Signature Recommendation for more information on algorithm -# URI Identifiers. If the MaxTransformsConstraint or MaxReferencesConstraint is +# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm +# name of the key type (ex: "RSA"). If the MaxTransformsConstraint, +# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is # specified more than once, only the last entry is enforced. # # Note: This property is currently used by the JDK Reference implementation. It @@ -940,6 +888,8 @@ maxTransforms 5,\ maxReferences 30,\ disallowReferenceUriSchemes file http https,\ + minKeySize RSA 1024,\ + minKeySize DSA 1024,\ noDuplicateIds,\ noRetrievalMethodLoops
--- a/src/java.base/share/lib/security/default.policy Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/lib/security/default.policy Tue Jan 24 00:30:25 2017 +0100 @@ -81,6 +81,8 @@ }; grant codeBase "jrt:/java.xml.crypto" { + permission java.lang.RuntimePermission + "accessClassInPackage.sun.security.util"; permission java.util.PropertyPermission "*", "read"; permission java.security.SecurityPermission "putProviderProperty.XMLDSig"; permission java.security.SecurityPermission @@ -91,10 +93,20 @@ "com.sun.org.apache.xml.internal.security.register"; permission java.security.SecurityPermission "getProperty.jdk.xml.dsig.secureValidationPolicy"; + permission java.lang.RuntimePermission + "accessClassInPackage.com.sun.org.apache.xml.internal.*"; + permission java.lang.RuntimePermission + "accessClassInPackage.com.sun.org.apache.xpath.internal"; + permission java.lang.RuntimePermission + "accessClassInPackage.com.sun.org.apache.xpath.internal.*"; }; grant codeBase "jrt:/java.xml.ws" { permission java.lang.RuntimePermission + "accessClassInPackage.com.sun.org.apache.xml.internal.resolver"; + permission java.lang.RuntimePermission + "accessClassInPackage.com.sun.org.apache.xml.internal.resolver.tools"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*"; permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal"; @@ -186,3 +198,18 @@ permission java.util.PropertyPermission "os.name", "read"; }; +grant codeBase "jrt:/jdk.accessibility" { + permission java.lang.RuntimePermission "accessClassInPackage.sun.awt"; +}; + +grant codeBase "jrt:/jdk.desktop" { + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.awt"; +}; + +// permissions needed by applications using java.desktop module +grant { + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.beans"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.beans.*"; + permission java.lang.RuntimePermission "accessClassInPackage.com.sun.java.swing.plaf.*"; + permission java.lang.RuntimePermission "accessClassInPackage.com.apple.*"; +};
--- a/src/java.base/share/native/libnet/net_util.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/native/libnet/net_util.c Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -64,10 +64,10 @@ preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s); /* - Since we have initialized and loaded the Socket library we will - check now to whether we have IPv6 on this platform and if the - supporting socket APIs are available - */ + * Since we have initialized and loaded the socket library we will + * check now whether we have IPv6 on this platform and if the + * supporting socket APIs are available + */ IPv6_available = IPv6_supported() & (!preferIPv4Stack); /* check if SO_REUSEPORT is supported on this platform */ @@ -120,16 +120,16 @@ return JNI_TRUE; } -int getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) { +jboolean getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) { jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); - CHECK_NULL_RETURN(holder, -1); + CHECK_NULL_RETURN(holder, JNI_FALSE); return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID); } -int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) { +unsigned int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) { jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); - CHECK_NULL_RETURN(holder, -1); - return (*env)->GetIntField(env, holder, ia6_scopeidID); + CHECK_NULL_RETURN(holder, 0); + return (unsigned int)(*env)->GetIntField(env, holder, ia6_scopeidID); } jboolean setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) { @@ -201,11 +201,10 @@ } JNIEXPORT jobject JNICALL -NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { +NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port) { jobject iaObj; - if (him->sa_family == AF_INET6) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - jbyte *caddr = (jbyte *)&(him6->sin6_addr); + if (sa->sa.sa_family == AF_INET6) { + jbyte *caddr = (jbyte *)&sa->sa6.sin6_addr; if (NET_IsIPv4Mapped(caddr)) { int address; iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); @@ -214,42 +213,35 @@ setInetAddress_addr(env, iaObj, address); setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4); } else { - jint scope; jboolean ret; iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID); CHECK_NULL_RETURN(iaObj, NULL); - ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr)); + ret = setInet6Address_ipaddress(env, iaObj, (char *)&sa->sa6.sin6_addr); if (ret == JNI_FALSE) return NULL; setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6); - scope = getScopeID(him); - setInet6Address_scopeid(env, iaObj, scope); + setInet6Address_scopeid(env, iaObj, sa->sa6.sin6_scope_id); } - *port = ntohs(him6->sin6_port); + *port = ntohs(sa->sa6.sin6_port); } else { - struct sockaddr_in *him4 = (struct sockaddr_in *)him; iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID); CHECK_NULL_RETURN(iaObj, NULL); setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4); - setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr)); - *port = ntohs(him4->sin_port); + setInetAddress_addr(env, iaObj, ntohl(sa->sa4.sin_addr.s_addr)); + *port = ntohs(sa->sa4.sin_port); } return iaObj; } -JNIEXPORT jint JNICALL -NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) +JNIEXPORT jboolean JNICALL +NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj) { - jint family = AF_INET; - - family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ? - AF_INET : AF_INET6; - if (him->sa_family == AF_INET6) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - jbyte *caddrNew = (jbyte *)&(him6->sin6_addr); + jint family = getInetAddress_family(env, iaObj) == + java_net_InetAddress_IPv4 ? AF_INET : AF_INET6; + if (sa->sa.sa_family == AF_INET6) { + jbyte *caddrNew = (jbyte *)&sa->sa6.sin6_addr; if (NET_IsIPv4Mapped(caddrNew)) { - int addrNew; - int addrCur; + int addrNew, addrCur; if (family == AF_INET6) { return JNI_FALSE; } @@ -262,26 +254,24 @@ } } else { jbyte caddrCur[16]; - int scope; - if (family == AF_INET) { return JNI_FALSE; } - scope = getInet6Address_scopeid(env, iaObj); getInet6Address_ipaddress(env, iaObj, (char *)caddrCur); - if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) { + if (NET_IsEqual(caddrNew, caddrCur) && + sa->sa6.sin6_scope_id == getInet6Address_scopeid(env, iaObj)) + { return JNI_TRUE; } else { return JNI_FALSE; } } } else { - struct sockaddr_in *him4 = (struct sockaddr_in *)him; int addrNew, addrCur; if (family != AF_INET) { return JNI_FALSE; } - addrNew = ntohl(him4->sin_addr.s_addr); + addrNew = ntohl(sa->sa4.sin_addr.s_addr); addrCur = getInetAddress_addr(env, iaObj); if (addrNew == addrCur) { return JNI_TRUE; @@ -291,6 +281,15 @@ } } +JNIEXPORT jint JNICALL +NET_GetPortFromSockaddr(SOCKETADDRESS *sa) { + if (sa->sa.sa_family == AF_INET6) { + return ntohs(sa->sa6.sin6_port); + } else { + return ntohs(sa->sa4.sin_port); + } +} + unsigned short in_cksum(unsigned short *addr, int len) { int nleft = len;
--- a/src/java.base/share/native/libnet/net_util.h Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/share/native/libnet/net_util.h Tue Jan 24 00:30:25 2017 +0100 @@ -63,8 +63,8 @@ */ extern jobject getInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj); extern jboolean setInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj, jobject scopeifname); -extern int getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj); -extern int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj); +extern jboolean getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj); +extern unsigned int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj); extern jboolean setInet6Address_scopeid(JNIEnv *env, jobject ia6Obj, int scopeid); extern jboolean getInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *dest); extern jboolean setInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *address); @@ -132,24 +132,41 @@ JNIEXPORT jint JNICALL reuseport_available(); +/** + * This function will fill a SOCKETADDRESS structure from an InetAddress + * object. + * + * The parameter 'sa' must point to valid storage of size + * 'sizeof(SOCKETADDRESS)'. + * + * The parameter 'len' is a pointer to an int and is used for returning + * the actual sockaddr length, e.g. 'sizeof(struct sockaddr_in)' or + * 'sizeof(struct sockaddr_in6)'. + * + * If the type of the InetAddress object is IPv6, the function will fill a + * sockaddr_in6 structure. IPv6 must be available in that case, otherwise an + * exception is thrown. + * In the case of an IPv4 InetAddress, when IPv6 is available and + * v4MappedAddress is TRUE, this method will fill a sockaddr_in6 structure + * containing an IPv4 mapped IPv6 address. Otherwise a sockaddr_in + * structure will be filled. + */ JNIEXPORT int JNICALL NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, - struct sockaddr *him, int *len, + SOCKETADDRESS *sa, int *len, jboolean v4MappedAddress); JNIEXPORT jobject JNICALL -NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port); +NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port); void platformInit(); void parseExclusiveBindProperty(JNIEnv *env); -void NET_SetTrafficClass(struct sockaddr *him, int trafficClass); +JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(SOCKETADDRESS *sa); -JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(struct sockaddr *him); - -JNIEXPORT jint JNICALL -NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj); +JNIEXPORT jboolean JNICALL +NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj); int NET_IsIPv4Mapped(jbyte* caddr); @@ -172,7 +189,7 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, int len); JNIEXPORT int JNICALL -NET_Bind(int fd, struct sockaddr *him, int len); +NET_Bind(int fd, SOCKETADDRESS *sa, int len); JNIEXPORT int JNICALL NET_MapSocketOption(jint cmd, int *level, int *optname); @@ -183,10 +200,6 @@ JNIEXPORT jint JNICALL NET_EnableFastTcpLoopback(int fd); -int getScopeID(struct sockaddr *); - -int cmpScopeID(unsigned int, struct sockaddr *); - unsigned short in_cksum(unsigned short *addr, int len); jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
--- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -211,7 +211,8 @@ { int port; int index = (family == AF_INET) ? i++ : j++; - jobject o = NET_SockaddrToInetAddress(env, iter->ifa_addr, &port); + jobject o = NET_SockaddrToInetAddress(env, + (SOCKETADDRESS *)iter->ifa_addr, &port); if (!o) { freeifaddrs(ifa); if (!(*env)->ExceptionCheck(env))
--- a/src/java.base/unix/native/libnet/NetworkInterface.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnet/NetworkInterface.c Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -791,7 +791,7 @@ int sock; sock = openSocket(env, AF_INET); - if (sock < 0 && (*env)->ExceptionOccurred(env)) { + if (sock < 0) { return NULL; } @@ -809,7 +809,7 @@ // so we have to call ipv6_available() if (ipv6_available()) { sock = openSocket(env, AF_INET6); - if (sock < 0 && (*env)->ExceptionOccurred(env)) { + if (sock < 0) { freeif(ifs); return NULL; }
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -99,7 +99,7 @@ CHECK_NULL_RETURN(i_class, NULL); } - return ( (*env)->NewObject(env, i_class, i_ctrID, i) ); + return (*env)->NewObject(env, i_class, i_ctrID, i); } /* @@ -118,10 +118,9 @@ CHECK_NULL_RETURN(b_class, NULL); } - return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) ); + return (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b != 0)); } - /* * Returns the fd for a PlainDatagramSocketImpl or -1 * if closed. @@ -134,7 +133,6 @@ return (*env)->GetIntField(env, fdObj, IO_fd_fdID); } - /* * Class: java_net_PlainDatagramSocketImpl * Method: init @@ -166,7 +164,6 @@ initInetAddressIDs(env); JNU_CHECK_EXCEPTION(env); Java_java_net_NetworkInterface_init(env, 0); - } /* @@ -176,13 +173,13 @@ */ JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, - jint localport, jobject iaObj) { + jint localport, jobject iaObj) { /* fdObj is the FileDescriptor field on this */ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); /* fd is an int field on fdObj */ int fd; int len = 0; - SOCKETADDRESS him; + SOCKETADDRESS sa; socklen_t slen = sizeof(SOCKETADDRESS); if (IS_NULL(fdObj)) { @@ -199,12 +196,13 @@ } /* bind */ - if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa, &len, JNI_TRUE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len, + JNI_TRUE) != 0) { return; } - setDefaultScopeID(env, &him.sa); + setDefaultScopeID(env, &sa.sa); - if (NET_Bind(fd, &him.sa, len) < 0) { + if (NET_Bind(fd, &sa, len) < 0) { if (errno == EADDRINUSE || errno == EADDRNOTAVAIL || errno == EPERM || errno == EACCES) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException", @@ -221,13 +219,13 @@ /* Now that we're a connected socket, let's extract the port number * that the system chose for us and store it in the Socket object. */ - if (getsockname(fd, &him.sa, &slen) == -1) { + if (getsockname(fd, &sa.sa, &slen) == -1) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); return; } - localport = NET_GetPortFromSockaddr(&him.sa); + localport = NET_GetPortFromSockaddr(&sa); (*env)->SetIntField(env, this, pdsi_localPortID, localport); } else { @@ -263,7 +261,8 @@ return; } - if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr.sa, &len, JNI_TRUE) != 0) { + if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr, &len, + JNI_TRUE) != 0) { return; } @@ -290,6 +289,9 @@ #if defined(__linux__) || defined(_ALLBSD_SOURCE) SOCKETADDRESS addr; socklen_t len; +#if defined(__linux__) + int localPort = 0; +#endif #endif if (IS_NULL(fdObj)) { @@ -298,32 +300,31 @@ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); #if defined(__linux__) || defined(_ALLBSD_SOURCE) - memset(&addr, 0, sizeof(addr)); - if (ipv6_available()) { - addr.sa6.sin6_family = AF_UNSPEC; - len = sizeof(struct sockaddr_in6); + memset(&addr, 0, sizeof(addr)); + if (ipv6_available()) { + addr.sa6.sin6_family = AF_UNSPEC; + len = sizeof(struct sockaddr_in6); + } else { + addr.sa4.sin_family = AF_UNSPEC; + len = sizeof(struct sockaddr_in); + } + NET_Connect(fd, &addr.sa, len); + +#if defined(__linux__) + if (getsockname(fd, &addr.sa, &len) == -1) + return; + + localPort = NET_GetPortFromSockaddr(&addr); + if (localPort == 0) { + localPort = (*env)->GetIntField(env, this, pdsi_localPortID); + if (addr.sa.sa_family == AF_INET6) { + addr.sa6.sin6_port = htons(localPort); } else { - addr.sa4.sin_family = AF_UNSPEC; - len = sizeof(struct sockaddr_in); + addr.sa4.sin_port = htons(localPort); } - NET_Connect(fd, &addr.sa, len); -#ifdef __linux__ - int localPort = 0; - if (getsockname(fd, &addr.sa, &len) == -1) - return; - - localPort = NET_GetPortFromSockaddr(&addr.sa); - if (localPort == 0) { - localPort = (*env)->GetIntField(env, this, pdsi_localPortID); - if (addr.sa.sa_family == AF_INET6) { - addr.sa6.sin6_port = htons(localPort); - } else { - addr.sa4.sin_port = htons(localPort); - } - - NET_Bind(fd, &addr.sa, len); - } + NET_Bind(fd, &addr, len); + } #endif #else @@ -355,8 +356,9 @@ /* The fdObj'fd */ jint fd; - SOCKETADDRESS rmtaddr, *rmtaddrP = &rmtaddr; - int len; + SOCKETADDRESS rmtaddr; + struct sockaddr *rmtaddrP = 0; + int len = 0; if (IS_NULL(fdObj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", @@ -382,15 +384,14 @@ packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); packetBufferLen = (*env)->GetIntField(env, packet, dp_lengthID); - if (connected) { - /* arg to NET_Sendto () null in this case */ - len = 0; - rmtaddrP = 0; - } else { + // arg to NET_Sendto() null, if connected + if (!connected) { packetPort = (*env)->GetIntField(env, packet, dp_portID); - if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, &rmtaddr.sa, &len, JNI_TRUE) != 0) { + if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, &rmtaddr, + &len, JNI_TRUE) != 0) { return; } + rmtaddrP = &rmtaddr.sa; } setDefaultScopeID(env, &rmtaddr.sa); @@ -427,7 +428,7 @@ (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen, (jbyte *)fullPacket); if (trafficClass != 0 && ipv6_available()) { - NET_SetTrafficClass(&rmtaddr.sa, trafficClass); + NET_SetTrafficClass(&rmtaddr, trafficClass); } /* @@ -437,8 +438,7 @@ * ECONNREFUSED indicating that an ICMP port unreachable has * received. */ - ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0, - (struct sockaddr *)rmtaddrP, len); + ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0, rmtaddrP, len); if (ret < 0) { if (errno == ECONNREFUSED) { @@ -510,7 +510,7 @@ #ifdef __solaris__ if (errno == ECONNREFUSED) { int orig_errno = errno; - (void) recv(fd, buf, 1, 0); + recv(fd, buf, 1, 0); errno = orig_errno; } #endif @@ -528,7 +528,7 @@ return 0; } - iaObj = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port); + iaObj = NET_SockaddrToInetAddress(env, &rmtaddr, &port); family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ? AF_INET : AF_INET6; if (family == AF_INET) { /* this API can't handle IPV6 addresses */ @@ -676,18 +676,18 @@ */ packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr.sa, packetAddress)) { + if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr, packetAddress)) { /* force a new InetAddress to be created */ packetAddress = NULL; } } if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port); + packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr, &port); /* stuff the new Inetaddress in the packet */ (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); } else { /* only get the new port number */ - port = NET_GetPortFromSockaddr(&rmtaddr.sa); + port = NET_GetPortFromSockaddr(&rmtaddr); } /* and fill in the data, remote address/port and such */ (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, @@ -857,18 +857,19 @@ */ packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr.sa, packetAddress)) { + if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr, + packetAddress)) { /* force a new InetAddress to be created */ packetAddress = NULL; } } if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port); + packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr, &port); /* stuff the new Inetaddress in the packet */ (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); } else { /* only get the new port number */ - port = NET_GetPortFromSockaddr(&rmtaddr.sa); + port = NET_GetPortFromSockaddr(&rmtaddr); } /* and fill in the data, remote address/port and such */ (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, @@ -1040,6 +1041,7 @@ /* * We need an ipv4 address here */ + in.s_addr = 0; for (i = 0; i < len; i++) { addr = (*env)->GetObjectArrayElement(env, addrArray, i); if (getInetAddress_family(env, addr) == java_net_InetAddress_IPv4) { @@ -1049,7 +1051,7 @@ } if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char*)&in, sizeof(in)) < 0) { + (const char *)&in, sizeof(in)) < 0) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error setting socket option"); } @@ -1670,17 +1672,17 @@ */ if (opt == java_net_SocketOptions_SO_BINDADDR) { /* find out local IP address */ - SOCKETADDRESS him; + SOCKETADDRESS sa; socklen_t len = sizeof(SOCKETADDRESS); int port; jobject iaObj; - if (getsockname(fd, &him.sa, &len) == -1) { + if (getsockname(fd, &sa.sa, &len) == -1) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); return NULL; } - iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port); + iaObj = NET_SockaddrToInetAddress(env, &sa, &port); return iaObj; } @@ -1969,6 +1971,7 @@ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj)); #ifdef __linux__ mname.imr_address.s_addr = htonl(getInetAddress_addr(env, addr)); + mname.imr_ifindex = 0; #else mname.imr_interface.s_addr = htonl(getInetAddress_addr(env, addr)); #endif @@ -2023,7 +2026,7 @@ #ifdef __linux__ mname.imr_address.s_addr = in.s_addr; - + mname.imr_ifindex = 0; #else mname.imr_interface.s_addr = in.s_addr; #endif
--- a/src/java.base/unix/native/libnet/PlainSocketImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -244,7 +244,7 @@ /* fd is an int field on iaObj */ jint fd; - SOCKETADDRESS him; + SOCKETADDRESS sa; /* The result of the connection */ int connect_rv = -1; @@ -260,17 +260,18 @@ } /* connect */ - if (NET_InetAddressToSockaddr(env, iaObj, port, &him.sa, &len, JNI_TRUE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len, + JNI_TRUE) != 0) { return; } - setDefaultScopeID(env, &him.sa); + setDefaultScopeID(env, &sa.sa); if (trafficClass != 0 && ipv6_available()) { - NET_SetTrafficClass(&him.sa, trafficClass); + NET_SetTrafficClass(&sa, trafficClass); } if (timeout <= 0) { - connect_rv = NET_Connect(fd, &him.sa, len); + connect_rv = NET_Connect(fd, &sa.sa, len); #ifdef __solaris__ if (connect_rv == -1 && errno == EINPROGRESS ) { @@ -319,7 +320,7 @@ SET_NONBLOCKING(fd); /* no need to use NET_Connect as non-blocking */ - connect_rv = connect(fd, &him.sa, len); + connect_rv = connect(fd, &sa.sa, len); /* connection not established immediately */ if (connect_rv != 0) { @@ -467,11 +468,11 @@ * that the system chose for us and store it in the Socket object. */ socklen_t slen = sizeof(SOCKETADDRESS); - if (getsockname(fd, &him.sa, &slen) == -1) { + if (getsockname(fd, &sa.sa, &slen) == -1) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); } else { - localport = NET_GetPortFromSockaddr(&him.sa); + localport = NET_GetPortFromSockaddr(&sa); (*env)->SetIntField(env, this, psi_localportID, localport); } } @@ -490,8 +491,8 @@ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); /* fd is an int field on fdObj */ int fd; - int len; - SOCKETADDRESS him; + int len = 0; + SOCKETADDRESS sa; if (IS_NULL(fdObj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", @@ -506,13 +507,13 @@ } /* bind */ - if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa, + if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len, JNI_TRUE) != 0) { return; } - setDefaultScopeID(env, &him.sa); + setDefaultScopeID(env, &sa.sa); - if (NET_Bind(fd, &him.sa, len) < 0) { + if (NET_Bind(fd, &sa, len) < 0) { if (errno == EADDRINUSE || errno == EADDRNOTAVAIL || errno == EPERM || errno == EACCES) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException", @@ -533,12 +534,12 @@ /* Now that we're a connected socket, let's extract the port number * that the system chose for us and store it in the Socket object. */ - if (getsockname(fd, &him.sa, &slen) == -1) { + if (getsockname(fd, &sa.sa, &slen) == -1) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); return; } - localport = NET_GetPortFromSockaddr(&him.sa); + localport = NET_GetPortFromSockaddr(&sa); (*env)->SetIntField(env, this, psi_localportID, localport); } else { (*env)->SetIntField(env, this, psi_localportID, localport); @@ -606,7 +607,7 @@ /* accepted fd */ jint newfd; - SOCKETADDRESS him; + SOCKETADDRESS sa; socklen_t slen = sizeof(SOCKETADDRESS); if (IS_NULL(fdObj)) { @@ -661,7 +662,7 @@ return; } - newfd = NET_Accept(fd, &him.sa, &slen); + newfd = NET_Accept(fd, &sa.sa, &slen); /* connection accepted */ if (newfd >= 0) { @@ -709,7 +710,7 @@ /* * fill up the remote peer port and address in the new socket structure. */ - socketAddressObj = NET_SockaddrToInetAddress(env, &him.sa, &port); + socketAddressObj = NET_SockaddrToInetAddress(env, &sa, &port); if (socketAddressObj == NULL) { /* should be pending exception */ close(newfd); @@ -944,19 +945,19 @@ * SO_BINDADDR isn't a socket option */ if (cmd == java_net_SocketOptions_SO_BINDADDR) { - SOCKETADDRESS him; + SOCKETADDRESS sa; socklen_t len = sizeof(SOCKETADDRESS); int port; jobject iaObj; jclass iaCntrClass; jfieldID iaFieldID; - if (getsockname(fd, &him.sa, &len) < 0) { + if (getsockname(fd, &sa.sa, &len) < 0) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); return -1; } - iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port); + iaObj = NET_SockaddrToInetAddress(env, &sa, &port); CHECK_NULL_RETURN(iaObj, -1); iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
--- a/src/java.base/unix/native/libnet/SocketOutputStream.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnet/SocketOutputStream.c Tue Jan 24 00:30:25 2017 +0100 @@ -98,27 +98,31 @@ int llen = chunkLen; (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP); - while(llen > 0) { - int n = NET_Send(fd, bufP + loff, llen, 0); - if (n > 0) { - llen -= n; - loff += n; - continue; + if ((*env)->ExceptionCheck(env)) { + break; + } else { + while(llen > 0) { + int n = NET_Send(fd, bufP + loff, llen, 0); + if (n > 0) { + llen -= n; + loff += n; + continue; + } + if (errno == ECONNRESET) { + JNU_ThrowByName(env, "sun/net/ConnectionResetException", + "Connection reset"); + } else { + JNU_ThrowByNameWithMessageAndLastError + (env, "java/net/SocketException", "Write failed"); + } + if (bufP != BUF) { + free(bufP); + } + return; } - if (errno == ECONNRESET) { - JNU_ThrowByName(env, "sun/net/ConnectionResetException", - "Connection reset"); - } else { - JNU_ThrowByNameWithMessageAndLastError - (env, "java/net/SocketException", "Write failed"); - } - if (bufP != BUF) { - free(bufP); - } - return; + len -= chunkLen; + off += chunkLen; } - len -= chunkLen; - off += chunkLen; } if (bufP != BUF) {
--- a/src/java.base/unix/native/libnet/net_util_md.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnet/net_util_md.c Tue Jan 24 00:30:25 2017 +0100 @@ -234,29 +234,6 @@ } return kernelV24; } - -int getScopeID (struct sockaddr *him) { - struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him; - return hext->sin6_scope_id; -} - -int cmpScopeID (unsigned int scope, struct sockaddr *him) { - struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him; - return hext->sin6_scope_id == scope; -} - -#else - -int getScopeID (struct sockaddr *him) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - return him6->sin6_scope_id; -} - -int cmpScopeID (unsigned int scope, struct sockaddr *him) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - return him6->sin6_scope_id == scope; -} - #endif void @@ -775,30 +752,32 @@ return 0; } -/* In the case of an IPv4 Inetaddress this method will return an - * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE. - * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress. -*/ +/** + * See net_util.h for documentation + */ JNIEXPORT int JNICALL -NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, - int *len, jboolean v4MappedAddress) { - jint family; - family = getInetAddress_family(env, iaObj); - /* needs work. 1. family 2. clean up him6 etc deallocate memory */ - if (ipv6_available() && !(family == java_net_InetAddress_IPv4 && - v4MappedAddress == JNI_FALSE)) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; +NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, + SOCKETADDRESS *sa, int *len, + jboolean v4MappedAddress) +{ + jint family = getInetAddress_family(env, iaObj); + memset((char *)sa, 0, sizeof(SOCKETADDRESS)); + + if (ipv6_available() && + !(family == java_net_InetAddress_IPv4 && + v4MappedAddress == JNI_FALSE)) + { jbyte caddr[16]; jint address; if (family == java_net_InetAddress_IPv4) { // convert to IPv4-mapped address - memset((char *) caddr, 0, 16); + memset((char *)caddr, 0, 16); address = getInetAddress_addr(env, iaObj); if (address == INADDR_ANY) { /* we would always prefer IPv6 wildcard address - caddr[10] = 0xff; - caddr[11] = 0xff; */ + * caddr[10] = 0xff; + * caddr[11] = 0xff; */ } else { caddr[10] = 0xff; caddr[11] = 0xff; @@ -810,22 +789,19 @@ } else { getInet6Address_ipaddress(env, iaObj, (char *)caddr); } - memset((char *)him6, 0, sizeof(struct sockaddr_in6)); - him6->sin6_port = htons(port); - memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) ); - him6->sin6_family = AF_INET6; - *len = sizeof(struct sockaddr_in6); + sa->sa6.sin6_port = htons(port); + memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr)); + sa->sa6.sin6_family = AF_INET6; + if (len != NULL) { + *len = sizeof(struct sockaddr_in6); + } -#if defined(_ALLBSD_SOURCE) -// XXXBSD: should we do something with scope id here ? see below linux comment -/* MMM: Come back to this! */ -#endif - +#ifdef __linux__ /* * On Linux if we are connecting to a link-local address * we need to specify the interface in the scope_id (2.4 kernel only) * - * If the scope was cached the we use the cached value. If not cached but + * If the scope was cached then we use the cached value. If not cached but * specified in the Inet6Address we use that, but we first check if the * address needs to be routed via the loopback interface. In this case, * we override the specified value with that of the loopback interface. @@ -833,9 +809,8 @@ * we try to determine a value from the routing table. In all these * cases the used value is cached for further use. */ -#ifdef __linux__ - if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) { - int cached_scope_id = 0, scope_id = 0; + if (IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr)) { + unsigned int cached_scope_id = 0, scope_id = 0; if (ia6_cachedscopeidID) { cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); @@ -850,7 +825,7 @@ /* check user-specified value for loopback case * that needs to be overridden */ - if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) { + if (kernelIsV24() && needsLoopbackRoute(&sa->sa6.sin6_addr)) { cached_scope_id = lo_scope_id; (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); } @@ -860,11 +835,11 @@ * try determine the appropriate interface. */ if (kernelIsV24()) { - cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr)); + cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr); } else { - cached_scope_id = getLocalScopeID((char *)&(him6->sin6_addr)); + cached_scope_id = getLocalScopeID((char *)&(sa->sa6.sin6_addr)); if (cached_scope_id == 0) { - cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr)); + cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr); } } (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); @@ -876,53 +851,37 @@ * If we have a scope_id use the extended form * of sockaddr_in6. */ - - struct sockaddr_in6 *him6 = - (struct sockaddr_in6 *)him; - him6->sin6_scope_id = cached_scope_id != 0 ? - cached_scope_id : scope_id; - *len = sizeof(struct sockaddr_in6); + sa->sa6.sin6_scope_id = cached_scope_id == 0 ? scope_id : cached_scope_id; } #else - /* handle scope_id for solaris */ - + /* handle scope_id */ if (family != java_net_InetAddress_IPv4) { if (ia6_scopeidID) { - him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj); + sa->sa6.sin6_scope_id = getInet6Address_scopeid(env, iaObj); } } #endif } else { - struct sockaddr_in *him4 = (struct sockaddr_in *)him; jint address; - if (family == java_net_InetAddress_IPv6) { + if (family != java_net_InetAddress_IPv4) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); return -1; } - memset((char *)him4, 0, sizeof(struct sockaddr_in)); address = getInetAddress_addr(env, iaObj); - him4->sin_port = htons((short) port); - him4->sin_addr.s_addr = htonl(address); - him4->sin_family = AF_INET; - *len = sizeof(struct sockaddr_in); + sa->sa4.sin_port = htons(port); + sa->sa4.sin_addr.s_addr = htonl(address); + sa->sa4.sin_family = AF_INET; + if (len != NULL) { + *len = sizeof(struct sockaddr_in); + } } return 0; } void -NET_SetTrafficClass(struct sockaddr *him, int trafficClass) { - if (him->sa_family == AF_INET6) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20); - } -} - -JNIEXPORT jint JNICALL -NET_GetPortFromSockaddr(struct sockaddr *him) { - if (him->sa_family == AF_INET6) { - return ntohs(((struct sockaddr_in6*)him)->sin6_port); - } else { - return ntohs(((struct sockaddr_in*)him)->sin_port); +NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass) { + if (sa->sa.sa_family == AF_INET6) { + sa->sa6.sin6_flowinfo = htonl((trafficClass & 0xff) << 20); } } @@ -1488,7 +1447,7 @@ * */ int -NET_Bind(int fd, struct sockaddr *him, int len) +NET_Bind(int fd, SOCKETADDRESS *sa, int len) { #if defined(__solaris__) int level = -1; @@ -1503,9 +1462,8 @@ * ## When IPv6 is enabled this will be an IPv4-mapped * ## with family set to AF_INET6 */ - if (him->sa_family == AF_INET) { - struct sockaddr_in *sa = (struct sockaddr_in *)him; - if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) { + if (sa->sa.sa_family == AF_INET) { + if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) { errno = EADDRNOTAVAIL; return -1; } @@ -1524,8 +1482,9 @@ */ alen = sizeof(arg); - if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (char *)&arg, &alen) == 0) { + if (useExclBind || + getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0) + { if (useExclBind || arg == 0) { /* * SO_REUSEADDR is disabled or sun.net.useExclusiveBind @@ -1533,8 +1492,8 @@ * UDP_EXCLBIND */ alen = sizeof(arg); - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, - &alen) == 0) { + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0) + { if (arg == SOCK_STREAM) { level = IPPROTO_TCP; exclbind = TCP_EXCLBIND; @@ -1545,14 +1504,13 @@ } arg = 1; - setsockopt(fd, level, exclbind, (char *)&arg, - sizeof(arg)); + setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg)); } } #endif - rv = bind(fd, him, len); + rv = bind(fd, &sa->sa, len); #if defined(__solaris__) if (rv < 0) {
--- a/src/java.base/unix/native/libnet/net_util_md.h Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnet/net_util_md.h Tue Jan 24 00:30:25 2017 +0100 @@ -30,6 +30,44 @@ #include <sys/poll.h> #include <sys/socket.h> +/************************************************************************ + * Macros and constants + */ + +/* Defines SO_REUSEPORT */ +#ifndef SO_REUSEPORT +#ifdef __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif + +/* + * On 64-bit JDKs we use a much larger stack and heap buffer. + */ +#ifdef _LP64 +#define MAX_BUFFER_LEN 65536 +#define MAX_HEAP_BUFFER_LEN 131072 +#else +#define MAX_BUFFER_LEN 8192 +#define MAX_HEAP_BUFFER_LEN 65536 +#endif + +typedef union { + struct sockaddr sa; + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; +} SOCKETADDRESS; + +/************************************************************************ + * Functions + */ + int NET_Timeout(int s, long timeout); int NET_Timeout0(int s, long timeout, long currentTime); int NET_Read(int s, void* buf, size_t len); @@ -55,44 +93,7 @@ int gai_error); void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, const char *defaultDetail); - -/************************************************************************ - * Macros and constants - */ - -/* Defines SO_REUSEPORT */ -#ifndef SO_REUSEPORT -#ifdef __linux__ -#define SO_REUSEPORT 15 -#elif __solaris__ -#define SO_REUSEPORT 0x100e -#elif defined(AIX) || defined(MACOSX) -#define SO_REUSEPORT 0x0200 -#else -#define SO_REUSEPORT 0 -#endif -#endif - -/* - * On 64-bit JDKs we use a much larger stack and heap buffer. - */ -#ifdef _LP64 -#define MAX_BUFFER_LEN 65536 -#define MAX_HEAP_BUFFER_LEN 131072 -#else -#define MAX_BUFFER_LEN 8192 -#define MAX_HEAP_BUFFER_LEN 65536 -#endif - -typedef union { - struct sockaddr sa; - struct sockaddr_in sa4; - struct sockaddr_in6 sa6; -} SOCKETADDRESS; - -/************************************************************************ - * Utilities - */ +void NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass); #ifdef __linux__ int kernelIsV24();
--- a/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -181,11 +181,11 @@ */ senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID); if (senderAddr != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, &sa.sa, senderAddr)) { + if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) { senderAddr = NULL; } else { jint port = (*env)->GetIntField(env, this, dci_senderPortID); - if (port != NET_GetPortFromSockaddr(&sa.sa)) { + if (port != NET_GetPortFromSockaddr(&sa)) { senderAddr = NULL; } } @@ -193,7 +193,7 @@ if (senderAddr == NULL) { jobject isa = NULL; int port = 0; - jobject ia = NET_SockaddrToInetAddress(env, &sa.sa, &port); + jobject ia = NET_SockaddrToInetAddress(env, &sa, &port); if (ia != NULL) { isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port); } @@ -201,7 +201,7 @@ (*env)->SetObjectField(env, this, dci_senderAddrID, ia); (*env)->SetIntField(env, this, dci_senderPortID, - NET_GetPortFromSockaddr(&sa.sa)); + NET_GetPortFromSockaddr(&sa)); (*env)->SetObjectField(env, this, dci_senderID, isa); } return n; @@ -215,14 +215,14 @@ jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKETADDRESS sa; - int sa_len = sizeof(SOCKETADDRESS); + int sa_len = 0; jint n = 0; if (len > MAX_PACKET_LEN) { len = MAX_PACKET_LEN; } - if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa.sa, + if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa, &sa_len, preferIPv6) != 0) { return IOS_THROWN; }
--- a/src/java.base/unix/native/libnio/ch/InheritedChannel.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnio/ch/InheritedChannel.c Tue Jan 24 00:30:25 2017 +0100 @@ -64,7 +64,7 @@ if (getpeername(fd, &sa.sa, &len) == 0) { if (matchFamily(&sa.sa)) { - remote_ia = NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port); + remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); } } @@ -81,7 +81,7 @@ if (getpeername(fd, &sa.sa, &len) == 0) { if (matchFamily(&sa.sa)) { - NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port); + NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); } }
--- a/src/java.base/unix/native/libnio/ch/Net.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnio/ch/Net.c Tue Jan 24 00:30:25 2017 +0100 @@ -274,15 +274,15 @@ jboolean useExclBind, jobject iao, int port) { SOCKETADDRESS sa; - int sa_len = sizeof(SOCKETADDRESS); + int sa_len = 0; int rv = 0; - if (NET_InetAddressToSockaddr(env, iao, port, &sa.sa, &sa_len, + if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) { return; } - rv = NET_Bind(fdval(env, fdo), &sa.sa, sa_len); + rv = NET_Bind(fdval(env, fdo), &sa, sa_len); if (rv != 0) { handleSocketError(env, errno); } @@ -300,10 +300,10 @@ jobject fdo, jobject iao, jint port) { SOCKETADDRESS sa; - int sa_len = sizeof(SOCKETADDRESS); + int sa_len = 0; int rv; - if (NET_InetAddressToSockaddr(env, iao, port, &sa.sa, &sa_len, + if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) { return IOS_THROWN; } @@ -349,7 +349,7 @@ return -1; #endif /* _ALLBSD_SOURCE */ } - return NET_GetPortFromSockaddr(&sa.sa); + return NET_GetPortFromSockaddr(&sa); } JNIEXPORT jobject JNICALL @@ -382,7 +382,7 @@ return NULL; #endif /* _ALLBSD_SOURCE */ } - return NET_SockaddrToInetAddress(env, &sa.sa, &port); + return NET_SockaddrToInetAddress(env, &sa, &port); } JNIEXPORT jint JNICALL
--- a/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -112,7 +112,7 @@ } (*env)->SetIntField(env, newfdo, fd_fdID, newfd); - remote_ia = NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port); + remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); CHECK_NULL_RETURN(remote_ia, IOS_THROWN); isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port); CHECK_NULL_RETURN(isa, IOS_THROWN);
--- a/src/java.base/windows/classes/java/io/WinNTFileSystem.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/classes/java/io/WinNTFileSystem.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -233,11 +233,14 @@ int childStart = 0; int parentEnd = pn; + boolean isDirectoryRelative = + pn == 2 && isLetter(parent.charAt(0)) && parent.charAt(1) == ':'; + if ((cn > 1) && (c.charAt(0) == slash)) { if (c.charAt(1) == slash) { /* Drop prefix when child is a UNC pathname */ childStart = 2; - } else { + } else if (!isDirectoryRelative) { /* Drop prefix when child is drive-relative */ childStart = 1; @@ -254,7 +257,7 @@ int strlen = parentEnd + cn - childStart; char[] theChars = null; - if (child.charAt(childStart) == slash) { + if (child.charAt(childStart) == slash || isDirectoryRelative) { theChars = new char[strlen]; parent.getChars(0, parentEnd, theChars, 0); child.getChars(childStart, cn, theChars, parentEnd);
--- a/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -53,7 +53,7 @@ break; } if (recvfrom(fd, buf, 1, MSG_PEEK, - (struct sockaddr *)&rmtaddr, &addrlen) != SOCKET_ERROR) { + &rmtaddr.sa, &addrlen) != SOCKET_ERROR) { break; } if (WSAGetLastError() != WSAECONNRESET) { @@ -61,7 +61,7 @@ break; } - recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen); + recvfrom(fd, buf, 1, 0, &rmtaddr.sa, &addrlen); got_icmp = JNI_TRUE; } @@ -134,14 +134,13 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) { SOCKETADDRESS sa; - int rv; - int sa_len = sizeof(sa); + int rv, sa_len = 0; - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, + if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &sa_len, JNI_TRUE) != 0) { return; } - rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind); + rv = NET_WinBind(fd, &sa, sa_len, exclBind); if (rv == SOCKET_ERROR) { if (WSAGetLastError() == WSAEACCES) { @@ -159,17 +158,15 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { SOCKETADDRESS sa; - int rv; - int sa_len = sizeof(sa); + int rv, sa_len = 0, t = TRUE; DWORD x1, x2; /* ignored result codes */ - int t = TRUE; - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, + if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &sa_len, JNI_TRUE) != 0) { return; } - rv = connect(fd, (struct sockaddr *)&sa, sa_len); + rv = connect(fd, &sa.sa, sa_len); if (rv == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "connect"); return; @@ -192,7 +189,7 @@ int t = FALSE; memset(&sa, 0, sa_len); - connect(fd, (struct sockaddr *)&sa, sa_len); + connect(fd, &sa.sa, sa_len); /* see comment in socketCreate */ WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0); @@ -219,7 +216,7 @@ SOCKETADDRESS sa; int len = sizeof(sa); - if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "getsockname"); return -1; } @@ -238,12 +235,12 @@ jobject iaObj; int port; - if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); return NULL; } - iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + iaObj = NET_SockaddrToInetAddress(env, &sa, &port); return iaObj; } @@ -316,7 +313,7 @@ /* receive the packet */ rv = recvfrom(fd, fullPacket, packetBufferLen, flags, - (struct sockaddr *)&sa, &sa_len); + &sa.sa, &sa_len); if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) { /* An icmp port unreachable - we must receive this as Windows @@ -383,15 +380,13 @@ */ packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID); if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa, - packetAddress)) { + if (!NET_SockaddrEqualsInetAddress(env, &sa, packetAddress)) { /* force a new InetAddress to be created */ packetAddress = NULL; } } if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, - &port); + packetAddress = NET_SockaddrToInetAddress(env, &sa, &port); if (packetAddress != NULL) { /* stuff the new Inetaddress into the packet */ (*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress); @@ -422,20 +417,18 @@ (JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length, jobject iaObj, jint port, jboolean connected) { SOCKETADDRESS sa; - int sa_len = sizeof(sa); - SOCKETADDRESS *sap = &sa; + int rv, sa_len = 0; + struct sockaddr *sap = 0; char BUF[MAX_BUFFER_LEN]; char *fullPacket; - int rv; - if (connected) { - sap = 0; /* arg to sendto () null in this case */ - sa_len = 0; - } else { - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, - &sa_len, JNI_TRUE) != 0) { + // if already connected, sap arg to sendto() is null + if (!connected) { + if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, + &sa_len, JNI_TRUE) != 0) { return; } + sap = &sa.sa; } if (length > MAX_BUFFER_LEN) { @@ -456,7 +449,7 @@ (*env)->GetByteArrayRegion(env, data, offset, length, (jbyte *)fullPacket); - rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len); + rv = sendto(fd, fullPacket, length, 0, sap, sa_len); if (rv == SOCKET_ERROR) { if (rv == -1) { NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");
--- a/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -89,15 +89,14 @@ jboolean exclBind) { SOCKETADDRESS sa; - int rv; - int sa_len = sizeof(sa); + int rv, sa_len = 0; - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, - &sa_len, JNI_TRUE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, + &sa_len, JNI_TRUE) != 0) { return; } - rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind); + rv = NET_WinBind(fd, &sa, sa_len, exclBind); if (rv == SOCKET_ERROR) NET_ThrowNew(env, WSAGetLastError(), "NET_Bind"); @@ -111,15 +110,14 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0 (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { SOCKETADDRESS sa; - int rv; - int sa_len = sizeof(sa); + int rv, sa_len = 0; - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, - &sa_len, JNI_TRUE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, + &sa_len, JNI_TRUE) != 0) { return -1; } - rv = connect(fd, (struct sockaddr *)&sa, sa_len); + rv = connect(fd, &sa.sa, sa_len); if (rv == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { @@ -217,7 +215,7 @@ SOCKETADDRESS sa; int len = sizeof(sa); - if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) { if (WSAGetLastError() == WSAENOTSOCK) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); @@ -243,11 +241,11 @@ jclass iaContainerClass; jfieldID iaFieldID; - if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); return; } - iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + iaObj = NET_SockaddrToInetAddress(env, &sa, &port); CHECK_NULL(iaObj); iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj); @@ -283,7 +281,7 @@ int len = sizeof(sa); memset((char *)&sa, 0, len); - newfd = accept(fd, (struct sockaddr *)&sa, &len); + newfd = accept(fd, &sa.sa, &len); if (newfd == INVALID_SOCKET) { if (WSAGetLastError() == -2) { @@ -298,7 +296,7 @@ SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0); - ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + ia = NET_SockaddrToInetAddress(env, &sa, &port); isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port); (*env)->SetObjectArrayElement(env, isaa, 0, isa);
--- a/src/java.base/windows/native/libnet/SocketOutputStream.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnet/SocketOutputStream.c Tue Jan 24 00:30:25 2017 +0100 @@ -92,66 +92,69 @@ int retry = 0; (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP); - - while(llen > 0) { - int n = send(fd, bufP + loff, llen, 0); - if (n > 0) { - llen -= n; - loff += n; - continue; - } - - /* - * Due to a bug in Windows Sockets (observed on NT and Windows - * 2000) it may be necessary to retry the send. The issue is that - * on blocking sockets send/WSASend is supposed to block if there - * is insufficient buffer space available. If there are a large - * number of threads blocked on write due to congestion then it's - * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. - * The workaround we use is to retry the send. If we have a - * large buffer to send (>2k) then we retry with a maximum of - * 2k buffer. If we hit the issue with <=2k buffer then we backoff - * for 1 second and retry again. We repeat this up to a reasonable - * limit before bailing out and throwing an exception. In load - * conditions we've observed that the send will succeed after 2-3 - * attempts but this depends on network buffers associated with - * other sockets draining. - */ - if (WSAGetLastError() == WSAENOBUFS) { - if (llen > MAX_BUFFER_LEN) { - buflen = MAX_BUFFER_LEN; - chunkLen = MAX_BUFFER_LEN; - llen = MAX_BUFFER_LEN; + if ((*env)->ExceptionCheck(env)) { + break; + } else { + while(llen > 0) { + int n = send(fd, bufP + loff, llen, 0); + if (n > 0) { + llen -= n; + loff += n; continue; } - if (retry >= 30) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "No buffer space available - exhausted attempts to queue buffer"); - if (bufP != BUF) { - free(bufP); + + /* + * Due to a bug in Windows Sockets (observed on NT and Windows + * 2000) it may be necessary to retry the send. The issue is that + * on blocking sockets send/WSASend is supposed to block if there + * is insufficient buffer space available. If there are a large + * number of threads blocked on write due to congestion then it's + * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. + * The workaround we use is to retry the send. If we have a + * large buffer to send (>2k) then we retry with a maximum of + * 2k buffer. If we hit the issue with <=2k buffer then we backoff + * for 1 second and retry again. We repeat this up to a reasonable + * limit before bailing out and throwing an exception. In load + * conditions we've observed that the send will succeed after 2-3 + * attempts but this depends on network buffers associated with + * other sockets draining. + */ + if (WSAGetLastError() == WSAENOBUFS) { + if (llen > MAX_BUFFER_LEN) { + buflen = MAX_BUFFER_LEN; + chunkLen = MAX_BUFFER_LEN; + llen = MAX_BUFFER_LEN; + continue; } - return; + if (retry >= 30) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "No buffer space available - exhausted attempts to queue buffer"); + if (bufP != BUF) { + free(bufP); + } + return; + } + Sleep(1000); + retry++; + continue; } - Sleep(1000); - retry++; - continue; + + /* + * Send failed - can be caused by close or write error. + */ + if (WSAGetLastError() == WSAENOTSOCK) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + } else { + NET_ThrowCurrent(env, "socket write error"); + } + if (bufP != BUF) { + free(bufP); + } + return; } - - /* - * Send failed - can be caused by close or write error. - */ - if (WSAGetLastError() == WSAENOTSOCK) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - } else { - NET_ThrowCurrent(env, "socket write error"); - } - if (bufP != BUF) { - free(bufP); - } - return; + len -= chunkLen; + off += chunkLen; } - len -= chunkLen; - off += chunkLen; } if (bufP != BUF) {
--- a/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -420,18 +420,13 @@ jboolean exclBind) { jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + int ipv6_supported = ipv6_available(); + int fd, fd1 = -1, lcladdrlen = 0; + SOCKETADDRESS lcladdr; - int fd, fd1 = -1, family; - int ipv6_supported = ipv6_available(); - - SOCKETADDRESS lcladdr; - int lcladdrlen = sizeof(SOCKETADDRESS); - int address; - - memset((char *)&lcladdr, 0, sizeof(lcladdr)); - - family = getInetAddress_family(env, addressObj); - if (family == java_net_InetAddress_IPv6 && !ipv6_supported) { + if (getInetAddress_family(env, addressObj) == java_net_InetAddress_IPv6 && + !ipv6_supported) + { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family not supported"); return; @@ -446,14 +441,13 @@ fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); } } + if (IS_NULL(addressObj)) { JNU_ThrowNullPointerException(env, "argument address"); return; - } else { - address = getInetAddress_addr(env, addressObj); } - if (NET_InetAddressToSockaddr(env, addressObj, port, &lcladdr.sa, + if (NET_InetAddressToSockaddr(env, addressObj, port, &lcladdr, &lcladdrlen, JNI_FALSE) != 0) { return; } @@ -493,7 +487,7 @@ return; } } else { - if (NET_WinBind(fd, &lcladdr.sa, lcladdrlen, exclBind) == -1) { + if (NET_WinBind(fd, &lcladdr, lcladdrlen, exclBind) == -1) { if (WSAGetLastError() == WSAEACCES) { WSASetLastError(WSAEADDRINUSE); } @@ -507,7 +501,7 @@ NET_ThrowCurrent(env, "getsockname"); return; } - port = ntohs((u_short) GET_PORT (&lcladdr)); + port = ntohs((u_short)GET_PORT(&lcladdr)); } (*env)->SetIntField(env, this, pdsi_localPortID, port); } @@ -520,27 +514,25 @@ */ JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this, - jobject address, jint port) { - /* The object's field */ +Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0 + (JNIEnv *env, jobject this, jobject address, jint port) +{ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - /* The fdObj'fd */ - jint fd=-1, fd1=-1, fdc; - /* The packetAddress address, family and port */ - jint addr, family; + jint fd = -1, fd1 = -1, fdc, family; SOCKETADDRESS rmtaddr; - int rmtaddrlen; - int ipv6_supported = ipv6_available(); + int rmtaddrlen = 0; if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); return; } + if (!IS_NULL(fdObj)) { fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); } + if (!IS_NULL(fd1Obj)) { fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); } @@ -550,10 +542,8 @@ return; } - addr = getInetAddress_addr(env, address); - family = getInetAddress_family(env, address); - if (family == java_net_InetAddress_IPv6 && !ipv6_supported) { + if (family == java_net_InetAddress_IPv6 && !ipv6_available()) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family not supported"); return; @@ -572,12 +562,12 @@ res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); } - if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr.sa, + if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr, &rmtaddrlen, JNI_FALSE) != 0) { return; } - if (connect(fdc, &rmtaddr.sa, sizeof(rmtaddr)) == -1) { + if (connect(fdc, &rmtaddr.sa, rmtaddrlen) == -1) { NET_ThrowCurrent(env, "connect"); return; } @@ -631,9 +621,9 @@ * Signature: (Ljava/net/DatagramPacket;)V */ JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, - jobject packet) { - +Java_java_net_TwoStacksPlainDatagramSocketImpl_send + (JNIEnv *env, jobject this, jobject packet) +{ char BUF[MAX_BUFFER_LEN]; char *fullPacket; jobject fdObj; @@ -647,11 +637,10 @@ jbyteArray packetBuffer; jboolean connected; - SOCKETADDRESS rmtaddr, *addrp = &rmtaddr; + SOCKETADDRESS rmtaddr; + struct sockaddr *addrp = 0; int addrlen = 0; - memset((char *)&rmtaddr, 0, sizeof(rmtaddr)); - if (IS_NULL(packet)) { JNU_ThrowNullPointerException(env, "null packet"); return; @@ -696,14 +685,13 @@ packetBufferLen = MAX_PACKET_LEN; } - if (connected) { - addrp = 0; /* arg to sendto () null in this case */ - addrlen = 0; - } else { - if (NET_InetAddressToSockaddr(env, iaObj, packetPort, &rmtaddr.sa, + // sockaddr arg to sendto() is null if already connected + if (!connected) { + if (NET_InetAddressToSockaddr(env, iaObj, packetPort, &rmtaddr, &addrlen, JNI_FALSE) != 0) { return; } + addrp = &rmtaddr.sa; } if (packetBufferLen > MAX_BUFFER_LEN) { @@ -753,11 +741,12 @@ fullPacket = &(BUF[0]); } - (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen, - (jbyte *)fullPacket); - if (sendto(fd, fullPacket, packetBufferLen, 0, - (struct sockaddr *)addrp, addrlen) == SOCKET_ERROR) { - NET_ThrowCurrent(env, "Datagram send failed"); + (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, + packetBufferLen, (jbyte *)fullPacket); + if (sendto(fd, fullPacket, packetBufferLen, 0, addrp, + addrlen) == SOCKET_ERROR) + { + NET_ThrowCurrent(env, "Datagram send failed"); } if (packetBufferLen > MAX_BUFFER_LEN) { @@ -1147,14 +1136,14 @@ */ packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, &remote_addr.sa, + if (!NET_SockaddrEqualsInetAddress(env, &remote_addr, packetAddress)) { /* force a new InetAddress to be created */ packetAddress = NULL; } } if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, &remote_addr.sa, + packetAddress = NET_SockaddrToInetAddress(env, &remote_addr, &port); /* stuff the new Inetaddress in the packet */ (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); @@ -1431,20 +1420,21 @@ * can't update any existing InetAddress because it is immutable */ packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); - if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, &remote_addr.sa, packetAddress)) { + if (!NET_SockaddrEqualsInetAddress(env, &remote_addr, + packetAddress)) { /* force a new InetAddress to be created */ packetAddress = NULL; } } if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, &remote_addr.sa, &port); + packetAddress = NET_SockaddrToInetAddress(env, &remote_addr, + &port); /* stuff the new Inetaddress in the packet */ (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); } else { /* only get the new port number */ - port = NET_GetPortFromSockaddr(&remote_addr.sa); + port = NET_GetPortFromSockaddr(&remote_addr); } /* populate the packet */ (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, @@ -1528,7 +1518,7 @@ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); int ipv6_supported = ipv6_available(); - int fd=-1, fd1=-1; + int fd = -1, fd1 = -1; if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) { return; @@ -1799,7 +1789,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption (JNIEnv *env,jobject this, jint opt,jobject value) { - int fd=-1, fd1=-1; + int fd = -1, fd1 = -1; int levelv4 = 0, levelv6 = 0, optnamev4 = 0, optnamev6 = 0, optlen = 0; union { int i; @@ -2167,7 +2157,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption (JNIEnv *env, jobject this, jint opt) { - int fd=-1, fd1=-1; + int fd = -1, fd1 = -1; int level, optname, optlen; union { int i; @@ -2255,7 +2245,7 @@ (JNIEnv *env, jobject this, jint family) { int fd = -1, fd1 = -1; - SOCKETADDRESS him; + SOCKETADDRESS sa; int len = 0; int port; jobject iaObj; @@ -2288,12 +2278,12 @@ return NULL; } - if (getsockname(fd, &him.sa, &len) == -1) { + if (getsockname(fd, &sa.sa, &len) == -1) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); return NULL; } - iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port); + iaObj = NET_SockaddrToInetAddress(env, &sa, &port); return iaObj; } @@ -2430,7 +2420,7 @@ int len, family; int ipv6_supported = ipv6_available(); - int cmd ; + int cmd; memset((char *)&in, 0, sizeof(in)); memset((char *)&name, 0, sizeof(name)); @@ -2452,7 +2442,7 @@ return; } - if (NET_InetAddressToSockaddr(env, iaObj, 0, &name.sa, &len, JNI_FALSE) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, 0, &name, &len, JNI_FALSE) != 0) { return; } @@ -2473,7 +2463,7 @@ return; } if (IS_NULL(niObj)) { - len = sizeof (in); + len = sizeof(in); if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&in, &len) < 0) { NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed");
--- a/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -175,8 +175,8 @@ */ JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, - jobject iaObj, jint port, - jint timeout) + jobject iaObj, jint port, + jint timeout) { jint localport = (*env)->GetIntField(env, this, psi_localportID); @@ -193,11 +193,11 @@ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - SOCKETADDRESS him; + SOCKETADDRESS sa; /* The result of the connection */ int connect_res; - memset((char *)&him, 0, sizeof(him)); + memset((char *)&sa, 0, sizeof(sa)); if (!IS_NULL(fdObj)) { fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); @@ -212,11 +212,12 @@ return; } - if (NET_InetAddressToSockaddr(env, iaObj, port, &him.sa, &len, JNI_FALSE) != 0) { - return; + if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len, + JNI_FALSE) != 0) { + return; } - family = him.sa.sa_family; + family = sa.sa.sa_family; if (family == AF_INET6) { if (!ipv6_supported) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", @@ -248,7 +249,7 @@ (*env)->SetObjectField(env, this, psi_fd1ID, NULL); if (timeout <= 0) { - connect_res = connect(fd, &him.sa, sizeof(SOCKETADDRESS)); + connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS)); if (connect_res == SOCKET_ERROR) { connect_res = WSAGetLastError(); } @@ -261,7 +262,7 @@ ioctlsocket(fd, FIONBIO, &optval); /* initiate the connect */ - connect_res = connect(fd, &him.sa, sizeof(SOCKETADDRESS)); + connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS)); if (connect_res == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { connect_res = WSAGetLastError(); @@ -362,7 +363,7 @@ */ u_short port; int len = sizeof(SOCKETADDRESS); - if (getsockname(fd, &him.sa, &len) == -1) { + if (getsockname(fd, &sa.sa, &len) == -1) { if (WSAGetLastError() == WSAENOTSOCK) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); @@ -371,7 +372,7 @@ } return; } - port = ntohs((u_short)GET_PORT(&him)); + port = ntohs((u_short)GET_PORT(&sa)); (*env)->SetIntField(env, this, psi_localportID, (int) port); } } @@ -396,7 +397,7 @@ int family; int rv; - SOCKETADDRESS him; + SOCKETADDRESS sa; fdObj = (*env)->GetObjectField(env, this, psi_fdID); fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); @@ -424,13 +425,13 @@ return; } - if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa, &len, + if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len, JNI_FALSE) != 0) { return; } if (ipv6_supported) { struct ipv6bind v6bind; - v6bind.addr = &him; + v6bind.addr = &sa.sa; v6bind.ipv4_fd = fd; v6bind.ipv6_fd = fd1; rv = NET_BindV6(&v6bind, exclBind); @@ -462,7 +463,7 @@ (*env)->SetObjectField(env, this, psi_fd1ID, NULL); } } else { - rv = NET_WinBind(fd, &him.sa, len, exclBind); + rv = NET_WinBind(fd, &sa, len, exclBind); } if (rv == -1) { @@ -481,11 +482,11 @@ int len = sizeof(SOCKETADDRESS); u_short port; - if (getsockname(him.sa.sa_family == AF_INET ? fd: fd1, &him.sa, &len) == -1) { + if (getsockname(sa.sa.sa_family == AF_INET ? fd : fd1, &sa.sa, &len) == -1) { NET_ThrowCurrent(env, "getsockname in plain socketBind"); return; } - port = ntohs((u_short) GET_PORT (&him)); + port = ntohs((u_short) GET_PORT (&sa)); (*env)->SetIntField(env, this, psi_localportID, (int)port); } else { @@ -529,7 +530,7 @@ JNU_ThrowNullPointerException(env, "socket address"); return; } - if (NET_InetAddressToSockaddr(env, address, 0, &addr.sa, &addrlen, + if (NET_InetAddressToSockaddr(env, address, 0, &addr, &addrlen, JNI_FALSE) != 0) { return; } @@ -585,7 +586,7 @@ /* the fd int field on fdObj */ jint fd=-1, fd1=-1; - SOCKETADDRESS him; + SOCKETADDRESS sa; jint len; if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { @@ -676,7 +677,7 @@ } } } - fd = accept(fd, &him.sa, &len); + fd = accept(fd, &sa.sa, &len); if (fd < 0) { /* REMIND: SOCKET CLOSED PROBLEM */ if (fd == -2) { @@ -691,7 +692,7 @@ SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0); (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd); - if (him.sa.sa_family == AF_INET) { + if (sa.sa.sa_family == AF_INET) { if (inet4Cls == NULL) { jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); if (c != NULL) { @@ -717,7 +718,7 @@ return; } - setInetAddress_addr(env, socketAddressObj, ntohl(him.sa4.sin_addr.s_addr)); + setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr)); setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4); (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); } else { @@ -743,14 +744,14 @@ NET_SocketClose(fd); return; } - setInet6Address_ipaddress(env, socketAddressObj, (char *)&him.sa6.sin6_addr); + setInet6Address_ipaddress(env, socketAddressObj, (char *)&sa.sa6.sin6_addr); setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6); - setInet6Address_scopeid(env, socketAddressObj, him.sa6.sin6_scope_id); + setInet6Address_scopeid(env, socketAddressObj, sa.sa6.sin6_scope_id); } /* fields common to AF_INET and AF_INET6 */ - port = ntohs ((u_short) GET_PORT (&him)); + port = ntohs ((u_short)GET_PORT(&sa)); (*env)->SetIntField(env, socket, psi_portID, (int)port); port = (*env)->GetIntField(env, this, psi_localportID); (*env)->SetIntField(env, socket, psi_localportID, port); @@ -1025,14 +1026,14 @@ * SO_BINDADDR isn't a socket option */ if (opt == java_net_SocketOptions_SO_BINDADDR) { - SOCKETADDRESS him; + SOCKETADDRESS sa; int len = sizeof(SOCKETADDRESS); int port; jobject iaObj; jclass iaCntrClass; jfieldID iaFieldID; - memset((char *)&him, 0, len); + memset((char *)&sa, 0, len); if (fd == -1) { /* must be an IPV6 only socket. Case where both sockets are != -1 @@ -1041,12 +1042,12 @@ fd = getFD1 (env, this); } - if (getsockname(fd, &him.sa, &len) < 0) { + if (getsockname(fd, &sa.sa, &len) < 0) { JNU_ThrowByNameWithMessageAndLastError (env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); return -1; } - iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port); + iaObj = NET_SockaddrToInetAddress(env, &sa, &port); CHECK_NULL_RETURN(iaObj, -1); iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
--- a/src/java.base/windows/native/libnet/net_util_md.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnet/net_util_md.c Tue Jan 24 00:30:25 2017 +0100 @@ -488,10 +488,10 @@ * Should be only called by the wrapper method NET_WinBind */ JNIEXPORT int JNICALL -NET_Bind(int s, struct sockaddr *him, int len) +NET_Bind(int s, SOCKETADDRESS *sa, int len) { int rv = 0; - rv = bind(s, him, len); + rv = bind(s, &sa->sa, len); if (rv == SOCKET_ERROR) { /* @@ -511,11 +511,11 @@ * if required, and then calls NET_BIND */ JNIEXPORT int JNICALL -NET_WinBind(int s, struct sockaddr *him, int len, jboolean exclBind) +NET_WinBind(int s, SOCKETADDRESS *sa, int len, jboolean exclBind) { if (exclBind == JNI_TRUE) setExclusiveBind(s); - return NET_Bind(s, him, len); + return NET_Bind(s, sa, len); } JNIEXPORT int JNICALL @@ -677,8 +677,8 @@ if (family == AF_INET && (b->addr->sa4.sin_addr.s_addr != INADDR_ANY)) { /* bind to v4 only */ int ret; - ret = NET_WinBind((int)b->ipv4_fd, (struct sockaddr *)b->addr, - sizeof(SOCKETADDRESS), exclBind); + ret = NET_WinBind((int)b->ipv4_fd, b->addr, + sizeof(SOCKETADDRESS), exclBind); if (ret == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } @@ -689,7 +689,7 @@ if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->sa6.sin6_addr))) { /* bind to v6 only */ int ret; - ret = NET_WinBind((int)b->ipv6_fd, (struct sockaddr *)b->addr, + ret = NET_WinBind((int)b->ipv6_fd, b->addr, sizeof(SOCKETADDRESS), exclBind); if (ret == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; @@ -719,7 +719,7 @@ oaddr.sa4.sin_addr.s_addr = INADDR_ANY; } - rv = NET_WinBind(fd, (struct sockaddr *)b->addr, sizeof(SOCKETADDRESS), exclBind); + rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind); if (rv == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } @@ -731,7 +731,7 @@ } bound_port = GET_PORT (b->addr); SET_PORT (&oaddr, bound_port); - if ((rv = NET_WinBind(ofd, &oaddr.sa, + if ((rv = NET_WinBind(ofd, &oaddr, sizeof(SOCKETADDRESS), exclBind)) == SOCKET_ERROR) { int retries; int sotype, arglen=sizeof(sotype); @@ -768,7 +768,7 @@ /* bind random port on first socket */ SET_PORT (&oaddr, 0); - rv = NET_WinBind(ofd, &oaddr.sa, sizeof(SOCKETADDRESS), exclBind); + rv = NET_WinBind(ofd, &oaddr, sizeof(SOCKETADDRESS), exclBind); if (rv == SOCKET_ERROR) { CLOSE_SOCKETS_AND_RETURN; } @@ -784,8 +784,7 @@ } bound_port = GET_PORT (&oaddr); SET_PORT (b->addr, bound_port); - rv = NET_WinBind(fd, (struct sockaddr *)b->addr, - sizeof(SOCKETADDRESS), exclBind); + rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind); if (rv != SOCKET_ERROR) { if (family == AF_INET) { @@ -853,31 +852,33 @@ return result == SOCKET_ERROR ? WSAGetLastError() : 0; } -/* If address types is IPv6, then IPv6 must be available. Otherwise - * no address can be generated. In the case of an IPv4 Inetaddress this - * method will return an IPv4 mapped address where IPv6 is available and - * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in - * structure for an IPv4 InetAddress. -*/ +/** + * See net_util.h for documentation + */ JNIEXPORT int JNICALL -NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, - int *len, jboolean v4MappedAddress) { - jint family, iafam; - iafam = getInetAddress_family(env, iaObj); - family = (iafam == java_net_InetAddress_IPv4)? AF_INET : AF_INET6; - if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; +NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, + SOCKETADDRESS *sa, int *len, + jboolean v4MappedAddress) +{ + jint family = getInetAddress_family(env, iaObj); + memset((char *)sa, 0, sizeof(SOCKETADDRESS)); + + if (ipv6_available() && + !(family == java_net_InetAddress_IPv4 && + v4MappedAddress == JNI_FALSE)) + { jbyte caddr[16]; - jint address, scopeid = 0; - jint cached_scope_id = 0; + jint address; + unsigned int scopeid = 0, cached_scope_id = 0; - if (family == AF_INET) { /* will convert to IPv4-mapped address */ - memset((char *) caddr, 0, 16); + if (family == java_net_InetAddress_IPv4) { + // convert to IPv4-mapped address + memset((char *)caddr, 0, 16); address = getInetAddress_addr(env, iaObj); if (address == INADDR_ANY) { /* we would always prefer IPv6 wildcard address - caddr[10] = 0xff; - caddr[11] = 0xff; */ + * caddr[10] = 0xff; + * caddr[11] = 0xff; */ } else { caddr[10] = 0xff; caddr[11] = 0xff; @@ -889,46 +890,39 @@ } else { getInet6Address_ipaddress(env, iaObj, (char *)caddr); scopeid = getInet6Address_scopeid(env, iaObj); - cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); + cached_scope_id = (unsigned int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); } - - memset((char *)him6, 0, sizeof(struct sockaddr_in6)); - him6->sin6_port = (u_short) htons((u_short)port); - memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) ); - him6->sin6_family = AF_INET6; - if ((family == AF_INET6) && IN6_IS_ADDR_LINKLOCAL( &(him6->sin6_addr) ) - && (!scopeid && !cached_scope_id)) { - cached_scope_id = getDefaultIPv6Interface(env, him6); + sa->sa6.sin6_port = (u_short)htons((u_short)port); + memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr)); + sa->sa6.sin6_family = AF_INET6; + if ((family == java_net_InetAddress_IPv6) && + IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr) && + (!scopeid && !cached_scope_id)) + { + cached_scope_id = getDefaultIPv6Interface(env, &sa->sa6); (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); } - him6->sin6_scope_id = scopeid != 0 ? scopeid : cached_scope_id; - *len = sizeof(struct sockaddr_in6) ; + sa->sa6.sin6_scope_id = scopeid == 0 ? cached_scope_id : scopeid; + if (len != NULL) { + *len = sizeof(struct sockaddr_in6); + } } else { - struct sockaddr_in *him4 = (struct sockaddr_in *)him; jint address; - if (family != AF_INET) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); - return -1; + if (family != java_net_InetAddress_IPv4) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable"); + return -1; } - memset((char *)him4, 0, sizeof(struct sockaddr_in)); address = getInetAddress_addr(env, iaObj); - him4->sin_port = htons((short) port); - him4->sin_addr.s_addr = (u_long) htonl(address); - him4->sin_family = AF_INET; - *len = sizeof(struct sockaddr_in); + sa->sa4.sin_port = htons((short)port); + sa->sa4.sin_addr.s_addr = (u_long)htonl(address); + sa->sa4.sin_family = AF_INET; + if (len != NULL) { + *len = sizeof(struct sockaddr_in); + } } return 0; } -JNIEXPORT jint JNICALL -NET_GetPortFromSockaddr(struct sockaddr *him) { - if (him->sa_family == AF_INET6) { - return ntohs(((struct sockaddr_in6 *)him)->sin6_port); - } else { - return ntohs(((struct sockaddr_in *)him)->sin_port); - } -} - int NET_IsIPv4Mapped(jbyte* caddr) { int i; @@ -961,16 +955,6 @@ return 1; } -int getScopeID(struct sockaddr *him) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - return him6->sin6_scope_id; -} - -int cmpScopeID(unsigned int scope, struct sockaddr *him) { - struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - return him6->sin6_scope_id == scope; -} - /** * Wrapper for select/poll with timeout on a single file descriptor. *
--- a/src/java.base/windows/native/libnet/net_util_md.h Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnet/net_util_md.h Tue Jan 24 00:30:25 2017 +0100 @@ -121,7 +121,7 @@ JNIEXPORT int JNICALL NET_BindV6(struct ipv6bind *b, jboolean exclBind); -JNIEXPORT int JNICALL NET_WinBind(int s, struct sockaddr *him, int len, +JNIEXPORT int JNICALL NET_WinBind(int s, SOCKETADDRESS *sa, int len, jboolean exclBind); /* XP versions of the native routines */
--- a/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -96,7 +96,7 @@ break; } if (recvfrom(fd, buf, 1, MSG_PEEK, - (struct sockaddr *)&sa, &addrlen) != SOCKET_ERROR) { + &sa.sa, &addrlen) != SOCKET_ERROR) { break; } if (WSAGetLastError() != WSAECONNRESET) { @@ -104,7 +104,7 @@ break; } - recvfrom(fd, buf, 1, 0, (struct sockaddr *)&sa, &addrlen); + recvfrom(fd, buf, 1, 0, &sa.sa, &addrlen); got_icmp = JNI_TRUE; } @@ -122,7 +122,7 @@ memset(&sa, 0, sa_len); - rv = connect((SOCKET)fd, (struct sockaddr *)&sa, sa_len); + rv = connect((SOCKET)fd, &sa.sa, sa_len); if (rv == SOCKET_ERROR) { handleSocketError(env, WSAGetLastError()); } else { @@ -153,7 +153,7 @@ (char *)buf, len, 0, - (struct sockaddr *)&sa, + &sa.sa, &sa_len); if (n == SOCKET_ERROR) { @@ -182,12 +182,11 @@ */ senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID); if (senderAddr != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa, - senderAddr)) { + if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) { senderAddr = NULL; } else { jint port = (*env)->GetIntField(env, this, dci_senderPortID); - if (port != NET_GetPortFromSockaddr((struct sockaddr *)&sa)) { + if (port != NET_GetPortFromSockaddr(&sa)) { senderAddr = NULL; } } @@ -195,7 +194,7 @@ if (senderAddr == NULL) { jobject isa = NULL; int port; - jobject ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + jobject ia = NET_SockaddrToInetAddress(env, &sa, &port); if (ia != NULL) { isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port); } @@ -204,7 +203,7 @@ // update cachedSenderInetAddress/cachedSenderPort (*env)->SetObjectField(env, this, dci_senderAddrID, ia); (*env)->SetIntField(env, this, dci_senderPortID, - NET_GetPortFromSockaddr((struct sockaddr *)&sa)); + NET_GetPortFromSockaddr(&sa)); (*env)->SetObjectField(env, this, dci_senderID, isa); } return n; @@ -219,21 +218,15 @@ jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKETADDRESS sa; - int sa_len; + int sa_len = 0; jint rv = 0; - if (NET_InetAddressToSockaddr(env, destAddress, destPort, - (struct sockaddr *)&sa, - &sa_len, preferIPv6) != 0) { + if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa, + &sa_len, preferIPv6) != 0) { return IOS_THROWN; } - rv = sendto((SOCKET)fd, - buf, - len, - 0, - (struct sockaddr *)&sa, - sa_len); + rv = sendto((SOCKET)fd, buf, len, 0, &sa.sa, sa_len); if (rv == SOCKET_ERROR) { int theErr = (jint)WSAGetLastError(); if (theErr == WSAEWOULDBLOCK) {
--- a/src/java.base/windows/native/libnio/ch/Net.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnio/ch/Net.c Tue Jan 24 00:30:25 2017 +0100 @@ -168,13 +168,13 @@ { SOCKETADDRESS sa; int rv; - int sa_len; + int sa_len = 0; - if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { - return; + if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) { + return; } - rv = NET_WinBind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len, isExclBind); + rv = NET_WinBind(fdval(env, fdo), &sa, sa_len, isExclBind); if (rv == SOCKET_ERROR) NET_ThrowNew(env, WSAGetLastError(), "bind"); } @@ -194,14 +194,14 @@ { SOCKETADDRESS sa; int rv; - int sa_len; + int sa_len = 0; SOCKET s = (SOCKET)fdval(env, fdo); - if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { + if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) { return IOS_THROWN; } - rv = connect(s, (struct sockaddr *)&sa, sa_len); + rv = connect(s, &sa.sa, sa_len); if (rv != 0) { int err = WSAGetLastError(); if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) { @@ -226,7 +226,7 @@ SOCKETADDRESS sa; int sa_len = sizeof(sa); - if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { + if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) { int error = WSAGetLastError(); if (error == WSAEINVAL) { return 0; @@ -234,7 +234,7 @@ NET_ThrowNew(env, error, "getsockname"); return IOS_THROWN; } - return NET_GetPortFromSockaddr((struct sockaddr *)&sa); + return NET_GetPortFromSockaddr(&sa); } JNIEXPORT jobject JNICALL @@ -244,11 +244,11 @@ int sa_len = sizeof(sa); int port; - if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { + if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) { NET_ThrowNew(env, WSAGetLastError(), "getsockname"); return NULL; } - return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + return NET_SockaddrToInetAddress(env, &sa, &port); } JNIEXPORT jint JNICALL @@ -257,7 +257,7 @@ SOCKETADDRESS sa; int sa_len = sizeof(sa); - if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { + if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) { int error = WSAGetLastError(); if (error == WSAEINVAL) { return 0; @@ -265,7 +265,7 @@ NET_ThrowNew(env, error, "getsockname"); return IOS_THROWN; } - return NET_GetPortFromSockaddr((struct sockaddr *)&sa); + return NET_GetPortFromSockaddr(&sa); } JNIEXPORT jobject JNICALL @@ -275,11 +275,11 @@ int sa_len = sizeof(sa); int port; - if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) { + if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) { NET_ThrowNew(env, WSAGetLastError(), "getsockname"); return NULL; } - return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + return NET_SockaddrToInetAddress(env, &sa, &port); } JNIEXPORT jint JNICALL
--- a/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -95,7 +95,7 @@ int addrlen = sizeof(sa); memset((char *)&sa, 0, sizeof(sa)); - newfd = (jint)accept(ssfd, (struct sockaddr *)&sa, &addrlen); + newfd = (jint)accept(ssfd, &sa.sa, &addrlen); if (newfd == INVALID_SOCKET) { int theErr = (jint)WSAGetLastError(); if (theErr == WSAEWOULDBLOCK) { @@ -107,7 +107,7 @@ SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0); (*env)->SetIntField(env, newfdo, fd_fdID, newfd); - remote_ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, (int *)&remote_port); + remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port); CHECK_NULL_RETURN(remote_ia, IOS_THROWN); isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
--- a/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -88,26 +88,21 @@ Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_connect0(JNIEnv* env, jclass this, jlong socket, jboolean preferIPv6, jobject iao, jint port, jlong ov) { - SOCKET s = (SOCKET) jlong_to_ptr(socket); - OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov); + SOCKET s = (SOCKET)jlong_to_ptr(socket); + OVERLAPPED *lpOverlapped = (OVERLAPPED *)jlong_to_ptr(ov); SOCKETADDRESS sa; - int sa_len; + int sa_len = 0; BOOL res; - if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { + if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, + preferIPv6) != 0) { return IOS_THROWN; } ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED)); - res = (*ConnectEx_func)(s, - (struct sockaddr *)&sa, - sa_len, - NULL, - 0, - NULL, - lpOverlapped); + res = (*ConnectEx_func)(s, &sa.sa, sa_len, NULL, 0, NULL, lpOverlapped); if (res == 0) { int error = GetLastError(); if (error == ERROR_IO_PENDING) {
--- a/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -32,6 +32,7 @@ #define FD_SETSIZE 1024 +#include <limits.h> #include <stdlib.h> #include <winsock2.h> @@ -74,9 +75,19 @@ } else if (timeout < 0) { tv = NULL; } else { + jlong sec = timeout / 1000; tv = &timevalue; - tv->tv_sec = (long)(timeout / 1000); - tv->tv_usec = (long)((timeout % 1000) * 1000); + // + // struct timeval members are signed 32-bit integers so the + // signed 64-bit jlong needs to be clamped + // + if (sec > INT_MAX) { + tv->tv_sec = INT_MAX; + tv->tv_usec = 0; + } else { + tv->tv_sec = (long)sec; + tv->tv_usec = (long)((timeout % 1000) * 1000); + } } /* Set FD_SET structures required for select */
--- a/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Tue Jan 24 00:30:25 2017 +0100 @@ -123,7 +123,7 @@ } // grab the pointer to the CMenuBar, and retain it in native - nativeSetDefaultMenuBar(((CMenuBar)peer).getModel()); + ((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar); } void setAboutMenuItemVisible(final boolean present) {
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -26,29 +26,28 @@ package sun.lwawt.macosx; import java.awt.CheckboxMenuItem; -import java.awt.EventQueue; import java.awt.event.ItemEvent; import java.awt.peer.CheckboxMenuItemPeer; import sun.awt.SunToolkit; public class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer { - boolean fAutoToggle = true; - boolean fIsIndeterminate = false; + volatile boolean fAutoToggle = true; + volatile boolean fIsIndeterminate = false; private native void nativeSetState(long modelPtr, boolean state); private native void nativeSetIsCheckbox(long modelPtr); - CCheckboxMenuItem(CheckboxMenuItem target) { + CCheckboxMenuItem(final CheckboxMenuItem target) { super(target); - nativeSetIsCheckbox(getModel()); + execute(this::nativeSetIsCheckbox); setState(target.getState()); } // MenuItemPeer implementation @Override - public void setState(boolean state) { - nativeSetState(getModel(), state); + public void setState(final boolean state) { + execute(ptr -> nativeSetState(ptr, state)); } public void handleAction(final boolean state) {
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java Tue Jan 24 00:30:25 2017 +0100 @@ -23,7 +23,6 @@ * questions. */ - package sun.lwawt.macosx; /** @@ -34,6 +33,7 @@ private static native void nativeCFRelease(final long ptr, final boolean disposeOnAppKitThread); private final boolean disposeOnAppKitThread; + // TODO this pointer should be private and accessed via CFNativeAction class protected volatile long ptr; /** @@ -70,8 +70,72 @@ nativeCFRelease(oldPtr, disposeOnAppKitThread); // perform outside of the synchronized block } + /** + * The interface which allows to execute some native operations with + * assumption that the native pointer will be valid till the end. + */ + public interface CFNativeAction { + + /** + * The native operation should be called from this method. + * + * @param ptr the pointer to the native data + */ + void run(long ptr); + } + + /** + * The interface which allows to execute some native operations and get a + * result with assumption that the native pointer will be valid till the + * end. + */ + interface CFNativeActionGet { + + /** + * The native operation should be called from this method. + * + * @param ptr the pointer to the native data + * @return result of the native operation + */ + long run(long ptr); + } + + /** + * This is utility method which should be used instead of the direct access + * to the {@link #ptr}, because this method guaranteed that the pointer will + * not be zero and will be valid till the end of the operation.It is highly + * recomended to not use any external lock in action. If the current + * {@link #ptr} is {@code 0} then action will be ignored. + * + * @param action The native operation + */ + public final synchronized void execute(final CFNativeAction action) { + if (ptr != 0) { + action.run(ptr); + } + } + + /** + * This is utility method which should be used instead of the direct access + * to the {@link #ptr}, because this method guaranteed that the pointer will + * not be zero and will be valid till the end of the operation. It is highly + * recomended to not use any external lock in action. If the current + * {@link #ptr} is {@code 0} then action will be ignored and {@code} is + * returned. + * + * @param action the native operation + * @return result of the native operation, usually the native pointer to + * some other data + */ + final synchronized long executeGet(final CFNativeActionGet action) { + if (ptr != 0) { + return action.run(ptr); + } + return 0; + } + @Override - protected void finalize() throws Throwable { + protected final void finalize() throws Throwable { dispose(); } }
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,7 +25,9 @@ package sun.lwawt.macosx; -import java.awt.*; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; import java.awt.peer.MenuItemPeer; import java.awt.peer.MenuPeer; @@ -37,7 +39,7 @@ // This way we avoiding invocation of the setters twice @Override - protected void initialize(MenuItem target) { + protected final void initialize(MenuItem target) { setLabel(target.getLabel()); setEnabled(target.isEnabled()); } @@ -57,52 +59,50 @@ } @Override - protected long createModel() { + long createModel() { CMenuComponent parent = (CMenuComponent) LWCToolkit.targetToPeer(getTarget().getParent()); - if (parent instanceof CMenu || - parent instanceof CPopupMenu) - { - return nativeCreateSubMenu(parent.getModel()); - } else if (parent instanceof CMenuBar) { + if (parent instanceof CMenu) { + return parent.executeGet(this::nativeCreateSubMenu); + } + if (parent instanceof CMenuBar) { MenuBar parentContainer = (MenuBar)getTarget().getParent(); boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget(); int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex(); - return nativeCreateMenu(parent.getModel(), - isHelpMenu, insertionLocation); - } else { - throw new InternalError("Parent must be CMenu or CMenuBar"); + return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu, + insertionLocation)); } + throw new InternalError("Parent must be CMenu or CMenuBar"); } @Override - public void addItem(MenuItem item) { + public final void addItem(MenuItem item) { // Nothing to do here -- we added it when we created the // menu item's peer. } @Override - public void delItem(int index) { - nativeDeleteItem(getModel(), index); + public final void delItem(final int index) { + execute(ptr -> nativeDeleteItem(ptr, index)); } @Override - public void setLabel(String label) { - nativeSetMenuTitle(getModel(), label); + public final void setLabel(final String label) { + execute(ptr->nativeSetMenuTitle(ptr, label)); super.setLabel(label); } // Note that addSeparator is never called directly from java.awt.Menu, // though it is required in the MenuPeer interface. @Override - public void addSeparator() { - nativeAddSeparator(getModel()); + public final void addSeparator() { + execute(this::nativeAddSeparator); } // Used by ScreenMenuBar to get to the native menu for event handling. - public long getNativeMenu() { - return nativeGetNSMenu(getModel()); + public final long getNativeMenu() { + return executeGet(this::nativeGetNSMenu); } private native long nativeCreateMenu(long parentMenuPtr,
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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,7 @@ import sun.awt.AWTAccessor; -public class CMenuBar extends CMenuComponent implements MenuBarPeer { +public final class CMenuBar extends CMenuComponent implements MenuBarPeer { private int nextInsertionIndex = -1; @@ -40,14 +40,15 @@ } @Override - protected long createModel() { + long createModel() { return nativeCreateMenuBar(); } @Override - public void addHelpMenu(Menu m) { - CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m); - nativeSetHelpMenu(getModel(), cMenu.getModel()); + public void addHelpMenu(final Menu m) { + final CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m); + execute(parentPtr -> cMenu.execute( + menuPtr -> nativeSetHelpMenu(parentPtr, menuPtr))); } public int getNextInsertionIndex() { @@ -65,8 +66,8 @@ } @Override - public void delMenu(int index) { - nativeDelMenu(getModel(), index); + public void delMenu(final int index) { + execute(ptr -> nativeDelMenu(ptr, index)); } private native long nativeCreateMenuBar();
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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,36 +29,32 @@ import java.awt.MenuComponent; import java.awt.peer.MenuComponentPeer; -public abstract class CMenuComponent implements MenuComponentPeer { +abstract class CMenuComponent extends CFRetainedResource + implements MenuComponentPeer { - private MenuComponent target; - private long modelPtr; + private final MenuComponent target; - CMenuComponent(MenuComponent target) { + CMenuComponent(final MenuComponent target) { + super(0, true); this.target = target; - this.modelPtr = createModel(); + setPtr(createModel()); } - MenuComponent getTarget() { + final MenuComponent getTarget() { return target; } - public long getModel() { - return modelPtr; + abstract long createModel(); + + @Override + public final void dispose() { + super.dispose(); + LWCToolkit.targetDisposedPeer(target, this); } - protected abstract long createModel(); - - public void dispose() { - LWCToolkit.targetDisposedPeer(target, this); - nativeDispose(modelPtr); - target = null; - } - - private native void nativeDispose(long modelPtr); - // 1.5 peer method - public void setFont(Font f) { + @Override + public final void setFont(final Font f) { // no-op, as we don't currently support menu fonts // c.f. radar 4032912 }
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,16 +25,17 @@ package sun.lwawt.macosx; +import java.awt.MenuItem; +import java.awt.MenuShortcut; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.peer.MenuItemPeer; +import java.util.concurrent.atomic.AtomicBoolean; + import sun.awt.SunToolkit; import sun.lwawt.LWToolkit; -import java.awt.MenuContainer; -import java.awt.MenuItem; -import java.awt.MenuShortcut; -import java.awt.event.*; -import java.awt.peer.MenuItemPeer; -import java.util.concurrent.atomic.AtomicBoolean; - public class CMenuItem extends CMenuComponent implements MenuItemPeer { private final AtomicBoolean enabled = new AtomicBoolean(true); @@ -58,9 +59,9 @@ } @Override - protected long createModel() { + long createModel() { CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent()); - return nativeCreate(parent.getModel(), isSeparator()); + return parent.executeGet(ptr->nativeCreate(ptr, isSeparator())); } public void setLabel(String label, char keyChar, int keyCode, int modifiers) { @@ -90,7 +91,12 @@ keyChar = 0; } - nativeSetLabel(getModel(), label, keyChar, keyCode, keyMask); + final String finalLabel = label; + final char finalKeyChar = keyChar; + final int finalKeyCode = keyCode; + final int finalKeyMask = keyMask; + execute(ptr -> nativeSetLabel(ptr, finalLabel, finalKeyChar, + finalKeyCode, finalKeyMask)); } @Override @@ -105,16 +111,16 @@ * There isn't a need to expose this except in a instanceof because * it isn't defined in the peer api. */ - public void setImage(java.awt.Image img) { + public final void setImage(final java.awt.Image img) { CImage cimg = CImage.getCreator().createFromImage(img); - nativeSetImage(getModel(), cimg == null ? 0L : cimg.ptr); + execute(ptr -> nativeSetImage(ptr, cimg == null ? 0L : cimg.ptr)); } /** * New API for tooltips */ - public void setToolTipText(String text) { - nativeSetTooltip(getModel(), text); + public final void setToolTipText(final String text) { + execute(ptr -> nativeSetTooltip(ptr, text)); } // @Override @@ -138,7 +144,8 @@ b &= ((CMenuItem) parent).isEnabled(); } if (enabled.compareAndSet(!b, b)) { - nativeSetEnabled(getModel(), b); + final boolean finalB = b; + execute(ptr->nativeSetEnabled(ptr, finalB)); } }
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Tue Jan 24 00:30:25 2017 +0100 @@ -231,6 +231,7 @@ private boolean isFullScreenAnimationOn; private volatile boolean isInFullScreen; + private volatile boolean isIconifyAnimationActive; private Window target; private LWWindowPeer peer; @@ -448,7 +449,7 @@ final long nsWindowPtr = getNSWindowPtr(); CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb); if (mbPeer != null) { - nativeSetNSWindowMenuBar(nsWindowPtr, mbPeer.getModel()); + mbPeer.execute(ptr -> nativeSetNSWindowMenuBar(nsWindowPtr, ptr)); } else { nativeSetNSWindowMenuBar(nsWindowPtr, 0); } @@ -997,6 +998,9 @@ if (peer != null) { peer.notifyIconify(iconify); } + if (iconify) { + isIconifyAnimationActive = false; + } } private void deliverZoom(final boolean isZoomed) { @@ -1071,6 +1075,17 @@ return true; } + private boolean isIconified() { + boolean isIconified = false; + if (target instanceof Frame) { + int state = ((Frame)target).getExtendedState(); + if ((state & Frame.ICONIFIED) != 0) { + isIconified = true; + } + } + return isIconifyAnimationActive || isIconified; + } + private boolean isOneOfOwnersOrSelf(CPlatformWindow window) { while (window != null) { if (this == window) { @@ -1094,11 +1109,14 @@ // the windows are ordered above their nearest owner; ancestors of the window, // which is going to become 'main window', are placed above their siblings. CPlatformWindow rootOwner = getRootOwner(); - if (rootOwner.isVisible()) { + if (rootOwner.isVisible() && !rootOwner.isIconified()) { CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr()); } - final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); - orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target)); + // Do not order child windows of iconified owner. + if (!rootOwner.isIconified()) { + final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); + orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target)); + } } private void orderAboveSiblingsImpl(Window[] windows) { @@ -1109,10 +1127,12 @@ // Go through the list of windows and perform ordering. for (Window w : windows) { + boolean iconified = false; final Object p = componentAccessor.getPeer(w); if (p instanceof LWWindowPeer) { CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow(); - if (pw != null && pw.isVisible()) { + iconified = isIconified(); + if (pw != null && pw.isVisible() && !iconified) { // If the window is one of ancestors of 'main window' or is going to become main by itself, // the window should be ordered above its siblings; otherwise the window is just ordered // above its nearest parent. @@ -1125,10 +1145,13 @@ pw.applyWindowLevel(w); } } - // Retrieve the child windows for each window from the list and store them for future use. + // Retrieve the child windows for each window from the list except iconified ones + // and store them for future use. // Note: we collect data about child windows even for invisible owners, since they may have // visible children. - childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w))); + if (!iconified) { + childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w))); + } } // If some windows, which have just been ordered, have any child windows, let's start new iteration // and order these child windows. @@ -1149,6 +1172,10 @@ // NATIVE CALLBACKS // ---------------------------------------------------------------------- + private void windowWillMiniaturize() { + isIconifyAnimationActive = true; + } + private void windowDidBecomeMain() { if (checkBlockingAndOrder()) return; // If it's not blocked, make sure it's above its siblings
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,18 +25,20 @@ package sun.lwawt.macosx; -import java.awt.*; +import java.awt.Component; +import java.awt.Event; +import java.awt.Point; +import java.awt.PopupMenu; import java.awt.peer.PopupMenuPeer; -import sun.lwawt.LWWindowPeer; +final class CPopupMenu extends CMenu implements PopupMenuPeer { -public class CPopupMenu extends CMenu implements PopupMenuPeer { CPopupMenu(PopupMenu target) { super(target); } @Override - protected long createModel() { + long createModel() { return nativeCreatePopupMenu(); } @@ -50,7 +52,7 @@ Point loc = origin.getLocationOnScreen(); e.x += loc.x; e.y += loc.y; - nativeShowPopupMenu(getModel(), e.x, e.y); + execute(ptr -> nativeShowPopupMenu(ptr, e.x, e.y)); } } }
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -118,7 +118,10 @@ } } - return checkAndCreatePopupPeer().getModel(); + // This method is executed on Appkit, so if ptr is not zero means that, + // it is still not deallocated(even if we call NSApp postRunnableEvent) + // and sent CFRelease to the native queue + return checkAndCreatePopupPeer().ptr; } /**
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Tue Jan 24 00:30:25 2017 +0100 @@ -327,10 +327,43 @@ return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]]; } +// Retrieves the list of possible window layers (levels) ++ (NSArray*) getWindowLayers { + static NSArray *windowLayers; + static dispatch_once_t token; + + // Initialize the list of possible window layers + dispatch_once(&token, ^{ + // The layers are ordered from front to back, (i.e. the toppest one is the first) + windowLayers = [NSArray arrayWithObjects: + [NSNumber numberWithInt:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)], + [NSNumber numberWithInt:CGWindowLevelForKey(kCGFloatingWindowLevelKey)], + [NSNumber numberWithInt:CGWindowLevelForKey(kCGNormalWindowLevelKey)], + nil + ]; + [windowLayers retain]; + }); + return windowLayers; +} + // returns id for the topmost window under mouse + (NSInteger) getTopmostWindowUnderMouseID { NSInteger result = -1; + NSArray *windowLayers = [AWTWindow getWindowLayers]; + // Looking for the window under mouse starting from the toppest layer + for (NSNumber *layer in windowLayers) { + result = [AWTWindow getTopmostWindowUnderMouseIDImpl:[layer integerValue]]; + if (result != -1) { + break; + } + } + return result; +} + ++ (NSInteger) getTopmostWindowUnderMouseIDImpl:(NSInteger)windowLayer { + NSInteger result = -1; + NSRect screenRect = [[NSScreen mainScreen] frame]; NSPoint nsMouseLocation = [NSEvent mouseLocation]; CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y); @@ -339,7 +372,7 @@ for (NSDictionary *window in windows) { NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue]; - if (layer == 0) { + if (layer == windowLayer) { CGRect rect; CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect); if (CGRectContainsPoint(rect, cgMouseLocation)) { @@ -639,6 +672,14 @@ AWT_ASSERT_APPKIT_THREAD; self.isMinimizing = YES; + + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env]; + if (platformWindow != NULL) { + static JNF_MEMBER_CACHE(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V"); + JNFCallVoidMethod(env, platformWindow, jm_windowWillMiniaturize); + (*env)->DeleteLocalRef(env, platformWindow); + } // Excplicitly make myself a key window to avoid possible // negative visual effects during iconify operation [self.nsWindow makeKeyAndOrderFront:self.nsWindow];
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -38,7 +38,7 @@ - (id)initWithPeer:(jobject)peer { AWT_ASSERT_APPKIT_THREAD; // Create the new NSMenu - self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]]; + self = [super initWithPeer:peer asSeparator:NO]; if (self) { fMenu = [NSMenu javaMenuWithTitle:@""]; [fMenu retain]; @@ -133,14 +133,13 @@ CMenu * createCMenu (jobject cPeerObjGlobal) { - CMenu *aCMenu = nil; + __block CMenu *aCMenu = nil; - // We use an array here only to be able to get a return value - NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES]; - - aCMenu = (CMenu *)[args objectAtIndex: 0]; + aCMenu = [[CMenu alloc] initWithPeer:cPeerObjGlobal]; + // the aCMenu is released in CMenuComponent.dispose() + }]; if (aCMenu == nil) { return 0L;
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -383,27 +383,20 @@ Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar (JNIEnv *env, jobject peer) { - CMenuBar *aCMenuBar = nil; + __block CMenuBar *aCMenuBar = nil; JNF_COCOA_ENTER(env); jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer); - // We use an array here only to be able to get a return value - NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES]; - - aCMenuBar = (CMenuBar *)[args objectAtIndex: 0]; - + aCMenuBar = [[CMenuBar alloc] initWithPeer:cPeerObjGlobal]; + // the aCMenuBar is released in CMenuComponent.dispose() + }]; if (aCMenuBar == nil) { return 0L; } - // [args release]; - - // A strange memory managment after that. - - JNF_COCOA_EXIT(env); return ptr_to_jlong(aCMenuBar); }
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -41,45 +41,11 @@ return self; } --(void) cleanup { - // Used by subclasses -} - --(void) disposer { +- (void)dealloc { JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; JNFDeleteGlobalRef(env, fPeer); fPeer = NULL; - [self cleanup]; - [self release]; + [super dealloc]; } - -// The method is used by all subclasses, since the process of the creation -// is the same. The only exception is the CMenuItem class. -- (void) _create_OnAppKitThread: (NSMutableArray *)argValue { - jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue]; - CMenuItem *aCMenuItem = [self initWithPeer:cPeerObjGlobal]; - [argValue removeAllObjects]; - [argValue addObject: aCMenuItem]; -} - @end - -/* - * Class: sun_lwawt_macosx_CMenuComponent - * Method: nativeDispose - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_sun_lwawt_macosx_CMenuComponent_nativeDispose -(JNIEnv *env, jobject peer, jlong menuItemObj) -{ -JNF_COCOA_ENTER(env); - - [ThreadUtilities performOnMainThread:@selector(disposer) - on:((id)jlong_to_ptr(menuItemObj)) - withObject:nil - waitUntilDone:NO]; - -JNF_COCOA_EXIT(env); -}
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -32,7 +32,7 @@ } // Setup -- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator; +- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator; - (void) setIsCheckbox; // Events
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -39,11 +39,11 @@ @implementation CMenuItem -- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator{ +- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator{ AWT_ASSERT_APPKIT_THREAD; self = [super initWithPeer:peer]; if (self) { - if ([asSeparator boolValue]) { + if (asSeparator) { fMenuItem = (NSMenuItem*)[NSMenuItem separatorItem]; [fMenuItem retain]; } else { @@ -204,12 +204,9 @@ }]; } -- (void)cleanup { +- (void)dealloc { [fMenuItem setAction:NULL]; [fMenuItem setTarget:nil]; -} - -- (void)dealloc { [fMenuItem release]; fMenuItem = nil; @@ -228,14 +225,6 @@ fIsCheckbox = YES; } -- (void) _createMenuItem_OnAppKitThread: (NSMutableArray *)argValue { - jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue]; - NSNumber * asSeparator = (NSNumber *)[argValue objectAtIndex: 1]; - CMenuItem *aCMenuItem = [self initWithPeer: cPeerObjGlobal asSeparator: asSeparator]; - [argValue removeAllObjects]; - [argValue addObject: aCMenuItem]; -} - - (NSString *)description { return [NSString stringWithFormat:@"CMenuItem[ %@ ]", fMenuItem]; } @@ -397,24 +386,18 @@ (JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator) { - CMenuItem *aCMenuItem = nil; + __block CMenuItem *aCMenuItem = nil; + BOOL asSeparator = (isSeparator == JNI_TRUE) ? YES: NO; CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj); JNF_COCOA_ENTER(env); jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer); - - NSMutableArray *args = nil; - - // Create a new item.... - if (isSeparator == JNI_TRUE) { - args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:YES], nil]; - } else { - args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil]; - } - - [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES]; - - aCMenuItem = (CMenuItem *)[args objectAtIndex: 0]; + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + aCMenuItem = [[CMenuItem alloc] initWithPeer: cPeerObjGlobal + asSeparator: asSeparator]; + // the CMenuItem is released in CMenuComponent.dispose() + }]; if (aCMenuItem == nil) { return 0L;
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Tue Jan 24 00:30:25 2017 +0100 @@ -735,7 +735,11 @@ parse_iCCP_chunk(chunkLength); break; case iTXt_TYPE: - parse_iTXt_chunk(chunkLength); + if (ignoreMetadata) { + stream.skipBytes(chunkLength); + } else { + parse_iTXt_chunk(chunkLength); + } break; case pHYs_TYPE: parse_pHYs_chunk(); @@ -759,7 +763,11 @@ parse_tRNS_chunk(chunkLength); break; case zTXt_TYPE: - parse_zTXt_chunk(chunkLength); + if (ignoreMetadata) { + stream.skipBytes(chunkLength); + } else { + parse_zTXt_chunk(chunkLength); + } break; default: // Read an unknown chunk
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java Tue Jan 24 00:30:25 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -730,18 +730,47 @@ // to use it if the data layout is component type. if (iccProfileField != null && itsRaw.getColorModel() instanceof ComponentColorModel) { - // Create a ColorSpace from the profile. - byte[] iccProfileValue = iccProfileField.getAsBytes(); - ICC_Profile iccProfile - = ICC_Profile.getInstance(iccProfileValue); - ICC_ColorSpace iccColorSpace - = new ICC_ColorSpace(iccProfile); - // Get the raw sample and color information. ColorModel cmRaw = itsRaw.getColorModel(); ColorSpace csRaw = cmRaw.getColorSpace(); SampleModel smRaw = itsRaw.getSampleModel(); + ColorSpace iccColorSpace = null; + try { + // Create a ColorSpace from the profile. + byte[] iccProfileValue = iccProfileField.getAsBytes(); + ICC_Profile iccProfile + = ICC_Profile.getInstance(iccProfileValue); + iccColorSpace = new ICC_ColorSpace(iccProfile); + + // Workaround for JDK-8145241: test a conversion and fall + // back to a standard ColorSpace if it fails. This + // workaround could be removed if JDK-8145241 is fixed. + float[] rgb = + iccColorSpace.toRGB(new float[] {1.0F, 1.0F, 1.0F}); + } catch (Exception iccProfileException) { + processWarningOccurred("Superseding bad ICC profile: " + + iccProfileException.getMessage()); + + if (iccColorSpace != null) { + switch (iccColorSpace.getType()) { + case ColorSpace.TYPE_GRAY: + iccColorSpace = + ColorSpace.getInstance(ColorSpace.CS_GRAY); + break; + case ColorSpace.TYPE_RGB: + iccColorSpace = + ColorSpace.getInstance(ColorSpace.CS_sRGB); + break; + default: + iccColorSpace = csRaw; + break; + } + } else { + iccColorSpace = csRaw; + } + } + // Get the number of samples per pixel and the number // of color components. int numBands = smRaw.getNumBands();
--- a/src/java.desktop/share/classes/java/beans/AppletInitializer.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/java/beans/AppletInitializer.java Tue Jan 24 00:30:25 2017 +0100 @@ -30,21 +30,20 @@ import java.beans.beancontext.BeanContext; /** - * <p> * This interface is designed to work in collusion with java.beans.Beans.instantiate. * The interface is intended to provide mechanism to allow the proper * initialization of JavaBeans that are also Applets, during their * instantiation by java.beans.Beans.instantiate(). - * </p> * * @see java.beans.Beans#instantiate * * @since 1.2 * + * @deprecated The Applet API is deprecated. See the + * <a href="../applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ - - -@SuppressWarnings("deprecation") +@Deprecated(since = "9") public interface AppletInitializer { /** @@ -74,7 +73,6 @@ * @param bCtxt The BeanContext intended for this Applet, or * null. */ - void initialize(Applet newAppletBean, BeanContext bCtxt); /** @@ -86,6 +84,5 @@ * * @param newApplet The newly instantiated JavaBean */ - void activate(Applet newApplet); }
--- a/src/java.desktop/share/classes/java/beans/Beans.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/java/beans/Beans.java Tue Jan 24 00:30:25 2017 +0100 @@ -97,8 +97,10 @@ * @exception IOException if an I/O error occurs. * @since 1.2 */ - - public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException { + @SuppressWarnings("deprecation") + public static Object instantiate(ClassLoader cls, String beanName, + BeanContext beanContext) + throws IOException, ClassNotFoundException { return Beans.instantiate(cls, beanName, beanContext, null); } @@ -153,10 +155,18 @@ * object could not be found. * @exception IOException if an I/O error occurs. * @since 1.2 + * + * @deprecated It is recommended to use + * {@link #instantiate(ClassLoader, String, BeanContext)}, + * because the Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ - @SuppressWarnings("deprecation") - public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext, AppletInitializer initializer) - throws IOException, ClassNotFoundException { + @Deprecated(since = "9") + public static Object instantiate(ClassLoader cls, String beanName, + BeanContext beanContext, + AppletInitializer initializer) + throws IOException, ClassNotFoundException { InputStream ins; ObjectInputStream oins = null; @@ -501,7 +511,7 @@ * Package private support class. This provides a default AppletContext * for beans which are applets. */ -@SuppressWarnings("deprecation") +@Deprecated(since = "9") class BeansAppletContext implements AppletContext { Applet target; Hashtable<URL,Object> imageCache = new Hashtable<>(); @@ -586,7 +596,7 @@ * Package private support class. This provides an AppletStub * for beans which are applets. */ -@SuppressWarnings("deprecation") +@Deprecated(since = "9") class BeansAppletStub implements AppletStub { transient boolean active; transient Applet target;
--- a/src/java.desktop/share/classes/javax/swing/PopupFactory.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/javax/swing/PopupFactory.java Tue Jan 24 00:30:25 2017 +0100 @@ -260,6 +260,7 @@ * Obtains the appropriate <code>Popup</code> based on * <code>popupType</code>. */ + @SuppressWarnings("deprecation") private Popup getPopup(Component owner, Component contents, int ownerX, int ownerY, int popupType) { if (GraphicsEnvironment.isHeadless()) {
--- a/src/java.desktop/share/classes/javax/swing/RepaintManager.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/javax/swing/RepaintManager.java Tue Jan 24 00:30:25 2017 +0100 @@ -525,8 +525,12 @@ * @param h Height of the region to repaint * @see JApplet#repaint * @since 1.6 + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ - @SuppressWarnings("deprecation") + @Deprecated(since = "9") public void addDirtyRegion(Applet applet, int x, int y, int w, int h) { addDirtyRegion0(applet, x, y, w, h); }
--- a/src/java.desktop/share/classes/javax/swing/TablePrintable.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/javax/swing/TablePrintable.java Tue Jan 24 00:30:25 2017 +0100 @@ -380,6 +380,12 @@ // print the current section of the table g2d.translate(-clip.x, -clip.y); g2d.clip(clip); + + // set a property so that BasicTableUI#paint can know JTable printMode + // is FIT_WIDTH since TablePrintable.printMode is not accessible from BasicTableUI + if (printMode == JTable.PrintMode.FIT_WIDTH) { + table.putClientProperty("Table.printMode", JTable.PrintMode.FIT_WIDTH); + } table.print(g2d); // restore the original transform and clip @@ -407,8 +413,18 @@ for(int visrow = rMin; visrow < rMax; visrow++) { rowHeight += table.getRowHeight(visrow); } - g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight); + // If PrintMode is FIT_WIDTH, then draw rect for entire column width while + // printing irrespective of how many columns are visible in console + if (printMode == JTable.PrintMode.FIT_WIDTH) { + g2d.drawRect(0, 0, clip.width, hclip.height + rowHeight); + } else { + g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight); + } + // clear the property + if (printMode == JTable.PrintMode.FIT_WIDTH) { + table.putClientProperty("Table.printMode", null); + } // dispose the graphics copy g2d.dispose(); @@ -534,5 +550,4 @@ } while (clip.width + colWidth <= pw); } - }
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java Tue Jan 24 00:30:25 2017 +0100 @@ -1812,12 +1812,12 @@ } boolean ltr = table.getComponentOrientation().isLeftToRight(); - + Point upperLeft, lowerRight; // compute the visible part of table which needs to be painted Rectangle visibleBounds = clip.intersection(bounds); - Point upperLeft = visibleBounds.getLocation(); - Point lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1, - visibleBounds.y + visibleBounds.height - 1); + upperLeft = visibleBounds.getLocation(); + lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1, + visibleBounds.y + visibleBounds.height - 1); int rMin = table.rowAtPoint(upperLeft); int rMax = table.rowAtPoint(lowerRight); @@ -1834,6 +1834,18 @@ rMax = table.getRowCount()-1; } + // For FIT_WIDTH, all columns should be printed irrespective of + // how many columns are visible. So, we used clip which is already set to + // total col width instead of visible region + // Since JTable.PrintMode is not accessible + // from here, we aet "Table.printMode" in TablePrintable#print and + // access from here. + Object printMode = table.getClientProperty("Table.printMode"); + if ((printMode == JTable.PrintMode.FIT_WIDTH)) { + upperLeft = clip.getLocation(); + lowerRight = new Point(clip.x + clip.width - 1, + clip.y + clip.height - 1); + } int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight); int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft); // This should never happen. @@ -2018,7 +2030,7 @@ int y = damagedArea.y; for (int row = rMin; row <= rMax; row++) { y += table.getRowHeight(row); - g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1); + SwingUtilities2.drawHLine(g, damagedArea.x, tableWidth - 1, y - 1); } } if (table.getShowVerticalLines()) { @@ -2030,14 +2042,14 @@ for (int column = cMin; column <= cMax; column++) { int w = cm.getColumn(column).getWidth(); x += w; - g.drawLine(x - 1, 0, x - 1, tableHeight - 1); + SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1); } } else { x = damagedArea.x; for (int column = cMax; column >= cMin; column--) { int w = cm.getColumn(column).getWidth(); x += w; - g.drawLine(x - 1, 0, x - 1, tableHeight - 1); + SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1); } } }
--- a/src/java.desktop/share/classes/javax/swing/text/PasswordView.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/javax/swing/text/PasswordView.java Tue Jan 24 00:30:25 2017 +0100 @@ -27,10 +27,7 @@ import sun.swing.SwingUtilities2; import java.awt.*; import java.awt.font.FontRenderContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import javax.swing.JPasswordField; -import static javax.swing.text.PlainView.isFPMethodOverriden; /** * Implements a View suitable for use in JPasswordField @@ -332,22 +329,6 @@ static char[] ONE = new char[1]; - private final boolean drawEchoCharacterOverridden; - - { - final Class<?> CLS = getClass(); - final Class<?> INT = Integer.TYPE; - final Class<?> FP = Float.TYPE; - final Class<?> CHAR = Character.TYPE; - - drawEchoCharacterOverridden = AccessController - .doPrivileged(new PrivilegedAction<Boolean>() { - @Override - public Boolean run() { - Class<?>[] intTypes = {Graphics.class, INT, INT, CHAR}; - Class<?>[] fpTypes = {Graphics2D.class, FP, FP, CHAR}; - return isFPMethodOverriden("drawEchoCharacter", CLS, intTypes, fpTypes); - } - }); - } + private final boolean drawEchoCharacterOverridden = + getFPMethodOverridden(getClass(), "drawEchoCharacter", FPMethodArgs.GNNC); }
--- a/src/java.desktop/share/classes/javax/swing/text/PlainView.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/javax/swing/text/PlainView.java Tue Jan 24 00:30:25 2017 +0100 @@ -32,6 +32,8 @@ import java.util.Objects; import javax.swing.event.*; import java.lang.reflect.Module; +import java.lang.ref.SoftReference; +import java.util.HashMap; /** * Implements View interface for a simple multi-line text view @@ -818,10 +820,45 @@ return w; } - static boolean isFPMethodOverriden(String method, - Class<?> cls, - Class<?>[] intTypes, - Class<?>[] fpTypes) + static boolean getFPMethodOverridden(Class<?> cls, String method, + FPMethodArgs methodArgs) { + HashMap<FPMethodItem, Boolean> map = null; + boolean initialized = methodsOverriddenMapRef != null + && (map = methodsOverriddenMapRef.get()) != null; + + if (!initialized) { + map = new HashMap<>(); + methodsOverriddenMapRef = new SoftReference<>(map); + } + + FPMethodItem key = new FPMethodItem(cls, method); + Boolean isFPMethodOverridden = map.get(key); + if (isFPMethodOverridden == null) { + isFPMethodOverridden = checkFPMethodOverridden(cls, method, methodArgs); + map.put(key, isFPMethodOverridden); + } + return isFPMethodOverridden; + } + + private static boolean checkFPMethodOverridden(final Class<?> className, + final String methodName, + final FPMethodArgs methodArgs) { + + return AccessController + .doPrivileged(new PrivilegedAction<Boolean>() { + @Override + public Boolean run() { + return isFPMethodOverridden(methodName, className, + methodArgs.getMethodArguments(false), + methodArgs.getMethodArguments(true)); + } + }); + } + + private static boolean isFPMethodOverridden(String method, + Class<?> cls, + Class<?>[] intTypes, + Class<?>[] fpTypes) { Module thisModule = PlainView.class.getModule(); while (!thisModule.equals(cls.getModule())) { @@ -840,6 +877,57 @@ return true; } + enum FPMethodArgs { + + IGNN, + IIGNN, + GNNII, + GNNC; + + public Class<?>[] getMethodArguments(boolean isFPType) { + Class<?> N = (isFPType) ? Float.TYPE : Integer.TYPE; + Class<?> G = (isFPType) ? Graphics2D.class : Graphics.class; + switch (this) { + case IGNN: + return new Class<?>[]{Integer.TYPE, G, N, N}; + case IIGNN: + return new Class<?>[]{Integer.TYPE, Integer.TYPE, G, N, N}; + case GNNII: + return new Class<?>[]{G, N, N, Integer.TYPE, Integer.TYPE}; + case GNNC: + return new Class<?>[]{G, N, N, Character.TYPE}; + default: + throw new RuntimeException("Unknown method arguments!"); + } + } + } + + private static class FPMethodItem { + + final Class<?> className; + final String methodName; + + public FPMethodItem(Class<?> className, String methodName) { + this.className = className; + this.methodName = methodName; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof FPMethodItem) { + FPMethodItem that = (FPMethodItem) obj; + return this.className.equals(that.className) + && this.methodName.equals(that.methodName); + } + return false; + } + + @Override + public int hashCode() { + return 31 * methodName.hashCode() + className.hashCode(); + } + } + // --- member variables ----------------------------------------------- /** @@ -878,46 +966,13 @@ */ int firstLineOffset; - final boolean drawLineOverridden; - final boolean drawSelectedTextOverridden; - final boolean drawUnselectedTextOverridden; - final boolean useFloatingPointAPI; - - { - final Class<?> CLS = getClass(); - final Class<?> INT = Integer.TYPE; - final Class<?> FP = Float.TYPE; - - drawLineOverridden = AccessController - .doPrivileged(new PrivilegedAction<Boolean>() { - @Override - public Boolean run() { - Class<?>[] intTypes = {INT, Graphics.class, INT, INT}; - Class<?>[] fpTypes = {INT, Graphics2D.class, FP, FP}; - return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes); - } - }); - - drawUnselectedTextOverridden = AccessController - .doPrivileged(new PrivilegedAction<Boolean>() { - @Override - public Boolean run() { - Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT}; - Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT}; - return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes); - } - }); - - drawSelectedTextOverridden = AccessController - .doPrivileged(new PrivilegedAction<Boolean>() { - @Override - public Boolean run() { - Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT}; - Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT}; - return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes); - } - }); - - useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden; - } + private static SoftReference<HashMap<FPMethodItem, Boolean>> methodsOverriddenMapRef; + final boolean drawLineOverridden = + getFPMethodOverridden(getClass(), "drawLine", FPMethodArgs.IGNN); + final boolean drawSelectedTextOverridden = + getFPMethodOverridden(getClass(), "drawSelectedText", FPMethodArgs.GNNII); + final boolean drawUnselectedTextOverridden = + getFPMethodOverridden(getClass(), "drawUnselectedText", FPMethodArgs.GNNII); + final boolean useFloatingPointAPI = + drawUnselectedTextOverridden || drawSelectedTextOverridden; }
--- a/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java Tue Jan 24 00:30:25 2017 +0100 @@ -28,10 +28,9 @@ import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.lang.ref.SoftReference; -import java.security.AccessController; -import java.security.PrivilegedAction; import javax.swing.event.*; -import static javax.swing.text.PlainView.isFPMethodOverriden; +import static javax.swing.text.PlainView.FPMethodArgs.*; +import static javax.swing.text.PlainView.getFPMethodOverridden; /** * View of plain text (text with only one font and color) @@ -989,46 +988,12 @@ SoftReference<int[]> lineCache = null; } - private final boolean drawLineOverridden; - private final boolean drawSelectedTextOverridden; - private final boolean drawUnselectedTextOverridden; - private final boolean useFloatingPointAPI; - - { - final Class<?> CLS = getClass(); - final Class<?> INT = Integer.TYPE; - final Class<?> FP = Float.TYPE; - - drawLineOverridden = AccessController - .doPrivileged(new PrivilegedAction<Boolean>() { - @Override - public Boolean run() { - Class<?>[] intTypes = {INT, INT, Graphics.class, INT, INT}; - Class<?>[] fpTypes = {INT, INT, Graphics2D.class, FP, FP}; - return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes); - } - }); - - drawUnselectedTextOverridden = AccessController - .doPrivileged(new PrivilegedAction<Boolean>() { - @Override - public Boolean run() { - Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT}; - Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT}; - return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes); - } - }); - - drawSelectedTextOverridden = AccessController - .doPrivileged(new PrivilegedAction<Boolean>() { - @Override - public Boolean run() { - Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT}; - Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT}; - return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes); - } - }); - - useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden; - } + private final boolean drawLineOverridden = + getFPMethodOverridden(getClass(), "drawLine", IIGNN); + private final boolean drawSelectedTextOverridden = + getFPMethodOverridden(getClass(), "drawSelectedText", GNNII); + private final boolean drawUnselectedTextOverridden = + getFPMethodOverridden(getClass(), "drawUnselectedText", GNNII); + private final boolean useFloatingPointAPI = + drawUnselectedTextOverridden || drawSelectedTextOverridden; }
--- a/src/java.desktop/share/classes/sun/applet/AppletEvent.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletEvent.java Tue Jan 24 00:30:25 2017 +0100 @@ -32,8 +32,13 @@ * AppletEvent class. * * @author Sunita Mani + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ @SuppressWarnings("serial") // JDK-implementation class +@Deprecated(since = "9") public class AppletEvent extends EventObject { private Object arg;
--- a/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java Tue Jan 24 00:30:25 2017 +0100 @@ -36,7 +36,12 @@ * responsible for dispatching events to them. * * @author Sunita Mani + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ +@Deprecated(since = "9") public class AppletEventMulticaster implements AppletListener { private final AppletListener a, b;
--- a/src/java.desktop/share/classes/sun/applet/AppletIOException.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletIOException.java Tue Jan 24 00:30:25 2017 +0100 @@ -31,10 +31,14 @@ * An applet IO exception. * * @author Koji Uno + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ @SuppressWarnings("serial") // JDK implementation class -public -class AppletIOException extends IOException { +@Deprecated(since = "9") +public class AppletIOException extends IOException { private String key = null; private Object msgobj = null;
--- a/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java Tue Jan 24 00:30:25 2017 +0100 @@ -29,10 +29,14 @@ * An applet security exception. * * @author Arthur van Hoff + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ @SuppressWarnings("serial") // JDK implementation class -public -class AppletIllegalArgumentException extends IllegalArgumentException { +@Deprecated(since = "9") +public class AppletIllegalArgumentException extends IllegalArgumentException { private String key = null; public AppletIllegalArgumentException(String key) {
--- a/src/java.desktop/share/classes/sun/applet/AppletImageRef.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletImageRef.java Tue Jan 24 00:30:25 2017 +0100 @@ -31,6 +31,7 @@ import sun.awt.image.URLImageSource; import java.net.URL; +@Deprecated(since = "9") class AppletImageRef { private SoftReference<Image> soft = null;
--- a/src/java.desktop/share/classes/sun/applet/AppletListener.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletListener.java Tue Jan 24 00:30:25 2017 +0100 @@ -32,8 +32,12 @@ * by objects interested in AppletEvents. * * @author Sunita Mani + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ - +@Deprecated(since = "9") public interface AppletListener extends EventListener { public void appletStateChanged(AppletEvent e); }
--- a/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java Tue Jan 24 00:30:25 2017 +0100 @@ -34,8 +34,12 @@ /** * This subclass of ObjectInputStream delegates loading of classes to * an existing ClassLoader. + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ - +@Deprecated(since = "9") class AppletObjectInputStream extends ObjectInputStream { private AppletClassLoader loader;
--- a/src/java.desktop/share/classes/sun/applet/AppletPanel.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletPanel.java Tue Jan 24 00:30:25 2017 +0100 @@ -52,9 +52,14 @@ * thread group to call the applet's init(), start(), stop(), and * destroy() methods. * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. + * * @author Arthur van Hoff */ -@SuppressWarnings({"serial", "deprecation"}) // JDK implementation class +@SuppressWarnings({"serial"}) // JDK implementation class +@Deprecated(since = "9") public abstract class AppletPanel extends Panel implements AppletStub, Runnable {
--- a/src/java.desktop/share/classes/sun/applet/AppletProps.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletProps.java Tue Jan 24 00:30:25 2017 +0100 @@ -36,6 +36,7 @@ import sun.security.action.*; @SuppressWarnings("serial") // JDK implementation class +@Deprecated(since = "9") class AppletProps extends Frame { TextField proxyHost; @@ -197,6 +198,7 @@ /* 4066432 */ /* Dialog class to display property-related errors to user */ @SuppressWarnings("serial") // JDK implementation class +@Deprecated(since = "9") class AppletPropsErrorDialog extends Dialog { @SuppressWarnings("deprecation") public AppletPropsErrorDialog(Frame parent, String title, String message,
--- a/src/java.desktop/share/classes/sun/applet/AppletViewer.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletViewer.java Tue Jan 24 00:30:25 2017 +0100 @@ -43,6 +43,7 @@ * A frame to show the applet tag in. */ @SuppressWarnings("serial") // JDK-implementation class +@Deprecated(since = "9") final class TextFrame extends Frame { /** @@ -91,6 +92,7 @@ /** * Lets us construct one using unix-style one shot behaviors. */ +@Deprecated(since = "9") final class StdAppletViewerFactory implements AppletViewerFactory { @Override @@ -116,8 +118,13 @@ * <a href="../../../docs/tooldocs/appletviewertags.html">AppletViewer Tags</a>. * (The document named appletviewertags.html in the JDK's docs/tooldocs directory, * once the JDK docs have been installed.) + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ -@SuppressWarnings({"serial", "deprecation"}) // JDK-implementation class +@SuppressWarnings({"serial"}) // JDK-implementation class +@Deprecated(since = "9") public class AppletViewer extends Frame implements AppletContext, Printable { /** @@ -146,7 +153,7 @@ */ AppletViewerFactory factory; - + @Deprecated(since = "9") private final class UserActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent evt) { @@ -219,6 +226,7 @@ } }; + @Deprecated(since = "9") class AppletEventListener implements AppletListener { final Frame frame;
--- a/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java Tue Jan 24 00:30:25 2017 +0100 @@ -33,8 +33,8 @@ import java.net.URL; import java.awt.MenuBar; -public -interface AppletViewerFactory { +@Deprecated(since = "9") +public interface AppletViewerFactory { public AppletViewer createAppletViewer(int x, int y, URL doc, Hashtable<String, String> atts); public MenuBar getBaseMenuBar();
--- a/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java Tue Jan 24 00:30:25 2017 +0100 @@ -40,7 +40,12 @@ * destroy() methods. * * @author Arthur van Hoff + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ +@Deprecated(since = "9") class AppletViewerPanel extends AppletPanel { /* Are we debugging? */
--- a/src/java.desktop/share/classes/sun/applet/Main.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/applet/Main.java Tue Jan 24 00:30:25 2017 +0100 @@ -39,7 +39,12 @@ /** * The main entry point into AppletViewer. + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ +@Deprecated(since = "9") public class Main { /** * The file which contains all of the AppletViewer specific properties.
--- a/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java Tue Jan 24 00:30:25 2017 +0100 @@ -496,10 +496,14 @@ * Checks if the component is in an EmbeddedFrame. If so, * returns the applet found in the hierarchy or null if * not found. - * @return the parent applet or {@ null} + * @return the parent applet or {@code null} * @since 1.6 + * + * @deprecated The Applet API is deprecated. See the + * <a href="../../java/applet/package-summary.html"> java.applet package + * documentation</a> for further information. */ - @SuppressWarnings("deprecation") + @Deprecated(since = "9") public static Applet getAppletIfAncestorOf(Component comp) { Container parent = comp.getParent(); Applet applet = null;
--- a/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c Wed Jan 25 15:31:01 2017 +0530 +++ b/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c Tue Jan 24 00:30:25 2017 +0100 @@ -2419,7 +2419,7 @@ case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES: if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) && SAFE_TO_ALLOC_2(width, 4) && - SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 4))) + SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 4))) { return -1; } @@ -2428,7 +2428,7 @@ if (offset < 0 || offset >= dataSize || width > rasterP->scanlineStride || - height * rasterP->scanlineStride * 4 > dataSize - offset) + ((width + (height - 1) * rasterP->scanlineStride) * 4) > dataSize - offset) { // raster data buffer is too short return -1; @@ -2446,7 +2446,7 @@