Mercurial > hg > openjdk > lambda > jdk
changeset 10503:364e0871f7a3
Merge
author | jlaskey |
---|---|
date | Sat, 02 Mar 2013 11:06:58 -0400 |
parents | 20a827b22a2e (current diff) f08ad5938709 (diff) |
children | 3565c755c49f |
files | make/launchers/Makefile makefiles/CompileLaunchers.gmk makefiles/CreateJars.gmk src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java test/javax/script/RhinoExceptionTest.java test/tools/launcher/VersionCheck.java |
diffstat | 95 files changed, 3682 insertions(+), 1587 deletions(-) [+] |
line wrap: on
line diff
--- a/make/tools/src/build/tools/deps/refs.allowed Fri Feb 22 23:36:47 2013 -0400 +++ b/make/tools/src/build/tools/deps/refs.allowed Sat Mar 02 11:06:58 2013 -0400 @@ -33,8 +33,3 @@ # java.beans.PropertyChangeListener=java.util.logging.LogManager,sun.org.mozilla.javascript.internal.Context,compact1,compact2,compact3 java.beans.PropertyChangeEvent=sun.org.mozilla.javascript.internal.Context,compact3 - -# JFR traces even in builds with JFR disabled -com.oracle.jrockit.jfr.FlightRecorder: com.sun.management.MissionControl, compact3 -com.oracle.jrockit.jfr.management.FlightRecorderMBean: com.sun.management.MissionControl, compact3 -
--- a/makefiles/CreateJars.gmk Fri Feb 22 23:36:47 2013 -0400 +++ b/makefiles/CreateJars.gmk Sat Mar 02 11:06:58 2013 -0400 @@ -213,28 +213,28 @@ org/relaxng/datatype \ sun/awt/HKSCS.class \ sun/awt/motif/X11GB2312.class \ - sun/awt/motif/X11GB2312\$$$$Decoder.class \ - sun/awt/motif/X11GB2312\$$$$Encoder.class \ + sun/awt/motif/X11GB2312\$$Decoder.class \ + sun/awt/motif/X11GB2312\$$Encoder.class \ sun/awt/motif/X11GBK.class \ - sun/awt/motif/X11GBK\$$$$Encoder.class \ + sun/awt/motif/X11GBK\$$Encoder.class \ sun/awt/motif/X11KSC5601.class \ - sun/awt/motif/X11KSC5601\$$$$Decoder.class \ - sun/awt/motif/X11KSC5601\$$$$Encoder.class \ + sun/awt/motif/X11KSC5601\$$Decoder.class \ + sun/awt/motif/X11KSC5601\$$Encoder.class \ sun/jvmstat \ sun/net/spi/nameservice/dns \ sun/nio/cs/ext \ sun/rmi/rmic \ sun/security/ec/ECDHKeyAgreement.class \ sun/security/ec/ECDSASignature.class \ - sun/security/ec/ECDSASignature\$$$$Raw.class \ - sun/security/ec/ECDSASignature\$$$$SHA1.class \ - sun/security/ec/ECDSASignature\$$$$SHA224.class \ - sun/security/ec/ECDSASignature\$$$$SHA256.class \ - sun/security/ec/ECDSASignature\$$$$SHA384.class \ - sun/security/ec/ECDSASignature\$$$$SHA512.class \ + sun/security/ec/ECDSASignature\$$Raw.class \ + sun/security/ec/ECDSASignature\$$SHA1.class \ + sun/security/ec/ECDSASignature\$$SHA224.class \ + sun/security/ec/ECDSASignature\$$SHA256.class \ + sun/security/ec/ECDSASignature\$$SHA384.class \ + sun/security/ec/ECDSASignature\$$SHA512.class \ sun/security/ec/ECKeyFactory.class \ sun/security/ec/ECKeyPairGenerator.class \ - sun/security/ec/SunEC\$$$$1.class \ + sun/security/ec/SunEC\$$1.class \ sun/security/ec/SunEC.class \ sun/security/ec/SunECEntries.class \ sun/security/internal \
--- a/makefiles/Images.gmk Fri Feb 22 23:36:47 2013 -0400 +++ b/makefiles/Images.gmk Sat Mar 02 11:06:58 2013 -0400 @@ -602,6 +602,7 @@ $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)") $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)") $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)") + if [ -n "$(JDK_ARCH_ABI_PROP_NAME)" ]; then $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"); fi $(call info-file-item, "SOURCE", "$(ALL_SOURCE_TIPS)") endef
--- a/makefiles/profile-rtjar-includes.txt Fri Feb 22 23:36:47 2013 -0400 +++ b/makefiles/profile-rtjar-includes.txt Sat Mar 02 11:06:58 2013 -0400 @@ -349,6 +349,7 @@ com/sun/rowset/providers \ com/sun/script/javascript \ com/sun/script/util \ + com/sun/security/auth \ com/sun/security/auth/callback \ com/sun/security/auth/login \ com/sun/security/auth/module \ @@ -448,8 +449,7 @@ sun/tracing \ sun/tracing/dtrace -PROFILE_3_RTJAR_INCLUDE_TYPES := \ - com/sun/security/auth/*.class +PROFILE_3_RTJAR_INCLUDE_TYPES := PROFILE_3_RTJAR_EXCLUDE_TYPES := \ javax/management/remote/rmi/_RMIConnectionImpl_Tie.class \ @@ -457,10 +457,10 @@ javax/management/remote/rmi/_RMIServerImpl_Tie.class \ javax/management/remote/rmi/_RMIServer_Stub.class \ com/sun/security/auth/callback/DialogCallbackHandler.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$1.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$2.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$Action.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$ConfirmationInfo.class + com/sun/security/auth/callback/DialogCallbackHandler\$$1.class \ + com/sun/security/auth/callback/DialogCallbackHandler\$$2.class \ + com/sun/security/auth/callback/DialogCallbackHandler\$$Action.class \ + com/sun/security/auth/callback/DialogCallbackHandler\$$ConfirmationInfo.class PROFILE_3_INCLUDE_METAINF_SERVICES := \ META-INF/services/javax.script.ScriptEngineFactory
--- a/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, 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 @@ -165,16 +165,18 @@ // partition keyblock into individual secrets int ofs = 0; - byte[] tmp = new byte[macLength]; + if (macLength != 0) { + byte[] tmp = new byte[macLength]; - // mac keys - System.arraycopy(keyBlock, ofs, tmp, 0, macLength); - ofs += macLength; - clientMacKey = new SecretKeySpec(tmp, "Mac"); + // mac keys + System.arraycopy(keyBlock, ofs, tmp, 0, macLength); + ofs += macLength; + clientMacKey = new SecretKeySpec(tmp, "Mac"); - System.arraycopy(keyBlock, ofs, tmp, 0, macLength); - ofs += macLength; - serverMacKey = new SecretKeySpec(tmp, "Mac"); + System.arraycopy(keyBlock, ofs, tmp, 0, macLength); + ofs += macLength; + serverMacKey = new SecretKeySpec(tmp, "Mac"); + } if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites return new TlsKeyMaterialSpec(clientMacKey, serverMacKey); @@ -198,7 +200,7 @@ // IV keys if needed. if (ivLength != 0) { - tmp = new byte[ivLength]; + byte[] tmp = new byte[ivLength]; System.arraycopy(keyBlock, ofs, tmp, 0, ivLength); ofs += ivLength; @@ -220,8 +222,8 @@ // TLS 1.0 byte[] seed = concat(clientRandom, serverRandom); - tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed, - expandedKeyLength, md5, sha); + byte[] tmp = doTLS10PRF(clientKeyBytes, + LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha); clientCipherKey = new SecretKeySpec(tmp, alg); tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed, @@ -239,7 +241,7 @@ } } else { // SSLv3 - tmp = new byte[expandedKeyLength]; + byte[] tmp = new byte[expandedKeyLength]; md5.update(clientKeyBytes); md5.update(clientRandom);
--- a/src/share/classes/java/lang/Deprecated.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/Deprecated.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -36,6 +36,7 @@ * * @author Neal Gafter * @since 1.5 + * @jls 9.6.3.6 @Deprecated */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/src/share/classes/java/lang/Override.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/Override.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ * * @author Peter von der Ahé * @author Joshua Bloch - * @jls 9.6.1.4 Override + * @jls 9.6.1.4 @Override * @since 1.5 */ @Target(ElementType.METHOD)
--- a/src/share/classes/java/lang/SafeVarargs.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/SafeVarargs.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ -85,6 +85,7 @@ * @since 1.7 * @jls 4.7 Reifiable Types * @jls 8.4.1 Formal Parameters + * @jls 9.6.3.7 @SafeVarargs */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/src/share/classes/java/lang/SecurityManager.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/SecurityManager.java Sat Mar 02 11:06:58 2013 -0400 @@ -1320,6 +1320,9 @@ * <code>AWTPermission("showWindowWithoutWarningBanner")</code> permission, * and returns <code>true</code> if a SecurityException is not thrown, * otherwise it returns <code>false</code>. + * In the case of subset Profiles of Java SE that do not include the + * {@code java.awt} package, {@code checkPermission} is instead called + * to check the permission {@code java.security.AllPermission}. * <p> * If you override this method, then you should make a call to * <code>super.checkTopLevelWindow</code> @@ -1340,8 +1343,12 @@ if (window == null) { throw new NullPointerException("window can't be null"); } + Permission perm = SecurityConstants.AWT.TOPLEVEL_WINDOW_PERMISSION; + if (perm == null) { + perm = SecurityConstants.ALL_PERMISSION; + } try { - checkPermission(SecurityConstants.AWT.TOPLEVEL_WINDOW_PERMISSION); + checkPermission(perm); return true; } catch (SecurityException se) { // just return false @@ -1379,6 +1386,9 @@ * This method calls <code>checkPermission</code> with the * <code>AWTPermission("accessClipboard")</code> * permission. + * In the case of subset Profiles of Java SE that do not include the + * {@code java.awt} package, {@code checkPermission} is instead called + * to check the permission {@code java.security.AllPermission}. * <p> * If you override this method, then you should make a call to * <code>super.checkSystemClipboardAccess</code> @@ -1391,7 +1401,11 @@ * @see #checkPermission(java.security.Permission) checkPermission */ public void checkSystemClipboardAccess() { - checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION); + Permission perm = SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION; + if (perm == null) { + perm = SecurityConstants.ALL_PERMISSION; + } + checkPermission(perm); } /** @@ -1400,6 +1414,10 @@ * <p> * This method calls <code>checkPermission</code> with the * <code>AWTPermission("accessEventQueue")</code> permission. + * In the case of subset Profiles of Java SE that do not include the + * {@code java.awt} package, {@code checkPermission} is instead called + * to check the permission {@code java.security.AllPermission}. + * * <p> * If you override this method, then you should make a call to * <code>super.checkAwtEventQueueAccess</code> @@ -1412,7 +1430,11 @@ * @see #checkPermission(java.security.Permission) checkPermission */ public void checkAwtEventQueueAccess() { - checkPermission(SecurityConstants.AWT.CHECK_AWT_EVENTQUEUE_PERMISSION); + Permission perm = SecurityConstants.AWT.CHECK_AWT_EVENTQUEUE_PERMISSION; + if (perm == null) { + perm = SecurityConstants.ALL_PERMISSION; + } + checkPermission(perm); } /*
--- a/src/share/classes/java/lang/SuppressWarnings.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/SuppressWarnings.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, 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,8 +41,13 @@ * suppress a warning in a particular method, you should annotate that * method rather than its class. * + * @author Josh Bloch * @since 1.5 - * @author Josh Bloch + * @jls 4.8 Raw Types + * @jls 4.12.2 Variables of Reference Type + * @jls 5.1.9 Unchecked Conversion + * @jls 5.5.2 Checked Casts and Unchecked Casts + * @jls 9.6.3.5 @SuppressWarnings */ @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) @@ -56,9 +61,11 @@ * free to emit a warning if an annotation contains an unrecognized * warning name. * - * <p>Compiler vendors should document the warning names they support in - * conjunction with this annotation type. They are encouraged to cooperate - * to ensure that the same names work across multiple compilers. + * <p> The string {@code "unchecked"} is used to suppress + * unchecked warnings. Compiler vendors should document the + * additional warning names they support in conjunction with this + * annotation type. They are encouraged to cooperate to ensure + * that the same names work across multiple compilers. */ String[] value(); }
--- a/src/share/classes/java/lang/annotation/Inherited.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/annotation/Inherited.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -44,6 +44,7 @@ * * @author Joshua Bloch * @since 1.5 + * @jls 9.6.3.3 @Inherited */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java Fri Feb 22 23:36:47 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2012, 2013, 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 java.lang.annotation; - -import java.util.Objects; - -/** - * Thrown to indicate that an annotation type expected to act as a - * container for another annotation type by virture of an @Repeatable - * annotation, does not act as a container. - * - * @see java.lang.reflect.AnnotatedElement - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -public class InvalidContainerAnnotationError extends AnnotationFormatError { - private static final long serialVersionUID = 5023L; - - /** - * The instance of the erroneous container. - */ - private transient Annotation container; - - /** - * The type of the annotation that should be contained in the - * container. - */ - private transient Class<? extends Annotation> annotationType; - - /** - * Constructs a new InvalidContainerAnnotationError with the - * specified detail message. - * - * @param message the detail message. - */ - public InvalidContainerAnnotationError(String message) { - super(message); - } - - /** - * Constructs a new InvalidContainerAnnotationError with the specified - * detail message and cause. Note that the detail message associated - * with {@code cause} is <i>not</i> automatically incorporated in - * this error's detail message. - * - * @param message the detail message - * @param cause the cause, may be {@code null} - */ - public InvalidContainerAnnotationError(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs a new InvalidContainerAnnotationError with the - * specified cause and a detail message of {@code (cause == null ? - * null : cause.toString())} (which typically contains the class - * and detail message of {@code cause}). - * - * @param cause the cause, may be {@code null} - */ - public InvalidContainerAnnotationError(Throwable cause) { - super(cause); - } - - /** - * Constructs InvalidContainerAnnotationError for the specified - * container instance and contained annotation type. - * - * @param message the detail message - * @param cause the cause, may be {@code null} - * @param container the erroneous container instance, may be - * {@code null} - * @param annotationType the annotation type intended to be - * contained, may be {@code null} - */ - public InvalidContainerAnnotationError(String message, - Throwable cause, - Annotation container, - Class<? extends Annotation> annotationType) { - super(message, cause); - this.container = container; - this.annotationType = annotationType; - } - - /** - * Returns the erroneous container. - * - * @return the erroneous container, may return {@code null} - */ - public Annotation getContainer() { - return container; - } - - /** - * Returns the annotation type intended to be contained. Returns - * {@code null} if the annotation type intended to be contained - * could not be determined. - * - * @return the annotation type intended to be contained, or {@code - * null} if unknown - */ - public Class<? extends Annotation> getAnnotationType() { - return annotationType; - } -}
--- a/src/share/classes/java/lang/annotation/Retention.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/annotation/Retention.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ * * @author Joshua Bloch * @since 1.5 + * @jls 9.6.3.2 @Retention */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/src/share/classes/java/lang/annotation/Target.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/annotation/Target.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -59,6 +59,9 @@ * ... * } * </pre> + * + * @since 1.5 + * @jls 9.6.3.1 @Target */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/src/share/classes/java/lang/invoke/DirectMethodHandle.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/DirectMethodHandle.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, 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 @@ -55,8 +55,7 @@ } // Factory methods: - - static DirectMethodHandle make(Class<?> receiver, MemberName member) { + static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) { MethodType mtype = member.getMethodOrFieldType(); if (!member.isStatic()) { if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor()) @@ -64,8 +63,14 @@ mtype = mtype.insertParameterTypes(0, receiver); } if (!member.isField()) { - LambdaForm lform = preparedLambdaForm(member); - return new DirectMethodHandle(mtype, lform, member); + if (refKind == REF_invokeSpecial) { + member = member.asSpecial(); + LambdaForm lform = preparedLambdaForm(member); + return new Special(mtype, lform, member); + } else { + LambdaForm lform = preparedLambdaForm(member); + return new DirectMethodHandle(mtype, lform, member); + } } else { LambdaForm lform = preparedFieldLambdaForm(member); if (member.isStatic()) { @@ -79,6 +84,12 @@ } } } + static DirectMethodHandle make(Class<?> receiver, MemberName member) { + byte refKind = member.getReferenceKind(); + if (refKind == REF_invokeSpecial) + refKind = REF_invokeVirtual; + return make(refKind, receiver, member); + } static DirectMethodHandle make(MemberName member) { if (member.isConstructor()) return makeAllocator(member); @@ -114,6 +125,10 @@ //// Implementation methods. @Override + MethodHandle viewAsType(MethodType newType) { + return new DirectMethodHandle(newType, form, member); + } + @Override @ForceInline MemberName internalMemberName() { return member; @@ -357,6 +372,21 @@ ((DirectMethodHandle)mh).ensureInitialized(); } + /** This subclass represents invokespecial instructions. */ + static class Special extends DirectMethodHandle { + private Special(MethodType mtype, LambdaForm form, MemberName member) { + super(mtype, form, member); + } + @Override + boolean isInvokeSpecial() { + return true; + } + @Override + MethodHandle viewAsType(MethodType newType) { + return new Special(newType, form, member); + } + } + /** This subclass handles constructor references. */ static class Constructor extends DirectMethodHandle { final MemberName initMethod; @@ -369,6 +399,10 @@ this.instanceClass = instanceClass; assert(initMethod.isResolved()); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new Constructor(newType, form, member, initMethod, instanceClass); + } } /*non-public*/ static Object constructorMethod(Object mh) { @@ -395,6 +429,10 @@ @Override Object checkCast(Object obj) { return fieldType.cast(obj); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new Accessor(newType, form, member, fieldOffset); + } } @ForceInline @@ -434,6 +472,10 @@ @Override Object checkCast(Object obj) { return fieldType.cast(obj); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new StaticAccessor(newType, form, member, staticBase, staticOffset); + } } @ForceInline
--- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Sat Mar 02 11:06:58 2013 -0400 @@ -53,7 +53,7 @@ private static final String NAME_OBJECT = "java/lang/Object"; private static final String DESCR_CTOR_SERIALIZED_LAMBDA = MethodType.methodType(void.class, - String.class, + Class.class, int.class, String.class, String.class, String.class, int.class, String.class, String.class, String.class, String.class, @@ -284,7 +284,7 @@ mv.visitCode(); mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA); mv.visitInsn(DUP);; - mv.visitLdcInsn(targetClass.getName().replace('.', '/')); + mv.visitLdcInsn(Type.getType(targetClass)); mv.visitLdcInsn(samInfo.getReferenceKind()); mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/')); mv.visitLdcInsn(samInfo.getName());
--- a/src/share/classes/java/lang/invoke/LambdaMetafactory.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/LambdaMetafactory.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -220,24 +220,11 @@ * of the caller. * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site. * Currently unused. - * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the + * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu * expected static type of the returned lambda object, and the static types of the captured * arguments for the lambda. In the event that the implementation method is an instance method, * the first argument in the invocation signature will correspond to the receiver. - * @param samMethod The primary method in the functional interface to which the lambda or method reference is - * being converted, represented as a method handle. - * @param implMethod The implementation method which should be called (with suitable adaptation of argument - * types, return types, and adjustment for captured arguments) when methods of the resulting - * functional interface instance are invoked. - * @param instantiatedMethodType The signature of the primary functional interface method after type variables - * are substituted with their instantiation from the capture site - * @param flags A bitmask containing flags that may influence the translation of this lambda expression. Defined - * fields include FLAG_SERIALIZABLE and FLAG_MARKERS. - * @param markerInterfaceCount If the FLAG_MARKERS flag is set, this is a count of the number of additional - * marker interfaces - * @param markerInterfaces If the FLAG_MARKERS flag is set, this consists of Class objects identifying additional - * marker interfaces which the lambda object should implement, whose count equals - * markerInterfaceCount + * @param args argument to pass, flags, marker interface count, and marker interfaces as described above * @return a CallSite, which, when invoked, will return an instance of the functional interface * @throws ReflectiveOperationException * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
--- a/src/share/classes/java/lang/invoke/MethodHandle.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandle.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, 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 @@ -1250,8 +1250,6 @@ /*non-public*/ MethodHandle viewAsType(MethodType newType) { // No actual conversions, just a new view of the same method. - if (!type.isViewableAs(newType)) - throw new InternalError(); return MethodHandleImpl.makePairwiseConvert(this, newType, 0); } @@ -1268,6 +1266,11 @@ } /*non-public*/ + boolean isInvokeSpecial() { + return false; // DMH.Special returns true + } + + /*non-public*/ Object internalValues() { return null; }
--- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, 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 @@ -367,11 +367,11 @@ @Override MethodHandle viewAsType(MethodType newType) { - MethodHandle mh = super.viewAsType(newType); + if (newType.lastParameterType() != type().lastParameterType()) + throw new InternalError(); + MethodHandle newTarget = asFixedArity().viewAsType(newType); // put back the varargs bit: - MethodType type = mh.type(); - int arity = type.parameterCount(); - return mh.asVarargsCollector(type.parameterType(arity-1)); + return new AsVarargsCollector(newTarget, newType, arrayType); } @Override @@ -379,6 +379,12 @@ return asFixedArity().internalMemberName(); } + /*non-public*/ + @Override + boolean isInvokeSpecial() { + return asFixedArity().isInvokeSpecial(); + } + @Override MethodHandle bindArgument(int pos, char basicType, Object value) {
--- a/src/share/classes/java/lang/invoke/MethodHandleInfo.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandleInfo.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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,6 @@ */ final class MethodHandleInfo { public static final int - REF_NONE = Constants.REF_NONE, REF_getField = Constants.REF_getField, REF_getStatic = Constants.REF_getStatic, REF_putField = Constants.REF_putField, @@ -48,12 +47,17 @@ private final MethodType methodType; private final int referenceKind; - public MethodHandleInfo(MethodHandle mh) throws ReflectiveOperationException { + public MethodHandleInfo(MethodHandle mh) { MemberName mn = mh.internalMemberName(); + if (mn == null) throw new IllegalArgumentException("not a direct method handle"); this.declaringClass = mn.getDeclaringClass(); this.name = mn.getName(); - this.methodType = mn.getMethodType(); - this.referenceKind = mn.getReferenceKind(); + this.methodType = mn.getMethodOrFieldType(); + byte refKind = mn.getReferenceKind(); + if (refKind == REF_invokeSpecial && !mh.isInvokeSpecial()) + // Devirtualized method invocation is usually formally virtual. + refKind = REF_invokeVirtual; + this.referenceKind = refKind; } public Class<?> getDeclaringClass() { @@ -78,7 +82,6 @@ static String getReferenceKindString(int referenceKind) { switch (referenceKind) { - case REF_NONE: return "REF_NONE"; case REF_getField: return "getfield"; case REF_getStatic: return "getstatic"; case REF_putField: return "putfield";
--- a/src/share/classes/java/lang/invoke/MethodHandles.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, 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 @@ -1209,7 +1209,7 @@ checkMethod(refKind, refc, method); if (method.isMethodHandleInvoke()) return fakeMethodHandleInvoke(method); - MethodHandle mh = DirectMethodHandle.make(refc, method); + MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); mh = maybeBindCaller(method, mh); mh = mh.setVarargs(method); if (doRestrict)
--- a/src/share/classes/java/lang/invoke/SerializedLambda.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/invoke/SerializedLambda.java Sat Mar 02 11:06:58 2013 -0400 @@ -40,7 +40,7 @@ */ public final class SerializedLambda implements Serializable { private static final long serialVersionUID = 8025925345765570181L; - private final String capturingClass; + private final Class<?> capturingClass; private final String functionalInterfaceClass; private final String functionalInterfaceMethodName; private final String functionalInterfaceMethodSignature; @@ -73,7 +73,7 @@ * @param capturedArgs The dynamic arguments to the lambda factory site, which represent variables captured by * the lambda */ - public SerializedLambda(String capturingClass, + public SerializedLambda(Class<?> capturingClass, int functionalInterfaceMethodKind, String functionalInterfaceClass, String functionalInterfaceMethodName, @@ -99,7 +99,7 @@ /** Get the name of the class that captured this lambda */ public String getCapturingClass() { - return capturingClass; + return capturingClass.getName().replace('.', '/'); } /** Get the name of the functional interface class to which this lambda has been converted */ @@ -166,9 +166,7 @@ Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() { @Override public Method run() throws Exception { - Class<?> clazz = Class.forName(capturingClass.replace('/', '.'), true, - Thread.currentThread().getContextClassLoader()); - Method m = clazz.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class); + Method m = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class); m.setAccessible(true); return m; } @@ -196,14 +194,4 @@ MethodHandleInfo.getReferenceKindString(implMethodKind), implClass, implMethodName, implMethodSignature, instantiatedMethodType, capturedArgs.length); } - - /* - // @@@ Review question: is it worthwhile implementing a versioned serialization protocol? - - private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { - } - - private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { - } -*/ }
--- a/src/share/classes/java/lang/reflect/AnnotatedElement.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/lang/reflect/AnnotatedElement.java Sat Mar 02 11:06:58 2013 -0400 @@ -26,6 +26,7 @@ package java.lang.reflect; import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; /** * Represents an annotated element of the program currently running in this @@ -86,8 +87,8 @@ * * <p>Attempting to read annotations of a repeatable annotation type T * that are contained in an annotation whose type is not, in fact, the - * containing annotation type of T will result in an - * InvalidContainerAnnotationError. + * containing annotation type of T, will result in an {@link + * AnnotationFormatError}. * * <p>Finally, attempting to read a member whose definition has evolved * incompatibly will result in a {@link @@ -96,10 +97,9 @@ * * @see java.lang.EnumConstantNotPresentException * @see java.lang.TypeNotPresentException - * @see java.lang.annotation.AnnotationFormatError + * @see AnnotationFormatError * @see java.lang.annotation.AnnotationTypeMismatchException * @see java.lang.annotation.IncompleteAnnotationException - * @see java.lang.annotation.InvalidContainerAnnotationError * @since 1.5 * @author Josh Bloch */
--- a/src/share/classes/java/nio/file/Files.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/nio/file/Files.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, 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 @@ -1152,7 +1152,7 @@ * and file system dependent and therefore unspecified. Minimally, the * {@link BasicFileAttributes#lastModifiedTime last-modified-time} is * copied to the target file if supported by both the source and target - * file store. Copying of file timestamps may result in precision + * file stores. Copying of file timestamps may result in precision * loss. </td> * </tr> * <tr> @@ -1169,12 +1169,12 @@ * implementation specific options. * * <p> Copying a file is not an atomic operation. If an {@link IOException} - * is thrown then it possible that the target file is incomplete or some of - * its file attributes have not been copied from the source file. When the - * {@code REPLACE_EXISTING} option is specified and the target file exists, - * then the target file is replaced. The check for the existence of the file - * and the creation of the new file may not be atomic with respect to other - * file system activities. + * is thrown, then it is possible that the target file is incomplete or some + * of its file attributes have not been copied from the source file. When + * the {@code REPLACE_EXISTING} option is specified and the target file + * exists, then the target file is replaced. The check for the existence of + * the file and the creation of the new file may not be atomic with respect + * to other file system activities. * * <p> <b>Usage Example:</b> * Suppose we want to copy a file into a directory, giving it the same file @@ -1279,15 +1279,16 @@ * <p> An implementation of this interface may support additional * implementation specific options. * - * <p> Where the move requires that the file be copied then the {@link - * BasicFileAttributes#lastModifiedTime last-modified-time} is copied to the - * new file. An implementation may also attempt to copy other file - * attributes but is not required to fail if the file attributes cannot be - * copied. When the move is performed as a non-atomic operation, and a {@code - * IOException} is thrown, then the state of the files is not defined. The - * original file and the target file may both exist, the target file may be - * incomplete or some of its file attributes may not been copied from the - * original file. + * <p> Moving a file will copy the {@link + * BasicFileAttributes#lastModifiedTime last-modified-time} to the target + * file if supported by both source and target file stores. Copying of file + * timestamps may result in precision loss. An implementation may also + * attempt to copy other file attributes but is not required to fail if the + * file attributes cannot be copied. When the move is performed as + * a non-atomic operation, and an {@code IOException} is thrown, then the + * state of the files is not defined. The original file and the target file + * may both exist, the target file may be incomplete or some of its file + * attributes may not been copied from the original file. * * <p> <b>Usage Examples:</b> * Suppose we want to rename a file to "newname", keeping the file in the
--- a/src/share/classes/java/util/IdentityHashMap.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/util/IdentityHashMap.java Sat Mar 02 11:06:58 2013 -0400 @@ -1106,12 +1106,12 @@ Object[] tab = table; int ti = 0; for (int si = 0; si < tab.length; si += 2) { - if (tab[si++] != null) { // key present ? + if (tab[si] != null) { // key present ? // more elements than expected -> concurrent modification from other thread if (ti >= size) { throw new ConcurrentModificationException(); } - a[ti++] = (T) tab[si]; // copy value + a[ti++] = (T) tab[si+1]; // copy value } } // fewer elements than expected or concurrent modification from other thread detected
--- a/src/share/classes/java/util/concurrent/ForkJoinPool.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java Sat Mar 02 11:06:58 2013 -0400 @@ -35,6 +35,7 @@ package java.util.concurrent; +import java.lang.Thread.UncaughtExceptionHandler; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -104,38 +105,45 @@ * there is little difference among choice of methods. * * <table BORDER CELLPADDING=3 CELLSPACING=1> + * <caption>Summary of task execution methods</caption> * <tr> * <td></td> * <td ALIGN=CENTER> <b>Call from non-fork/join clients</b></td> * <td ALIGN=CENTER> <b>Call from within fork/join computations</b></td> * </tr> * <tr> - * <td> <b>Arrange async execution</td> + * <td> <b>Arrange async execution</b></td> * <td> {@link #execute(ForkJoinTask)}</td> * <td> {@link ForkJoinTask#fork}</td> * </tr> * <tr> - * <td> <b>Await and obtain result</td> + * <td> <b>Await and obtain result</b></td> * <td> {@link #invoke(ForkJoinTask)}</td> * <td> {@link ForkJoinTask#invoke}</td> * </tr> * <tr> - * <td> <b>Arrange exec and obtain Future</td> + * <td> <b>Arrange exec and obtain Future</b></td> * <td> {@link #submit(ForkJoinTask)}</td> * <td> {@link ForkJoinTask#fork} (ForkJoinTasks <em>are</em> Futures)</td> * </tr> * </table> * * <p>The common pool is by default constructed with default - * parameters, but these may be controlled by setting three {@link - * System#getProperty system properties} with prefix {@code - * java.util.concurrent.ForkJoinPool.common}: {@code parallelism} -- - * an integer greater than zero, {@code threadFactory} -- the class - * name of a {@link ForkJoinWorkerThreadFactory}, and {@code - * exceptionHandler} -- the class name of a {@link - * java.lang.Thread.UncaughtExceptionHandler - * Thread.UncaughtExceptionHandler}. Upon any error in establishing - * these settings, default parameters are used. + * parameters, but these may be controlled by setting three + * {@linkplain System#getProperty system properties}: + * <ul> + * <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism} + * - the parallelism level, a non-negative integer + * <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory} + * - the class name of a {@link ForkJoinWorkerThreadFactory} + * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler} + * - the class name of a {@link UncaughtExceptionHandler} + * </ul> + * The system class loader is used to load these classes. + * Upon any error in establishing these settings, default parameters + * are used. It is possible to disable or limit the use of threads in + * the common pool by setting the parallelism property to zero, and/or + * using a factory that may return {@code null}. * * <p><b>Implementation notes</b>: This implementation restricts the * maximum number of running threads to 32767. Attempts to create @@ -225,18 +233,18 @@ * for work-stealing (this would contaminate lifo/fifo * processing). Instead, we randomly associate submission queues * with submitting threads, using a form of hashing. The - * ThreadLocal Submitter class contains a value initially used as - * a hash code for choosing existing queues, but may be randomly - * repositioned upon contention with other submitters. In - * essence, submitters act like workers except that they are - * restricted to executing local tasks that they submitted (or in - * the case of CountedCompleters, others with the same root task). - * However, because most shared/external queue operations are more - * expensive than internal, and because, at steady state, external - * submitters will compete for CPU with workers, ForkJoinTask.join - * and related methods disable them from repeatedly helping to - * process tasks if all workers are active. Insertion of tasks in - * shared mode requires a lock (mainly to protect in the case of + * ThreadLocalRandom probe value serves as a hash code for + * choosing existing queues, and may be randomly repositioned upon + * contention with other submitters. In essence, submitters act + * like workers except that they are restricted to executing local + * tasks that they submitted (or in the case of CountedCompleters, + * others with the same root task). However, because most + * shared/external queue operations are more expensive than + * internal, and because, at steady state, external submitters + * will compete for CPU with workers, ForkJoinTask.join and + * related methods disable them from repeatedly helping to process + * tasks if all workers are active. Insertion of tasks in shared + * mode requires a lock (mainly to protect in the case of * resizing) but we use only a simple spinlock (using bits in * field qlock), because submitters encountering a busy queue move * on to try or create other queues -- they block only when @@ -469,7 +477,7 @@ * Common Pool * =========== * - * The static commonPool always exists after static + * The static common Pool always exists after static * initialization. Since it (or any other created pool) need * never be used, we minimize initial construction overhead and * footprint to the setup of about a dozen fields, with no nested @@ -548,6 +556,7 @@ * * @param pool the pool this thread works in * @throws NullPointerException if the pool is null + * @return the new worker thread */ public ForkJoinWorkerThread newThread(ForkJoinPool pool); } @@ -564,26 +573,6 @@ } /** - * Per-thread records for threads that submit to pools. Currently - * holds only pseudo-random seed / index that is used to choose - * submission queues in method externalPush. In the future, this may - * also incorporate a means to implement different task rejection - * and resubmission policies. - * - * Seeds for submitters and workers/workQueues work in basically - * the same way but are initialized and updated using slightly - * different mechanics. Both are initialized using the same - * approach as in class ThreadLocal, where successive values are - * unlikely to collide with previous values. Seeds are then - * randomly modified upon collisions using xorshifts, which - * requires a non-zero seed. - */ - static final class Submitter { - int seed; - Submitter(int s) { seed = s; } - } - - /** * Class for artificial tasks that are used to replace the target * of local joins if they are removed from an interior queue slot * in WorkQueue.tryRemoveAndExec. We don't need the proxy to @@ -737,7 +726,7 @@ * shared-queue version is embedded in method externalPush.) * * @param task the task. Caller must ensure non-null. - * @throw RejectedExecutionException if array cannot be resized + * @throws RejectedExecutionException if array cannot be resized */ final void push(ForkJoinTask<?> task) { ForkJoinTask<?>[] a; ForkJoinPool p; @@ -936,7 +925,7 @@ * or any other cancelled task. Returns (true) on any CAS * or consistency check failure so caller can retry. * - * @return false if no progress can be made, else true; + * @return false if no progress can be made, else true */ final boolean tryRemoveAndExec(ForkJoinTask<?> task) { boolean stat = true, removed = false, empty = true; @@ -981,7 +970,7 @@ /** * Polls for and executes the given task or any other task in - * its CountedCompleter computation + * its CountedCompleter computation. */ final boolean pollAndExecCC(ForkJoinTask<?> root) { ForkJoinTask<?>[] a; int b; Object o; @@ -1055,7 +1044,6 @@ private static final int ABASE; private static final int ASHIFT; static { - int s; try { U = sun.misc.Unsafe.getUnsafe(); Class<?> k = WorkQueue.class; @@ -1063,13 +1051,13 @@ QLOCK = U.objectFieldOffset (k.getDeclaredField("qlock")); ABASE = U.arrayBaseOffset(ak); - s = U.arrayIndexScale(ak); + int scale = U.arrayIndexScale(ak); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); } catch (Exception e) { throw new Error(e); } - if ((s & (s-1)) != 0) - throw new Error("data type scale not a power of two"); - ASHIFT = 31 - Integer.numberOfLeadingZeros(s); } } @@ -1083,15 +1071,6 @@ defaultForkJoinWorkerThreadFactory; /** - * Per-thread submission bookkeeping. Shared across all pools - * to reduce ThreadLocal pollution and because random motion - * to avoid contention in one pool is likely to hold for others. - * Lazily initialized on first submission (but null-checked - * in other contexts to avoid unnecessary initialization). - */ - static final ThreadLocal<Submitter> submitters; - - /** * Permission required for callers of methods that may start or * kill threads. */ @@ -1103,12 +1082,15 @@ * to paranoically avoid potential initialization circularities * as well as to simplify generated code. */ - static final ForkJoinPool commonPool; + static final ForkJoinPool common; /** - * Common pool parallelism. Must equal commonPool.parallelism. + * Common pool parallelism. To allow simpler use and management + * when common pool threads are disabled, we allow the underlying + * common.config field to be zero, but in that case still report + * parallelism as 1 to reflect resulting caller-runs mechanics. */ - static final int commonPoolParallelism; + static final int commonParallelism; /** * Sequence number for creating workerNamePrefix. @@ -1116,8 +1098,8 @@ private static int poolNumberSequence; /** - * Return the next sequence number. We don't expect this to - * ever contend so use simple builtin sync. + * Returns the next sequence number. We don't expect this to + * ever contend, so use simple builtin sync. */ private static final synchronized int nextPoolId() { return ++poolNumberSequence; @@ -1161,7 +1143,7 @@ */ private static final int SEED_INCREMENT = 0x61c88647; - /** + /* * Bits and masks for control variables * * Field ctl is a long packed with: @@ -1268,39 +1250,28 @@ final int config; // mode and parallelism level WorkQueue[] workQueues; // main registry final ForkJoinWorkerThreadFactory factory; - final Thread.UncaughtExceptionHandler ueh; // per-worker UEH + final UncaughtExceptionHandler ueh; // per-worker UEH final String workerNamePrefix; // to create worker name string volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17; volatile Object pad18, pad19, pad1a, pad1b; - /* + /** * Acquires the plock lock to protect worker array and related * updates. This method is called only if an initial CAS on plock - * fails. This acts as a spinLock for normal cases, but falls back + * fails. This acts as a spinlock for normal cases, but falls back * to builtin monitor to block when (rarely) needed. This would be * a terrible idea for a highly contended lock, but works fine as * a more conservative alternative to a pure spinlock. */ private int acquirePlock() { - int spins = PL_SPINS, r = 0, ps, nps; + int spins = PL_SPINS, ps, nps; for (;;) { if (((ps = plock) & PL_LOCK) == 0 && U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK)) return nps; - else if (r == 0) { // randomize spins if possible - Thread t = Thread.currentThread(); WorkQueue w; Submitter z; - if ((t instanceof ForkJoinWorkerThread) && - (w = ((ForkJoinWorkerThread)t).workQueue) != null) - r = w.seed; - else if ((z = submitters.get()) != null) - r = z.seed; - else - r = 1; - } else if (spins >= 0) { - r ^= r << 1; r ^= r >>> 3; r ^= r << 10; // xorshift - if (r >= 0) + if (ThreadLocalRandom.nextSecondarySeed() >= 0) --spins; } else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) { @@ -1332,39 +1303,6 @@ } /** - * Performs secondary initialization, called when plock is zero. - * Creates workQueue array and sets plock to a valid value. The - * lock body must be exception-free (so no try/finally) so we - * optimistically allocate new array outside the lock and throw - * away if (very rarely) not needed. (A similar tactic is used in - * fullExternalPush.) Because the plock seq value can eventually - * wrap around zero, this method harmlessly fails to reinitialize - * if workQueues exists, while still advancing plock. - * - * Additionally tries to create the first worker. - */ - private void initWorkers() { - WorkQueue[] ws, nws; int ps; - int p = config & SMASK; // find power of two table size - int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots - n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; - n = (n + 1) << 1; - if ((ws = workQueues) == null || ws.length == 0) - nws = new WorkQueue[n]; - else - nws = null; - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if (((ws = workQueues) == null || ws.length == 0) && nws != null) - workQueues = nws; - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - tryAddWorker(); - } - - /** * Tries to create and start one worker if fewer than target * parallelism level exist. Adjusts counts etc on failure. */ @@ -1406,7 +1344,7 @@ * @return the worker's queue */ final WorkQueue registerWorker(ForkJoinWorkerThread wt) { - Thread.UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps; + UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps; wt.setDaemon(true); if ((handler = ueh) != null) wt.setUncaughtExceptionHandler(handler); @@ -1450,7 +1388,7 @@ * array, and adjusts counts. If pool is shutting down, tries to * complete termination. * - * @param wt the worker thread or null if construction failed + * @param wt the worker thread, or null if construction failed * @param ex the exception causing failure, or null if none */ final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) { @@ -1489,7 +1427,7 @@ if (e > 0) { // activate or create replacement if ((ws = workQueues) == null || (i = e & SMASK) >= ws.length || - (v = ws[i]) != null) + (v = ws[i]) == null) break; long nc = (((long)(v.nextWait & E_MASK)) | ((long)(u + UAC_UNIT) << 32)); @@ -1526,10 +1464,10 @@ * @param task the task. Caller must ensure non-null. */ final void externalPush(ForkJoinTask<?> task) { - WorkQueue[] ws; WorkQueue q; Submitter z; int m; ForkJoinTask<?>[] a; - if ((z = submitters.get()) != null && plock > 0 && + WorkQueue[] ws; WorkQueue q; int z, m; ForkJoinTask<?>[] a; + if ((z = ThreadLocalRandom.getProbe()) != 0 && plock > 0 && (ws = workQueues) != null && (m = (ws.length - 1)) >= 0 && - (q = ws[m & z.seed & SQMASK]) != null && + (q = ws[m & z & SQMASK]) != null && U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock int b = q.base, s = q.top, n, an; if ((a = q.array) != null && (an = a.length) > (n = s + 1 - b)) { @@ -1549,34 +1487,48 @@ /** * Full version of externalPush. This method is called, among * other times, upon the first submission of the first task to the - * pool, so must perform secondary initialization (via - * initWorkers). It also detects first submission by an external - * thread by looking up its ThreadLocal, and creates a new shared - * queue if the one at index if empty or contended. The plock lock - * body must be exception-free (so no try/finally) so we - * optimistically allocate new queues outside the lock and throw - * them away if (very rarely) not needed. + * pool, so must perform secondary initialization. It also + * detects first submission by an external thread by looking up + * its ThreadLocal, and creates a new shared queue if the one at + * index if empty or contended. The plock lock body must be + * exception-free (so no try/finally) so we optimistically + * allocate new queues outside the lock and throw them away if + * (very rarely) not needed. + * + * Secondary initialization occurs when plock is zero, to create + * workQueue array and set plock to a valid value. This lock body + * must also be exception-free. Because the plock seq value can + * eventually wrap around zero, this method harmlessly fails to + * reinitialize if workQueues exists, while still advancing plock. */ private void fullExternalPush(ForkJoinTask<?> task) { - int r = 0; // random index seed - for (Submitter z = submitters.get();;) { + int r; + if ((r = ThreadLocalRandom.getProbe()) == 0) { + ThreadLocalRandom.localInit(); + r = ThreadLocalRandom.getProbe(); + } + for (;;) { WorkQueue[] ws; WorkQueue q; int ps, m, k; - if (z == null) { - if (U.compareAndSwapInt(this, INDEXSEED, r = indexSeed, - r += SEED_INCREMENT) && r != 0) - submitters.set(z = new Submitter(r)); - } - else if (r == 0) { // move to a different index - r = z.seed; - r ^= r << 13; // same xorshift as WorkQueues - r ^= r >>> 17; - z.seed = r ^ (r << 5); - } - else if ((ps = plock) < 0) + boolean move = false; + if ((ps = plock) < 0) throw new RejectedExecutionException(); else if (ps == 0 || (ws = workQueues) == null || - (m = ws.length - 1) < 0) - initWorkers(); + (m = ws.length - 1) < 0) { // initialize workQueues + int p = config & SMASK; // find power of two table size + int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots + n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; + n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1; + WorkQueue[] nws = ((ws = workQueues) == null || ws.length == 0 ? + new WorkQueue[n] : null); + if (((ps = plock) & PL_LOCK) != 0 || + !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) + ps = acquirePlock(); + if (((ws = workQueues) == null || ws.length == 0) && nws != null) + workQueues = nws; + int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); + if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) + releasePlock(nps); + } else if ((q = ws[k = r & m & SQMASK]) != null) { if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) { ForkJoinTask<?>[] a = q.array; @@ -1598,7 +1550,7 @@ return; } } - r = 0; // move on failure + move = true; // move on failure } else if (((ps = plock) & PL_LOCK) == 0) { // create new queue q = new WorkQueue(this, null, SHARED_QUEUE, r); @@ -1612,7 +1564,9 @@ releasePlock(nps); } else - r = 0; // try elsewhere while lock held + move = true; // move if busy + if (move) + r = ThreadLocalRandom.advanceProbe(r); } } @@ -1703,7 +1657,7 @@ * park awaiting signal, else lingering to help scan and signal. * * * If a non-empty queue discovered or left as a hint, - * help wake up other workers before return + * help wake up other workers before return. * * @param w the worker (via its WorkQueue) * @return a task or null if none found @@ -1758,14 +1712,13 @@ else if ((int)(c >> AC_SHIFT) == 1 - (config & SMASK)) idleAwaitWork(w, nc, c); } - else if (w.eventCount < 0 && !tryTerminate(false, false) && - ctl == c) { // block + else if (w.eventCount < 0 && ctl == c) { Thread wt = Thread.currentThread(); Thread.interrupted(); // clear status U.putObject(wt, PARKBLOCKER, this); w.parker = wt; // emulate LockSupport.park if (w.eventCount < 0) // recheck - U.park(false, 0L); + U.park(false, 0L); // block w.parker = null; U.putObject(wt, PARKBLOCKER, null); } @@ -1774,7 +1727,7 @@ (ws = workQueues) != null && h < ws.length && (q = ws[h]) != null) { // signal others before retry WorkQueue v; Thread p; int u, i, s; - for (int n = (config & SMASK) >>> 1;;) { + for (int n = (config & SMASK) - 1;;) { int idleCount = (w.eventCount < 0) ? 0 : -1; if (((s = idleCount - q.base + q.top) <= n && (n = s) <= 0) || @@ -1814,7 +1767,8 @@ */ private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) { if (w != null && w.eventCount < 0 && - !tryTerminate(false, false) && (int)prevCtl != 0) { + !tryTerminate(false, false) && (int)prevCtl != 0 && + ctl == currentCtl) { int dc = -(short)(currentCtl >>> TC_SHIFT); long parkTime = dc < 0 ? FAST_IDLE_TIMEOUT: (dc + 1) * IDLE_TIMEOUT; long deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP; @@ -1832,6 +1786,7 @@ if (deadline - System.nanoTime() <= 0L && U.compareAndSwapLong(this, CTL, currentCtl, prevCtl)) { w.eventCount = (w.eventCount + E_SEQ) | E_MASK; + w.hint = -1; w.qlock = -1; // shrink break; } @@ -1973,7 +1928,6 @@ * @param task the task to join * @param mode if shared, exit upon completing any task * if all workers are active - * */ private int helpComplete(ForkJoinTask<?> task, int mode) { WorkQueue[] ws; WorkQueue q; int m, n, s, u; @@ -2125,29 +2079,22 @@ /** * Returns a (probably) non-empty steal queue, if one is found - * during a random, then cyclic scan, else null. This method must - * be retried by caller if, by the time it tries to use the queue, - * it is empty. + * during a scan, else null. This method must be retried by + * caller if, by the time it tries to use the queue, it is empty. * @param r a (random) seed for scanning */ private WorkQueue findNonEmptyStealQueue(int r) { - for (WorkQueue[] ws;;) { - int ps = plock, m, n; - if ((ws = workQueues) == null || (m = ws.length - 1) < 1) - return null; - for (int j = (m + 1) << 2; ;) { - WorkQueue q = ws[(((r + j) << 1) | 1) & m]; - if (q != null && (n = q.base - q.top) < 0) { - if (n < -1) - signalWork(q); - return q; - } - else if (--j < 0) { - if (plock == ps) - return null; - break; + for (;;) { + int ps = plock, m; WorkQueue[] ws; WorkQueue q; + if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) { + for (int j = (m + 1) << 2; j >= 0; --j) { + if ((q = ws[(((r + j) << 1) | 1) & m]) != null && + q.base - q.top < 0) + return q; } } + if (plock == ps) + return null; } } @@ -2159,37 +2106,34 @@ */ final void helpQuiescePool(WorkQueue w) { for (boolean active = true;;) { - ForkJoinTask<?> localTask; // exhaust local queue - while ((localTask = w.nextLocalTask()) != null) - localTask.doExec(); - // Similar to loop in scan(), but ignoring submissions - WorkQueue q = findNonEmptyStealQueue(w.nextSeed()); - if (q != null) { - ForkJoinTask<?> t; int b; + long c; WorkQueue q; ForkJoinTask<?> t; int b; + while ((t = w.nextLocalTask()) != null) { + if (w.base - w.top < 0) + signalWork(w); + t.doExec(); + } + if ((q = findNonEmptyStealQueue(w.nextSeed())) != null) { if (!active) { // re-establish active count - long c; active = true; do {} while (!U.compareAndSwapLong (this, CTL, c = ctl, c + AC_UNIT)); } - if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) + if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) { + if (q.base - q.top < 0) + signalWork(q); w.runSubtask(t); - } - else { - long c; - if (active) { // decrement active count without queuing - active = false; - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, c -= AC_UNIT)); - } - else - c = ctl; // re-increment on exit - if ((int)(c >> AC_SHIFT) + (config & SMASK) == 0) { - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, c + AC_UNIT)); - break; } } + else if (active) { // decrement active count without queuing + long nc = (c = ctl) - AC_UNIT; + if ((int)(nc >> AC_SHIFT) + (config & SMASK) == 0) + return; // bypass decrement-then-increment + if (U.compareAndSwapLong(this, CTL, c, nc)) + active = false; + } + else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) == 0 && + U.compareAndSwapLong(this, CTL, c, c + AC_UNIT)) + return; } } @@ -2205,8 +2149,11 @@ return t; if ((q = findNonEmptyStealQueue(w.nextSeed())) == null) return null; - if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) + if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) { + if (q.base - q.top < 0) + signalWork(q); return t; + } } } @@ -2235,7 +2182,7 @@ * producing extra tasks amortizes the uncertainty of progress and * diffusion assumptions. * - * So, users will want to use values larger, but not much larger + * So, users will want to use values larger (but not much larger) * than 1 to both smooth over transient shortages and hedge * against uneven progress; as traded off against the cost of * extra task overhead. We leave the user to pick a threshold @@ -2288,45 +2235,49 @@ * @return true if now terminating or terminated */ private boolean tryTerminate(boolean now, boolean enable) { - if (this == commonPool) // cannot shut down + int ps; + if (this == common) // cannot shut down return false; + if ((ps = plock) >= 0) { // enable by setting plock + if (!enable) + return false; + if ((ps & PL_LOCK) != 0 || + !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) + ps = acquirePlock(); + int nps = ((ps + PL_LOCK) & ~SHUTDOWN) | SHUTDOWN; + if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) + releasePlock(nps); + } for (long c;;) { - if (((c = ctl) & STOP_BIT) != 0) { // already terminating + if (((c = ctl) & STOP_BIT) != 0) { // already terminating if ((short)(c >>> TC_SHIFT) == -(config & SMASK)) { synchronized (this) { - notifyAll(); // signal when 0 workers + notifyAll(); // signal when 0 workers } } return true; } - if (plock >= 0) { // not yet enabled - int ps; - if (!enable) + if (!now) { // check if idle & no tasks + WorkQueue[] ws; WorkQueue w; + if ((int)(c >> AC_SHIFT) != -(config & SMASK)) return false; - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if (!U.compareAndSwapInt(this, PLOCK, ps, SHUTDOWN)) - releasePlock(SHUTDOWN); - } - if (!now) { // check if idle & no tasks - if ((int)(c >> AC_SHIFT) != -(config & SMASK) || - hasQueuedSubmissions()) - return false; - // Check for unqueued inactive workers. One pass suffices. - WorkQueue[] ws = workQueues; WorkQueue w; - if (ws != null) { - for (int i = 1; i < ws.length; i += 2) { - if ((w = ws[i]) != null && w.eventCount >= 0) - return false; + if ((ws = workQueues) != null) { + for (int i = 0; i < ws.length; ++i) { + if ((w = ws[i]) != null) { + if (!w.isEmpty()) { // signal unprocessed tasks + signalWork(w); + return false; + } + if ((i & 1) != 0 && w.eventCount >= 0) + return false; // unqueued inactive worker + } } } } if (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) { for (int pass = 0; pass < 3; ++pass) { - WorkQueue[] ws = workQueues; - if (ws != null) { - WorkQueue w; Thread wt; + WorkQueue[] ws; WorkQueue w; Thread wt; + if ((ws = workQueues) != null) { int n = ws.length; for (int i = 0; i < n; ++i) { if ((w = ws[i]) != null) { @@ -2337,7 +2288,7 @@ if (!wt.isInterrupted()) { try { wt.interrupt(); - } catch (SecurityException ignore) { + } catch (Throwable ignore) { } } U.unpark(wt); @@ -2348,7 +2299,7 @@ // Wake up workers parked on event queue int i, e; long cc; Thread p; while ((e = (int)(cc = ctl) & E_MASK) != 0 && - (i = e & SMASK) < n && + (i = e & SMASK) < n && i >= 0 && (w = ws[i]) != null) { long nc = ((long)(w.nextWait & E_MASK) | ((cc + AC_UNIT) & AC_MASK) | @@ -2374,26 +2325,26 @@ * least one task. */ static WorkQueue commonSubmitterQueue() { - ForkJoinPool p; WorkQueue[] ws; int m; Submitter z; - return ((z = submitters.get()) != null && - (p = commonPool) != null && + ForkJoinPool p; WorkQueue[] ws; int m, z; + return ((z = ThreadLocalRandom.getProbe()) != 0 && + (p = common) != null && (ws = p.workQueues) != null && (m = ws.length - 1) >= 0) ? - ws[m & z.seed & SQMASK] : null; + ws[m & z & SQMASK] : null; } /** * Tries to pop the given task from submitter's queue in common pool. */ static boolean tryExternalUnpush(ForkJoinTask<?> t) { - ForkJoinPool p; WorkQueue[] ws; WorkQueue q; Submitter z; - ForkJoinTask<?>[] a; int m, s; + ForkJoinPool p; WorkQueue[] ws; WorkQueue q; + ForkJoinTask<?>[] a; int m, s, z; if (t != null && - (z = submitters.get()) != null && - (p = commonPool) != null && + (z = ThreadLocalRandom.getProbe()) != 0 && + (p = common) != null && (ws = p.workQueues) != null && (m = ws.length - 1) >= 0 && - (q = ws[m & z.seed & SQMASK]) != null && + (q = ws[m & z & SQMASK]) != null && (s = q.top) != q.base && (a = q.array) != null) { long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; @@ -2445,9 +2396,10 @@ if (task != null) task.doExec(); if (root.status < 0 || - (u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0) + (config != 0 && + ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0))) break; - if (task == null) { + if (task == null) { helpSignal(root, q.poolIndex); if (root.status >= 0) helpComplete(root, SHARED_QUEUE); @@ -2463,14 +2415,14 @@ */ static void externalHelpJoin(ForkJoinTask<?> t) { // Some hard-to-avoid overlap with tryExternalUnpush - ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w; Submitter z; - ForkJoinTask<?>[] a; int m, s, n; + ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w; + ForkJoinTask<?>[] a; int m, s, n, z; if (t != null && - (z = submitters.get()) != null && - (p = commonPool) != null && + (z = ThreadLocalRandom.getProbe()) != 0 && + (p = common) != null && (ws = p.workQueues) != null && (m = ws.length - 1) >= 0 && - (q = ws[m & z.seed & SQMASK]) != null && + (q = ws[m & z & SQMASK]) != null && (a = q.array) != null) { int am = a.length - 1; if ((s = q.top) != q.base) { @@ -2496,18 +2448,6 @@ } } - /** - * Restricted version of helpQuiescePool for external callers - */ - static void externalHelpQuiescePool() { - ForkJoinPool p; ForkJoinTask<?> t; WorkQueue q; int b; - if ((p = commonPool) != null && - (q = p.findNonEmptyStealQueue(1)) != null && - (b = q.base) - q.top < 0 && - (t = q.pollAt(b)) != null) - t.doExec(); - } - // Exported methods // Constructors @@ -2524,7 +2464,7 @@ * java.lang.RuntimePermission}{@code ("modifyThread")} */ public ForkJoinPool() { - this(Runtime.getRuntime().availableProcessors(), + this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()), defaultForkJoinWorkerThreadFactory, null, false); } @@ -2572,50 +2512,63 @@ */ public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory, - Thread.UncaughtExceptionHandler handler, + UncaughtExceptionHandler handler, boolean asyncMode) { + this(checkParallelism(parallelism), + checkFactory(factory), + handler, + asyncMode, + "ForkJoinPool-" + nextPoolId() + "-worker-"); checkPermission(); + } + + private static int checkParallelism(int parallelism) { + if (parallelism <= 0 || parallelism > MAX_CAP) + throw new IllegalArgumentException(); + return parallelism; + } + + private static ForkJoinWorkerThreadFactory checkFactory + (ForkJoinWorkerThreadFactory factory) { if (factory == null) throw new NullPointerException(); - if (parallelism <= 0 || parallelism > MAX_CAP) - throw new IllegalArgumentException(); + return factory; + } + + /** + * Creates a {@code ForkJoinPool} with the given parameters, without + * any security checks or parameter validation. Invoked directly by + * makeCommonPool. + */ + private ForkJoinPool(int parallelism, + ForkJoinWorkerThreadFactory factory, + UncaughtExceptionHandler handler, + boolean asyncMode, + String workerNamePrefix) { + this.workerNamePrefix = workerNamePrefix; this.factory = factory; this.ueh = handler; this.config = parallelism | (asyncMode ? (FIFO_QUEUE << 16) : 0); long np = (long)(-parallelism); // offset ctl counts this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK); - int pn = nextPoolId(); - StringBuilder sb = new StringBuilder("ForkJoinPool-"); - sb.append(Integer.toString(pn)); - sb.append("-worker-"); - this.workerNamePrefix = sb.toString(); - } - - /** - * Constructor for common pool, suitable only for static initialization. - * Basically the same as above, but uses smallest possible initial footprint. - */ - ForkJoinPool(int parallelism, long ctl, - ForkJoinWorkerThreadFactory factory, - Thread.UncaughtExceptionHandler handler) { - this.config = parallelism; - this.ctl = ctl; - this.factory = factory; - this.ueh = handler; - this.workerNamePrefix = "ForkJoinPool.commonPool-worker-"; } /** * Returns the common pool instance. This pool is statically - * constructed; its run state is unaffected by attempts to - * {@link #shutdown} or {@link #shutdownNow}. + * constructed; its run state is unaffected by attempts to {@link + * #shutdown} or {@link #shutdownNow}. However this pool and any + * ongoing processing are automatically terminated upon program + * {@link System#exit}. Any program that relies on asynchronous + * task processing to complete before program termination should + * invoke {@code commonPool().}{@link #awaitQuiescence awaitQuiescence}, + * before exit. * * @return the common pool instance * @since 1.8 */ public static ForkJoinPool commonPool() { - // assert commonPool != null : "static init error"; - return commonPool; + // assert common != null : "static init error"; + return common; } // Execution methods @@ -2671,7 +2624,7 @@ if (task instanceof ForkJoinTask<?>) // avoid re-wrap job = (ForkJoinTask<?>) task; else - job = new ForkJoinTask.AdaptedRunnableAction(task); + job = new ForkJoinTask.RunnableExecuteAction(task); externalPush(job); } @@ -2738,27 +2691,23 @@ // In previous versions of this class, this method constructed // a task to run ForkJoinTask.invokeAll, but now external // invocation of multiple tasks is at least as efficient. - List<ForkJoinTask<T>> fs = new ArrayList<ForkJoinTask<T>>(tasks.size()); - // Workaround needed because method wasn't declared with - // wildcards in return type but should have been. - @SuppressWarnings({"unchecked", "rawtypes"}) - List<Future<T>> futures = (List<Future<T>>) (List) fs; + ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); boolean done = false; try { for (Callable<T> t : tasks) { ForkJoinTask<T> f = new ForkJoinTask.AdaptedCallable<T>(t); + futures.add(f); externalPush(f); - fs.add(f); } - for (ForkJoinTask<T> f : fs) - f.quietlyJoin(); + for (int i = 0, size = futures.size(); i < size; i++) + ((ForkJoinTask<?>)futures.get(i)).quietlyJoin(); done = true; return futures; } finally { if (!done) - for (ForkJoinTask<T> f : fs) - f.cancel(false); + for (int i = 0, size = futures.size(); i < size; i++) + futures.get(i).cancel(false); } } @@ -2777,7 +2726,7 @@ * * @return the handler, or {@code null} if none */ - public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() { + public UncaughtExceptionHandler getUncaughtExceptionHandler() { return ueh; } @@ -2787,7 +2736,8 @@ * @return the targeted parallelism level of this pool */ public int getParallelism() { - return config & SMASK; + int par = (config & SMASK); + return (par > 0) ? par : 1; } /** @@ -2797,7 +2747,7 @@ * @since 1.8 */ public static int getCommonPoolParallelism() { - return commonPoolParallelism; + return commonParallelism; } /** @@ -3055,7 +3005,7 @@ * Possibly initiates an orderly shutdown in which previously * submitted tasks are executed, but no new tasks will be * accepted. Invocation has no effect on execution state if this - * is the {@link #commonPool}, and no additional effect if + * is the {@link #commonPool()}, and no additional effect if * already shut down. Tasks that are in the process of being * submitted concurrently during the course of this method may or * may not be rejected. @@ -3073,7 +3023,7 @@ /** * Possibly attempts to cancel and/or stop all tasks, and reject * all subsequently submitted tasks. Invocation has no effect on - * execution state if this is the {@link #commonPool}, and no + * execution state if this is the {@link #commonPool()}, and no * additional effect if already shut down. Otherwise, tasks that * are in the process of being submitted or executed concurrently * during the course of this method may or may not be @@ -3136,9 +3086,10 @@ /** * Blocks until all tasks have completed execution after a * shutdown request, or the timeout occurs, or the current thread - * is interrupted, whichever happens first. Note that the {@link - * #commonPool()} never terminates until program shutdown so - * this method will always time out. + * is interrupted, whichever happens first. Because the {@link + * #commonPool()} never terminates until program shutdown, when + * applied to the common pool, this method is equivalent to {@link + * #awaitQuiescence(long, TimeUnit)} but always returns {@code false}. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument @@ -3148,6 +3099,12 @@ */ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (this == common) { + awaitQuiescence(timeout, unit); + return false; + } long nanos = unit.toNanos(timeout); if (isTerminated()) return true; @@ -3167,6 +3124,62 @@ } /** + * If called by a ForkJoinTask operating in this pool, equivalent + * in effect to {@link ForkJoinTask#helpQuiesce}. Otherwise, + * waits and/or attempts to assist performing tasks until this + * pool {@link #isQuiescent} or the indicated timeout elapses. + * + * @param timeout the maximum time to wait + * @param unit the time unit of the timeout argument + * @return {@code true} if quiescent; {@code false} if the + * timeout elapsed. + */ + public boolean awaitQuiescence(long timeout, TimeUnit unit) { + long nanos = unit.toNanos(timeout); + ForkJoinWorkerThread wt; + Thread thread = Thread.currentThread(); + if ((thread instanceof ForkJoinWorkerThread) && + (wt = (ForkJoinWorkerThread)thread).pool == this) { + helpQuiescePool(wt.workQueue); + return true; + } + long startTime = System.nanoTime(); + WorkQueue[] ws; + int r = 0, m; + boolean found = true; + while (!isQuiescent() && (ws = workQueues) != null && + (m = ws.length - 1) >= 0) { + if (!found) { + if ((System.nanoTime() - startTime) > nanos) + return false; + Thread.yield(); // cannot block + } + found = false; + for (int j = (m + 1) << 2; j >= 0; --j) { + ForkJoinTask<?> t; WorkQueue q; int b; + if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) { + found = true; + if ((t = q.pollAt(b)) != null) { + if (q.base - q.top < 0) + signalWork(q); + t.doExec(); + } + break; + } + } + } + return true; + } + + /** + * Waits and/or attempts to assist performing tasks indefinitely + * until the {@link #commonPool()} {@link #isQuiescent}. + */ + static void quiesceCommonPool() { + common.awaitQuiescence(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + } + + /** * Interface for extending managed parallelism for tasks running * in {@link ForkJoinPool}s. * @@ -3175,9 +3188,9 @@ * not necessary. Method {@code block} blocks the current thread * if necessary (perhaps internally invoking {@code isReleasable} * before actually blocking). These actions are performed by any - * thread invoking {@link ForkJoinPool#managedBlock}. The - * unusual methods in this API accommodate synchronizers that may, - * but don't usually, block for long periods. Similarly, they + * thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}. + * The unusual methods in this API accommodate synchronizers that + * may, but don't usually, block for long periods. Similarly, they * allow more efficient internal handling of cases in which * additional workers may be, but usually are not, needed to * ensure sufficient parallelism. Toward this end, @@ -3235,6 +3248,7 @@ /** * Returns {@code true} if blocking is unnecessary. + * @return {@code true} if blocking is unnecessary */ boolean isReleasable(); } @@ -3319,7 +3333,7 @@ private static final long QLOCK; static { - int s; // initialize field offsets for CAS etc + // initialize field offsets for CAS etc try { U = sun.misc.Unsafe.getUnsafe(); Class<?> k = ForkJoinPool.class; @@ -3339,54 +3353,58 @@ (wk.getDeclaredField("qlock")); Class<?> ak = ForkJoinTask[].class; ABASE = U.arrayBaseOffset(ak); - s = U.arrayIndexScale(ak); - ASHIFT = 31 - Integer.numberOfLeadingZeros(s); + int scale = U.arrayIndexScale(ak); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); } catch (Exception e) { throw new Error(e); } - if ((s & (s-1)) != 0) - throw new Error("data type scale not a power of two"); - submitters = new ThreadLocal<Submitter>(); - ForkJoinWorkerThreadFactory fac = defaultForkJoinWorkerThreadFactory = + defaultForkJoinWorkerThreadFactory = new DefaultForkJoinWorkerThreadFactory(); modifyThreadPermission = new RuntimePermission("modifyThread"); - /* - * Establish common pool parameters. For extra caution, - * computations to set up common pool state are here; the - * constructor just assigns these values to fields. - */ + common = java.security.AccessController.doPrivileged + (new java.security.PrivilegedAction<ForkJoinPool>() { + public ForkJoinPool run() { return makeCommonPool(); }}); + int par = common.config; // report 1 even if threads disabled + commonParallelism = par > 0 ? par : 1; + } - int par = 0; - Thread.UncaughtExceptionHandler handler = null; - try { // TBD: limit or report ignored exceptions? + /** + * Creates and returns the common pool, respecting user settings + * specified via system properties. + */ + private static ForkJoinPool makeCommonPool() { + int parallelism = -1; + ForkJoinWorkerThreadFactory factory + = defaultForkJoinWorkerThreadFactory; + UncaughtExceptionHandler handler = null; + try { // ignore exceptions in accesing/parsing properties String pp = System.getProperty ("java.util.concurrent.ForkJoinPool.common.parallelism"); - String hp = System.getProperty - ("java.util.concurrent.ForkJoinPool.common.exceptionHandler"); String fp = System.getProperty ("java.util.concurrent.ForkJoinPool.common.threadFactory"); + String hp = System.getProperty + ("java.util.concurrent.ForkJoinPool.common.exceptionHandler"); + if (pp != null) + parallelism = Integer.parseInt(pp); if (fp != null) - fac = ((ForkJoinWorkerThreadFactory)ClassLoader. - getSystemClassLoader().loadClass(fp).newInstance()); + factory = ((ForkJoinWorkerThreadFactory)ClassLoader. + getSystemClassLoader().loadClass(fp).newInstance()); if (hp != null) - handler = ((Thread.UncaughtExceptionHandler)ClassLoader. + handler = ((UncaughtExceptionHandler)ClassLoader. getSystemClassLoader().loadClass(hp).newInstance()); - if (pp != null) - par = Integer.parseInt(pp); } catch (Exception ignore) { } - if (par <= 0) - par = Runtime.getRuntime().availableProcessors(); - if (par > MAX_CAP) - par = MAX_CAP; - commonPoolParallelism = par; - long np = (long)(-par); // precompute initial ctl value - long ct = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK); - - commonPool = new ForkJoinPool(par, ct, fac, handler); + if (parallelism < 0) + parallelism = Runtime.getRuntime().availableProcessors(); + if (parallelism > MAX_CAP) + parallelism = MAX_CAP; + return new ForkJoinPool(parallelism, factory, handler, false, + "ForkJoinPool.commonPool-worker-"); } }
--- a/src/share/classes/java/util/concurrent/ForkJoinTask.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/util/concurrent/ForkJoinTask.java Sat Mar 02 11:06:58 2013 -0400 @@ -464,7 +464,7 @@ } /** - * Records exception and possibly propagates + * Records exception and possibly propagates. * * @return status on exit */ @@ -497,7 +497,7 @@ } /** - * Removes exception node and clears status + * Removes exception node and clears status. */ private void clearExceptionalCompletion() { int h = System.identityHashCode(this); @@ -635,7 +635,7 @@ throw (Error)ex; if (ex instanceof RuntimeException) throw (RuntimeException)ex; - throw uncheckedThrowable(ex, RuntimeException.class); + ForkJoinTask.<RuntimeException>uncheckedThrow(ex); } } @@ -645,8 +645,9 @@ * unchecked exceptions */ @SuppressWarnings("unchecked") static <T extends Throwable> - T uncheckedThrowable(final Throwable t, final Class<T> c) { - return (T)t; // rely on vacuous cast + void uncheckedThrow(Throwable t) throws T { + if (t != null) + throw (T)t; // rely on vacuous cast } /** @@ -681,7 +682,7 @@ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ((ForkJoinWorkerThread)t).workQueue.push(this); else - ForkJoinPool.commonPool.externalPush(this); + ForkJoinPool.common.externalPush(this); return this; } @@ -857,7 +858,7 @@ * <p>This method is designed to be invoked by <em>other</em> * tasks. To terminate the current task, you can just return or * throw an unchecked exception from its computation method, or - * invoke {@link #completeExceptionally}. + * invoke {@link #completeExceptionally(Throwable)}. * * @param mayInterruptIfRunning this value has no effect in the * default implementation because interrupts are not used to @@ -1007,8 +1008,9 @@ if (Thread.interrupted()) throw new InterruptedException(); // Messy in part because we measure in nanosecs, but wait in millisecs - int s; long ns, ms; - if ((s = status) >= 0 && (ns = unit.toNanos(timeout)) > 0L) { + int s; long ms; + long ns = unit.toNanos(timeout); + if ((s = status) >= 0 && ns > 0L) { long deadline = System.nanoTime() + ns; ForkJoinPool p = null; ForkJoinPool.WorkQueue w = null; @@ -1104,7 +1106,7 @@ wt.pool.helpQuiescePool(wt.workQueue); } else - ForkJoinPool.externalHelpQuiescePool(); + ForkJoinPool.quiesceCommonPool(); } /** @@ -1391,6 +1393,24 @@ } /** + * Adaptor for Runnables in which failure forces worker exception + */ + static final class RunnableExecuteAction extends ForkJoinTask<Void> { + final Runnable runnable; + RunnableExecuteAction(Runnable runnable) { + if (runnable == null) throw new NullPointerException(); + this.runnable = runnable; + } + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) { } + public final boolean exec() { runnable.run(); return true; } + void internalPropagateException(Throwable ex) { + rethrow(ex); // rethrow outside exec() catches. + } + private static final long serialVersionUID = 5232453952276885070L; + } + + /** * Adaptor for Callables */ static final class AdaptedCallable<T> extends ForkJoinTask<T>
--- a/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Sat Mar 02 11:06:58 2013 -0400 @@ -83,22 +83,20 @@ * programs. * * Because this class is in a different package than class Thread, - * field access methods must use Unsafe to bypass access control - * rules. The base functionality of Random methods is - * conveniently isolated in method next(bits), that just reads and - * writes the Thread field rather than its own field. However, to - * conform to the requirements of the Random constructor, during - * construction, the common static ThreadLocalRandom must maintain - * initialization and value fields, mainly for the sake of - * disabling user calls to setSeed while still allowing a call - * from constructor. For serialization compatibility, these - * fields are left with the same declarations as used in the - * previous ThreadLocal-based version of this class, that used - * them differently. Note that serialization is completely - * unnecessary because there is only a static singleton. But these - * mechanics still ensure compatibility across versions. + * field access methods use Unsafe to bypass access control rules. + * The base functionality of Random methods is conveniently + * isolated in method next(bits), that just reads and writes the + * Thread field rather than its own field. However, to conform to + * the requirements of the Random superclass constructor, the + * common static ThreadLocalRandom maintains an "initialized" + * field for the sake of rejecting user calls to setSeed while + * still allowing a call from constructor. Note that + * serialization is completely unnecessary because there is only a + * static singleton. But we generate a serial form containing + * "rnd" and "initialized" fields to ensure compatibility across + * versions. * - * Per-instance initialization is similar to that in the no-arg + * Per-thread initialization is similar to that in the no-arg * Random constructor, but we avoid correlation among not only * initial seeds of those created in different threads, but also * those created using class Random itself; while at the same time @@ -132,10 +130,11 @@ private static final ThreadLocal<Double> nextLocalGaussian = new ThreadLocal<Double>(); - /* - * Field used only during singleton initialization + /** + * Field used only during singleton initialization. + * True when constructor completes. */ - boolean initialized; // true when constructor completes + boolean initialized; /** Constructor used only for static singleton */ private ThreadLocalRandom() { @@ -184,7 +183,8 @@ * @throws UnsupportedOperationException always */ public void setSeed(long seed) { - if (initialized) // allow call from super() constructor + // only allow call from super() constructor + if (initialized) throw new UnsupportedOperationException(); } @@ -357,39 +357,29 @@ r ^= r >>> 17; r ^= r << 5; } - else if ((r = (int)UNSAFE.getLong(t, SEED)) == 0) - r = 1; // avoid zero + else { + localInit(); + if ((r = (int)UNSAFE.getLong(t, SEED)) == 0) + r = 1; // avoid zero + } UNSAFE.putInt(t, SECONDARY, r); return r; } - // Serialization support, maintains original persistent form. + // Serialization support private static final long serialVersionUID = -5851777807851030925L; /** * @serialField rnd long + * seed for random computations * @serialField initialized boolean - * @serialField pad0 long - * @serialField pad1 long - * @serialField pad2 long - * @serialField pad3 long - * @serialField pad4 long - * @serialField pad5 long - * @serialField pad6 long - * @serialField pad7 long + * always true */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("rnd", long.class), - new ObjectStreamField("initialized", boolean.class), - new ObjectStreamField("pad0", long.class), - new ObjectStreamField("pad1", long.class), - new ObjectStreamField("pad2", long.class), - new ObjectStreamField("pad3", long.class), - new ObjectStreamField("pad4", long.class), - new ObjectStreamField("pad5", long.class), - new ObjectStreamField("pad6", long.class), - new ObjectStreamField("pad7", long.class) }; + new ObjectStreamField("initialized", boolean.class) + }; /** * Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it). @@ -398,16 +388,8 @@ throws java.io.IOException { java.io.ObjectOutputStream.PutField fields = out.putFields(); - fields.put("rnd", 0L); + fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED)); fields.put("initialized", true); - fields.put("pad0", 0L); - fields.put("pad1", 0L); - fields.put("pad2", 0L); - fields.put("pad3", 0L); - fields.put("pad4", 0L); - fields.put("pad5", 0L); - fields.put("pad6", 0L); - fields.put("pad7", 0L); out.writeFields(); }
--- a/src/share/classes/java/util/function/BinaryOperator.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/util/function/BinaryOperator.java Sat Mar 02 11:06:58 2013 -0400 @@ -30,7 +30,7 @@ * * @param <T> the type of operands to {@code apply} and of the result * - * @see BiFunction. + * @see BiFunction * @since 1.8 */ @FunctionalInterface
--- a/src/share/classes/java/util/function/ToDoubleBiFunction.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/java/util/function/ToDoubleBiFunction.java Sat Mar 02 11:06:58 2013 -0400 @@ -33,7 +33,7 @@ * @param <U> the type of the second argument to the {@code applyAsDouble} * operation. * - * @see BiFunction. + * @see BiFunction * @since 1.8 */ @FunctionalInterface
--- a/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Sat Mar 02 11:06:58 2013 -0400 @@ -86,11 +86,11 @@ Class<? extends Annotation> containerClass = containerInstance.annotationType(); AnnotationType annoType = AnnotationType.getInstance(containerClass); if (annoType == null) - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); + throw new AnnotationFormatError(containerInstance + " is an invalid container for repeating annotations"); Method m = annoType.members().get("value"); if (m == null) - throw new InvalidContainerAnnotationError(containerInstance + + throw new AnnotationFormatError(containerInstance + " is an invalid container for repeating annotations"); m.setAccessible(true); @@ -103,11 +103,9 @@ IllegalArgumentException | // parameters doesn't match InvocationTargetException | // the value method threw an exception ClassCastException e) { // well, a cast failed ... - throw new InvalidContainerAnnotationError( + throw new AnnotationFormatError( containerInstance + " is an invalid container for repeating annotations", - e, - containerInstance, - null); + e); } } @@ -129,12 +127,10 @@ return l; } catch (ClassCastException | NullPointerException e) { - throw new InvalidContainerAnnotationError( + throw new AnnotationFormatError( String.format("%s is an invalid container for repeating annotations of type: %s", containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + e); } } }
--- a/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, 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 @@ -212,12 +212,6 @@ * generated. */ public int getIvLength() { - // TLS v1.1 or later uses an explicit IV to protect against - // the CBC attacks. - if (majorVersion >= 0x03 && minorVersion >= 0x02) { - return 0; - } - return ivLength; }
--- a/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,9 +58,8 @@ * <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey, * null, null, null, null)</code>. * - * @param clientMacKey the client MAC key - * @param serverMacKey the server MAC key - * @throws NullPointerException if clientMacKey or serverMacKey is null + * @param clientMacKey the client MAC key (or null) + * @param serverMacKey the server MAC key (or null) */ public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey) { this(clientMacKey, serverMacKey, null, null, null, null); @@ -73,11 +72,10 @@ * <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey, * clientCipherKey, serverCipherKey, null, null)</code>. * - * @param clientMacKey the client MAC key - * @param serverMacKey the server MAC key + * @param clientMacKey the client MAC key (or null) + * @param serverMacKey the server MAC key (or null) * @param clientCipherKey the client cipher key (or null) * @param serverCipherKey the server cipher key (or null) - * @throws NullPointerException if clientMacKey or serverMacKey is null */ public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey, SecretKey clientCipherKey, SecretKey serverCipherKey) { @@ -90,21 +88,17 @@ * keys, client and server cipher keys, and client and server * initialization vectors. * - * @param clientMacKey the client MAC key - * @param serverMacKey the server MAC key + * @param clientMacKey the client MAC key (or null) + * @param serverMacKey the server MAC key (or null) * @param clientCipherKey the client cipher key (or null) * @param clientIv the client initialization vector (or null) * @param serverCipherKey the server cipher key (or null) * @param serverIv the server initialization vector (or null) - * - * @throws NullPointerException if clientMacKey or serverMacKey is null */ public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey, SecretKey clientCipherKey, IvParameterSpec clientIv, SecretKey serverCipherKey, IvParameterSpec serverIv) { - if ((clientMacKey == null) || (serverMacKey == null)) { - throw new NullPointerException("MAC keys must not be null"); - } + this.clientMacKey = clientMacKey; this.serverMacKey = serverMacKey; this.clientCipherKey = clientCipherKey; @@ -143,7 +137,7 @@ /** * Returns the client MAC key. * - * @return the client MAC key. + * @return the client MAC key (or null). */ public SecretKey getClientMacKey() { return clientMacKey; @@ -152,7 +146,7 @@ /** * Return the server MAC key. * - * @return the server MAC key. + * @return the server MAC key (or null). */ public SecretKey getServerMacKey() { return serverMacKey;
--- a/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, 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 @@ -168,10 +168,22 @@ // Note that the MAC keys do not inherit all attributes from the // template, but they do inherit the sensitive/extractable/token // flags, which is all P11Key cares about. - SecretKey clientMacKey = P11Key.secretKey + SecretKey clientMacKey, serverMacKey; + + // The MAC size may be zero for GCM mode. + // + // PKCS11 does not support GCM mode as the author made the comment, + // so the macBits is unlikely to be zero. It's only a place holder. + if (macBits != 0) { + clientMacKey = P11Key.secretKey (session, out.hClientMacSecret, "MAC", macBits, attributes); - SecretKey serverMacKey = P11Key.secretKey + serverMacKey = P11Key.secretKey (session, out.hServerMacSecret, "MAC", macBits, attributes); + } else { + clientMacKey = null; + serverMacKey = null; + } + SecretKey clientCipherKey, serverCipherKey; if (keyBits != 0) { clientCipherKey = P11Key.secretKey(session, out.hClientKey,
--- a/src/share/classes/sun/security/provider/PolicyFile.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/provider/PolicyFile.java Sat Mar 02 11:06:58 2013 -0400 @@ -1336,10 +1336,9 @@ if (pppe.isWildcardName()) { // a wildcard name matches any principal with the same class - for (Principal p : principals) { - if (pppe.principalClass.equals(p.getClass().getName())) { - continue; - } + if (wildcardPrincipalNameImplies(pppe.principalClass, + principals)) { + continue; } if (debug != null) { debug.println("evaluation (principal name wildcard) failed"); @@ -1414,6 +1413,21 @@ addPerms(perms, principals, entry); } + /** + * Returns true if the array of principals contains at least one + * principal of the specified class. + */ + private static boolean wildcardPrincipalNameImplies(String principalClass, + Principal[] principals) + { + for (Principal p : principals) { + if (principalClass.equals(p.getClass().getName())) { + return true; + } + } + return false; + } + private void addPerms(Permissions perms, Principal[] accPs, PolicyEntry entry) {
--- a/src/share/classes/sun/security/provider/certpath/OCSP.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/provider/certpath/OCSP.java Sat Mar 02 11:06:58 2013 -0400 @@ -89,7 +89,7 @@ new GetIntegerAction("com.sun.security.ocsp.timeout", DEFAULT_CONNECT_TIMEOUT)); if (tmp < 0) { - tmp = DEFAULT_CONNECT_TIMEOUT; + return DEFAULT_CONNECT_TIMEOUT; } // Convert to milliseconds, as the system property will be // specified in seconds
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/ssl/Authenticator.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2012, 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.ssl; + +import java.util.Arrays; + +/** + * This class represents an SSL/TLS message authentication token, + * which encapsulates a sequence number and ensures that attempts to + * delete or reorder messages can be detected. + * + * Each SSL/TLS connection state contains a sequence number, which + * is maintained separately for read and write states. The sequence + * number MUST be set to zero whenever a connection state is made the + * active state. Sequence numbers are of type uint64 and may not + * exceed 2^64-1. Sequence numbers do not wrap. If a SSL/TLS + * implementation would need to wrap a sequence number, it must + * renegotiate instead. A sequence number is incremented after each + * record: specifically, the first record transmitted under a + * particular connection state MUST use sequence number 0. + */ +class Authenticator { + + // byte array containing the additional authentication information for + // each record + private final byte[] block; + + // the block size of SSL v3.0: + // sequence number + record type + + record length + private static final int BLOCK_SIZE_SSL = 8 + 1 + 2; + + // the block size of TLS v1.0 and later: + // sequence number + record type + protocol version + record length + private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2; + + /** + * Default construct, no message authentication token is initialized. + * + * Note that this construct can only be called for null MAC + */ + Authenticator() { + block = new byte[0]; + } + + /** + * Constructs the message authentication token for the specified + * SSL/TLS protocol. + */ + Authenticator(ProtocolVersion protocolVersion) { + if (protocolVersion.v >= ProtocolVersion.TLS10.v) { + block = new byte[BLOCK_SIZE_TLS]; + block[9] = protocolVersion.major; + block[10] = protocolVersion.minor; + } else { + block = new byte[BLOCK_SIZE_SSL]; + } + } + + /** + * Checks whether the sequence number is close to wrap. + * + * Sequence numbers are of type uint64 and may not exceed 2^64-1. + * Sequence numbers do not wrap. When the sequence number is near + * to wrap, we need to close the connection immediately. + * + * @return true if the sequence number is close to wrap + */ + final boolean seqNumOverflow() { + /* + * Conservatively, we don't allow more records to be generated + * when there are only 2^8 sequence numbers left. + */ + return (block.length != 0 && + block[0] == (byte)0xFF && block[1] == (byte)0xFF && + block[2] == (byte)0xFF && block[3] == (byte)0xFF && + block[4] == (byte)0xFF && block[5] == (byte)0xFF && + block[6] == (byte)0xFF); + } + + /** + * Checks whether the sequence number close to renew. + * + * Sequence numbers are of type uint64 and may not exceed 2^64-1. + * Sequence numbers do not wrap. If a TLS + * implementation would need to wrap a sequence number, it must + * renegotiate instead. + * + * @return true if the sequence number is huge enough to renew + */ + final boolean seqNumIsHuge() { + /* + * Conservatively, we should ask for renegotiation when there are + * only 2^48 sequence numbers left. + */ + return (block.length != 0 && + block[0] == (byte)0xFF && block[1] == (byte)0xFF); + } + + /** + * Gets the current sequence number. + * + * @return the byte array of the current sequence number + */ + final byte[] sequenceNumber() { + return Arrays.copyOf(block, 8); + } + + /** + * Acquires the current message authentication information with the + * specified record type and fragment length, and then increases the + * sequence number. + * + * @param type the record type + * @param length the fragment of the record + * @return the byte array of the current message authentication information + */ + final byte[] acquireAuthenticationBytes(byte type, int length) { + byte[] copy = block.clone(); + + if (block.length != 0) { + copy[8] = type; + copy[copy.length - 2] = (byte)(length >> 8); + copy[copy.length - 1] = (byte)(length); + + /* + * Increase the sequence number in the block array + * it is a 64-bit number stored in big-endian format + */ + int k = 7; + while ((k >= 0) && (++block[k] == 0)) { + k--; + } + } + + return copy; + } + +}
--- a/src/share/classes/sun/security/ssl/CipherBox.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/CipherBox.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, 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,15 +29,18 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Hashtable; +import java.util.Arrays; import java.security.*; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.GCMParameterSpec; import java.nio.*; import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.*; +import static sun.security.ssl.CipherSuite.CipherType.*; import sun.misc.HexDumpEncoder; @@ -102,19 +105,40 @@ private final Cipher cipher; /** - * Cipher blocksize, 0 for stream ciphers - */ - private int blockSize; - - /** * secure random */ private SecureRandom random; /** - * Is the cipher of CBC mode? + * fixed IV, the implicit nonce of AEAD cipher suite, only apply to + * AEAD cipher suites + */ + private final byte[] fixedIv; + + /** + * the key, reserved only for AEAD cipher initialization + */ + private final Key key; + + /** + * the operation mode, reserved for AEAD cipher initialization */ - private final boolean isCBCMode; + private final int mode; + + /** + * the authentication tag size, only apply to AEAD cipher suites + */ + private final int tagSize; + + /** + * the record IV length, only apply to AEAD cipher suites + */ + private final int recordIvSize; + + /** + * cipher type + */ + private final CipherType cipherType; /** * Fixed masks of various block size, as the initial decryption IVs @@ -132,7 +156,13 @@ private CipherBox() { this.protocolVersion = ProtocolVersion.DEFAULT; this.cipher = null; - this.isCBCMode = false; + this.cipherType = STREAM_CIPHER; + this.fixedIv = new byte[0]; + this.key = null; + this.mode = Cipher.ENCRYPT_MODE; // choose at random + this.random = null; + this.tagSize = 0; + this.recordIvSize = 0; } /** @@ -147,13 +177,13 @@ try { this.protocolVersion = protocolVersion; this.cipher = JsseJce.getCipher(bulkCipher.transformation); - int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; + this.mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; if (random == null) { random = JsseJce.getSecureRandom(); } this.random = random; - this.isCBCMode = bulkCipher.isCBCMode; + this.cipherType = bulkCipher.cipherType; /* * RFC 4346 recommends two algorithms used to generated the @@ -171,14 +201,40 @@ iv = getFixedMask(bulkCipher.ivSize); } - cipher.init(mode, key, iv, random); + if (cipherType == AEAD_CIPHER) { + // AEAD must completely initialize the cipher for each packet, + // and so we save initialization parameters for packet + // processing time. + + // Set the tag size for AEAD cipher + tagSize = bulkCipher.tagSize; + + // Reserve the key for AEAD cipher initialization + this.key = key; + + fixedIv = iv.getIV(); + if (fixedIv == null || + fixedIv.length != bulkCipher.fixedIvSize) { + throw new RuntimeException("Improper fixed IV for AEAD"); + } - // Do not call getBlockSize until after init() - // otherwise we would disrupt JCE delayed provider selection - blockSize = cipher.getBlockSize(); - // some providers implement getBlockSize() incorrectly - if (blockSize == 1) { - blockSize = 0; + // Set the record IV length for AEAD cipher + recordIvSize = bulkCipher.ivSize - bulkCipher.fixedIvSize; + + // DON'T initialize the cipher for AEAD! + } else { + // CBC only requires one initialization during its lifetime + // (future packets/IVs set the proper CBC state), so we can + // initialize now. + + // Zeroize the variables that only apply to AEAD cipher + this.tagSize = 0; + this.fixedIv = new byte[0]; + this.recordIvSize = 0; + this.key = null; + + // Initialize the cipher + cipher.init(mode, key, iv, random); } } catch (NoSuchAlgorithmException e) { throw e; @@ -235,26 +291,11 @@ } try { - if (blockSize != 0) { - // TLSv1.1 needs a IV block - if (protocolVersion.v >= ProtocolVersion.TLS11.v) { - // generate a random number - byte[] prefix = new byte[blockSize]; - random.nextBytes(prefix); - - // move forward the plaintext - System.arraycopy(buf, offset, - buf, offset + prefix.length, len); - - // prefix the plaintext - System.arraycopy(prefix, 0, - buf, offset, prefix.length); - - len += prefix.length; - } - + int blockSize = cipher.getBlockSize(); + if (cipherType == BLOCK_CIPHER) { len = addPadding(buf, offset, len, blockSize); } + if (debug != null && Debug.isOn("plaintext")) { try { HexDumpEncoder hd = new HexDumpEncoder(); @@ -267,14 +308,28 @@ System.out); } catch (IOException e) { } } - int newLen = cipher.update(buf, offset, len, buf, offset); - if (newLen != len) { - // catch BouncyCastle buffering error - throw new RuntimeException("Cipher buffering error " + - "in JCE provider " + cipher.getProvider().getName()); + + + if (cipherType == AEAD_CIPHER) { + try { + return cipher.doFinal(buf, offset, len, buf, offset); + } catch (IllegalBlockSizeException | BadPaddingException ibe) { + // unlikely to happen + throw new RuntimeException( + "Cipher error in AEAD mode in JCE provider " + + cipher.getProvider().getName(), ibe); + } + } else { + int newLen = cipher.update(buf, offset, len, buf, offset); + if (newLen != len) { + // catch BouncyCastle buffering error + throw new RuntimeException("Cipher buffering error " + + "in JCE provider " + cipher.getProvider().getName()); + } + return newLen; } - return newLen; } catch (ShortBufferException e) { + // unlikely to happen, we should have enough buffer space here throw new ArrayIndexOutOfBoundsException(e.toString()); } } @@ -288,7 +343,7 @@ * set to last position padded/encrypted. The limit may have changed * because of the added padding bytes. */ - int encrypt(ByteBuffer bb) { + int encrypt(ByteBuffer bb, int outLimit) { int len = bb.remaining(); @@ -297,66 +352,71 @@ return len; } - try { - int pos = bb.position(); + int pos = bb.position(); - if (blockSize != 0) { - // TLSv1.1 needs a IV block - if (protocolVersion.v >= ProtocolVersion.TLS11.v) { - // generate a random number - byte[] prefix = new byte[blockSize]; - random.nextBytes(prefix); + int blockSize = cipher.getBlockSize(); + if (cipherType == BLOCK_CIPHER) { + // addPadding adjusts pos/limit + len = addPadding(bb, blockSize); + bb.position(pos); + } - // move forward the plaintext - byte[] buf = null; - int limit = bb.limit(); - if (bb.hasArray()) { - int arrayOffset = bb.arrayOffset(); - buf = bb.array(); - System.arraycopy(buf, arrayOffset + pos, - buf, arrayOffset + pos + prefix.length, - limit - pos); - bb.limit(limit + prefix.length); - } else { - buf = new byte[limit - pos]; - bb.get(buf, 0, limit - pos); - bb.position(pos + prefix.length); - bb.limit(limit + prefix.length); - bb.put(buf); - } - bb.position(pos); + if (debug != null && Debug.isOn("plaintext")) { + try { + HexDumpEncoder hd = new HexDumpEncoder(); + + System.out.println( + "Padded plaintext before ENCRYPTION: len = " + + len); + hd.encodeBuffer(bb.duplicate(), System.out); + + } catch (IOException e) { } + } - // prefix the plaintext - bb.put(prefix); - bb.position(pos); + /* + * Encrypt "in-place". This does not add its own padding. + */ + ByteBuffer dup = bb.duplicate(); + if (cipherType == AEAD_CIPHER) { + try { + int outputSize = cipher.getOutputSize(dup.remaining()); + if (outputSize > bb.remaining()) { + // need to expand the limit of the output buffer for + // the authentication tag. + // + // DON'T worry about the buffer's capacity, we have + // reserved space for the authentication tag. + if (outLimit < pos + outputSize) { + // unlikely to happen + throw new ShortBufferException( + "need more space in output buffer"); + } + bb.limit(pos + outputSize); } - - // addPadding adjusts pos/limit - len = addPadding(bb, blockSize); - bb.position(pos); + int newLen = cipher.doFinal(dup, bb); + if (newLen != outputSize) { + throw new RuntimeException( + "Cipher buffering error in JCE provider " + + cipher.getProvider().getName()); + } + return newLen; + } catch (IllegalBlockSizeException | + BadPaddingException | ShortBufferException ibse) { + // unlikely to happen + throw new RuntimeException( + "Cipher error in AEAD mode in JCE provider " + + cipher.getProvider().getName(), ibse); } - if (debug != null && Debug.isOn("plaintext")) { - try { - HexDumpEncoder hd = new HexDumpEncoder(); - - System.out.println( - "Padded plaintext before ENCRYPTION: len = " - + len); - hd.encodeBuffer(bb, System.out); - - } catch (IOException e) { } - /* - * reset back to beginning - */ - bb.position(pos); + } else { + int newLen; + try { + newLen = cipher.update(dup, bb); + } catch (ShortBufferException sbe) { + // unlikely to happen + throw new RuntimeException("Cipher buffering error " + + "in JCE provider " + cipher.getProvider().getName()); } - /* - * Encrypt "in-place". This does not add its own padding. - */ - ByteBuffer dup = bb.duplicate(); - int newLen = cipher.update(dup, bb); - if (bb.position() != dup.position()) { throw new RuntimeException("bytebuffer padding error"); } @@ -367,10 +427,6 @@ "in JCE provider " + cipher.getProvider().getName()); } return newLen; - } catch (ShortBufferException e) { - RuntimeException exc = new RuntimeException(e.toString()); - exc.initCause(e); - throw exc; } } @@ -398,11 +454,23 @@ } try { - int newLen = cipher.update(buf, offset, len, buf, offset); - if (newLen != len) { - // catch BouncyCastle buffering error - throw new RuntimeException("Cipher buffering error " + - "in JCE provider " + cipher.getProvider().getName()); + int newLen; + if (cipherType == AEAD_CIPHER) { + try { + newLen = cipher.doFinal(buf, offset, len, buf, offset); + } catch (IllegalBlockSizeException ibse) { + // unlikely to happen + throw new RuntimeException( + "Cipher error in AEAD mode in JCE provider " + + cipher.getProvider().getName(), ibse); + } + } else { + newLen = cipher.update(buf, offset, len, buf, offset); + if (newLen != len) { + // catch BouncyCastle buffering error + throw new RuntimeException("Cipher buffering error " + + "in JCE provider " + cipher.getProvider().getName()); + } } if (debug != null && Debug.isOn("plaintext")) { try { @@ -416,7 +484,9 @@ System.out); } catch (IOException e) { } } - if (blockSize != 0) { + + if (cipherType == BLOCK_CIPHER) { + int blockSize = cipher.getBlockSize(); newLen = removePadding(buf, offset, newLen, blockSize, protocolVersion); @@ -424,16 +494,11 @@ if (newLen < blockSize) { throw new BadPaddingException("invalid explicit IV"); } - - // discards the first cipher block, the IV component. - System.arraycopy(buf, offset + blockSize, - buf, offset, newLen - blockSize); - - newLen -= blockSize; } } return newLen; } catch (ShortBufferException e) { + // unlikely to happen, we should have enough buffer space here throw new ArrayIndexOutOfBoundsException(e.toString()); } } @@ -463,15 +528,29 @@ */ int pos = bb.position(); ByteBuffer dup = bb.duplicate(); - int newLen = cipher.update(dup, bb); - if (newLen != len) { - // catch BouncyCastle buffering error - throw new RuntimeException("Cipher buffering error " + - "in JCE provider " + cipher.getProvider().getName()); + int newLen; + if (cipherType == AEAD_CIPHER) { + try { + newLen = cipher.doFinal(dup, bb); + } catch (IllegalBlockSizeException ibse) { + // unlikely to happen + throw new RuntimeException( + "Cipher error in AEAD mode \"" + ibse.getMessage() + + " \"in JCE provider " + cipher.getProvider().getName()); + } + } else { + newLen = cipher.update(dup, bb); + if (newLen != len) { + // catch BouncyCastle buffering error + throw new RuntimeException("Cipher buffering error " + + "in JCE provider " + cipher.getProvider().getName()); + } } + // reset the limit to the end of the decryted data + bb.limit(pos + newLen); + if (debug != null && Debug.isOn("plaintext")) { - bb.position(pos); try { HexDumpEncoder hd = new HexDumpEncoder(); @@ -479,50 +558,33 @@ "Padded plaintext after DECRYPTION: len = " + newLen); - hd.encodeBuffer(bb, System.out); + hd.encodeBuffer( + (ByteBuffer)bb.duplicate().position(pos), System.out); } catch (IOException e) { } } /* * Remove the block padding. */ - if (blockSize != 0) { + if (cipherType == BLOCK_CIPHER) { + int blockSize = cipher.getBlockSize(); bb.position(pos); newLen = removePadding(bb, blockSize, protocolVersion); + // check the explicit IV of TLS v1.1 or later if (protocolVersion.v >= ProtocolVersion.TLS11.v) { if (newLen < blockSize) { throw new BadPaddingException("invalid explicit IV"); } - // discards the first cipher block, the IV component. - byte[] buf = null; - int limit = bb.limit(); - if (bb.hasArray()) { - int arrayOffset = bb.arrayOffset(); - buf = bb.array(); - System.arraycopy(buf, arrayOffset + pos + blockSize, - buf, arrayOffset + pos, limit - pos - blockSize); - bb.limit(limit - blockSize); - } else { - buf = new byte[limit - pos - blockSize]; - bb.position(pos + blockSize); - bb.get(buf); - bb.position(pos); - bb.put(buf); - bb.limit(limit - blockSize); - } - // reset the position to the end of the decrypted data - limit = bb.limit(); - bb.position(limit); + bb.position(bb.limit()); } } return newLen; } catch (ShortBufferException e) { - RuntimeException exc = new RuntimeException(e.toString()); - exc.initCause(e); - throw exc; + // unlikely to happen, we should have enough buffer space here + throw new ArrayIndexOutOfBoundsException(e.toString()); } } @@ -695,8 +757,8 @@ // ignore return value. cipher.doFinal(); } - } catch (GeneralSecurityException e) { - // swallow for now. + } catch (Exception e) { + // swallow all types of exceptions. } } @@ -706,6 +768,234 @@ * @return true if the cipher use CBC mode, false otherwise. */ boolean isCBCMode() { - return isCBCMode; + return cipherType == BLOCK_CIPHER; + } + + /* + * Does the cipher use AEAD mode? + * + * @return true if the cipher use AEAD mode, false otherwise. + */ + boolean isAEADMode() { + return cipherType == AEAD_CIPHER; + } + + /* + * Is the cipher null? + * + * @return true if the cipher is null, false otherwise. + */ + boolean isNullCipher() { + return cipher == null; + } + + /* + * Gets the explicit nonce/IV size of the cipher. + * + * The returned value is the SecurityParameters.record_iv_length in + * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the + * size of explicit nonce for AEAD mode. + * + * @return the explicit nonce size of the cipher. + */ + int getExplicitNonceSize() { + switch (cipherType) { + case BLOCK_CIPHER: + // For block ciphers, the explicit IV length is of length + // SecurityParameters.record_iv_length, which is equal to + // the SecurityParameters.block_size. + if (protocolVersion.v >= ProtocolVersion.TLS11.v) { + return cipher.getBlockSize(); + } + break; + case AEAD_CIPHER: + return recordIvSize; + // It is also the length of sequence number, which is + // used as the nonce_explicit for AEAD cipher suites. + } + + return 0; + } + + /* + * Applies the explicit nonce/IV to this cipher. This method is used to + * decrypt an SSL/TLS input record. + * + * The returned value is the SecurityParameters.record_iv_length in + * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the + * size of explicit nonce for AEAD mode. + * + * @param authenticator the authenticator to get the additional + * authentication data + * @param contentType the content type of the input record + * @param bb the byte buffer to get the explicit nonce from + * + * @return the explicit nonce size of the cipher. + */ + int applyExplicitNonce(Authenticator authenticator, byte contentType, + ByteBuffer bb) throws BadPaddingException { + switch (cipherType) { + case BLOCK_CIPHER: + // For block ciphers, the explicit IV length is of length + // SecurityParameters.record_iv_length, which is equal to + // the SecurityParameters.block_size. + if (protocolVersion.v >= ProtocolVersion.TLS11.v) { + return cipher.getBlockSize(); + } + break; + case AEAD_CIPHER: + if (bb.remaining() < (recordIvSize + tagSize)) { + throw new BadPaddingException( + "invalid AEAD cipher fragment"); + } + + // initialize the AEAD cipher for the unique IV + byte[] iv = Arrays.copyOf(fixedIv, + fixedIv.length + recordIvSize); + bb.get(iv, fixedIv.length, recordIvSize); + bb.position(bb.position() - recordIvSize); + GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); + try { + cipher.init(mode, key, spec, random); + } catch (InvalidKeyException | + InvalidAlgorithmParameterException ikae) { + // unlikely to happen + throw new RuntimeException( + "invalid key or spec in GCM mode", ikae); + } + + // update the additional authentication data + byte[] aad = authenticator.acquireAuthenticationBytes( + contentType, bb.remaining() - recordIvSize - tagSize); + cipher.updateAAD(aad); + + return recordIvSize; + // It is also the length of sequence number, which is + // used as the nonce_explicit for AEAD cipher suites. + } + + return 0; + } + + /* + * Applies the explicit nonce/IV to this cipher. This method is used to + * decrypt an SSL/TLS input record. + * + * The returned value is the SecurityParameters.record_iv_length in + * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the + * size of explicit nonce for AEAD mode. + * + * @param authenticator the authenticator to get the additional + * authentication data + * @param contentType the content type of the input record + * @param buf the byte array to get the explicit nonce from + * @param offset the offset of the byte buffer + * @param cipheredLength the ciphered fragment length of the output + * record, it is the TLSCiphertext.length in RFC 4346/5246. + * + * @return the explicit nonce size of the cipher. + */ + int applyExplicitNonce(Authenticator authenticator, + byte contentType, byte[] buf, int offset, + int cipheredLength) throws BadPaddingException { + + ByteBuffer bb = ByteBuffer.wrap(buf, offset, cipheredLength); + + return applyExplicitNonce(authenticator, contentType, bb); + } + + /* + * Creates the explicit nonce/IV to this cipher. This method is used to + * encrypt an SSL/TLS output record. + * + * The size of the returned array is the SecurityParameters.record_iv_length + * in RFC 4346/5246. It is the size of explicit IV for CBC mode, and the + * size of explicit nonce for AEAD mode. + * + * @param authenticator the authenticator to get the additional + * authentication data + * @param contentType the content type of the input record + * @param fragmentLength the fragment length of the output record, it is + * the TLSCompressed.length in RFC 4346/5246. + * + * @return the explicit nonce of the cipher. + */ + byte[] createExplicitNonce(Authenticator authenticator, + byte contentType, int fragmentLength) { + + byte[] nonce = new byte[0]; + switch (cipherType) { + case BLOCK_CIPHER: + if (protocolVersion.v >= ProtocolVersion.TLS11.v) { + // For block ciphers, the explicit IV length is of length + // SecurityParameters.record_iv_length, which is equal to + // the SecurityParameters.block_size. + // + // Generate a random number as the explicit IV parameter. + nonce = new byte[cipher.getBlockSize()]; + random.nextBytes(nonce); + } + break; + case AEAD_CIPHER: + // To be unique and aware of overflow-wrap, sequence number + // is used as the nonce_explicit of AEAD cipher suites. + nonce = authenticator.sequenceNumber(); + + // initialize the AEAD cipher for the unique IV + byte[] iv = Arrays.copyOf(fixedIv, + fixedIv.length + nonce.length); + System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length); + GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); + try { + cipher.init(mode, key, spec, random); + } catch (InvalidKeyException | + InvalidAlgorithmParameterException ikae) { + // unlikely to happen + throw new RuntimeException( + "invalid key or spec in GCM mode", ikae); + } + + // update the additional authentication data + byte[] aad = authenticator.acquireAuthenticationBytes( + contentType, fragmentLength); + cipher.updateAAD(aad); + break; + } + + return nonce; + } + + /* + * Is this cipher available? + * + * This method can only be called by CipherSuite.BulkCipher.isAvailable() + * to test the availability of a cipher suites. Please DON'T use it in + * other places, otherwise, the behavior may be unexpected because we may + * initialize AEAD cipher improperly in the method. + */ + Boolean isAvailable() { + // We won't know whether a cipher for a particular key size is + // available until the cipher is successfully initialized. + // + // We do not initialize AEAD cipher in the constructor. Need to + // initialize the cipher to ensure that the AEAD mode for a + // particular key size is supported. + if (cipherType == AEAD_CIPHER) { + try { + Authenticator authenticator = + new Authenticator(protocolVersion); + byte[] nonce = authenticator.sequenceNumber(); + byte[] iv = Arrays.copyOf(fixedIv, + fixedIv.length + nonce.length); + System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length); + GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); + + cipher.init(mode, key, spec, random); + } catch (Exception e) { + return Boolean.FALSE; + } + } // Otherwise, we have initialized the cipher in the constructor. + + return Boolean.TRUE; } }
--- a/src/share/classes/sun/security/ssl/CipherSuite.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/CipherSuite.java Sat Mar 02 11:06:58 2013 -0400 @@ -33,12 +33,14 @@ import java.security.SecureRandom; import java.security.KeyManagementException; +import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import static sun.security.ssl.CipherSuite.KeyExchange.*; import static sun.security.ssl.CipherSuite.PRF.*; +import static sun.security.ssl.CipherSuite.CipherType.*; import static sun.security.ssl.JsseJce.*; /** @@ -135,7 +137,9 @@ this.keyExchange = keyExchange; this.cipher = cipher; this.exportable = cipher.exportable; - if (name.endsWith("_MD5")) { + if (cipher.cipherType == CipherType.AEAD_CIPHER) { + macAlg = M_NULL; + } else if (name.endsWith("_MD5")) { macAlg = M_MD5; } else if (name.endsWith("_SHA")) { macAlg = M_SHA; @@ -385,6 +389,12 @@ } } + static enum CipherType { + STREAM_CIPHER, // null or stream cipher + BLOCK_CIPHER, // block cipher in CBC mode + AEAD_CIPHER // AEAD cipher + } + /** * An SSL/TLS bulk cipher algorithm. One instance per combination of * cipher and key length. @@ -417,14 +427,26 @@ // for non-exportable ciphers, this is the same as keySize final int expandedKeySize; - // size of the IV (also block size) + // size of the IV final int ivSize; + // size of fixed IV + // + // record_iv_length = ivSize - fixedIvSize + final int fixedIvSize; + // exportable under 512/40 bit rules final boolean exportable; // Is the cipher algorithm of Cipher Block Chaining (CBC) mode? - final boolean isCBCMode; + final CipherType cipherType; + + // size of the authentication tag, only applicable to cipher suites in + // Galois Counter Mode (GCM) + // + // As far as we know, all supported GCM cipher suites use 128-bits + // authentication tags. + final int tagSize = 16; // The secure random used to detect the cipher availability. private final static SecureRandom secureRandom; @@ -437,32 +459,34 @@ } } - BulkCipher(String transformation, int keySize, - int expandedKeySize, int ivSize, boolean allowed) { + BulkCipher(String transformation, CipherType cipherType, int keySize, + int expandedKeySize, int ivSize, + int fixedIvSize, boolean allowed) { + this.transformation = transformation; String[] splits = transformation.split("/"); this.algorithm = splits[0]; - this.isCBCMode = - splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]); + this.cipherType = cipherType; this.description = this.algorithm + "/" + (keySize << 3); this.keySize = keySize; this.ivSize = ivSize; + this.fixedIvSize = fixedIvSize; this.allowed = allowed; this.expandedKeySize = expandedKeySize; this.exportable = true; } - BulkCipher(String transformation, int keySize, - int ivSize, boolean allowed) { + BulkCipher(String transformation, CipherType cipherType, int keySize, + int ivSize, int fixedIvSize, boolean allowed) { this.transformation = transformation; String[] splits = transformation.split("/"); this.algorithm = splits[0]; - this.isCBCMode = - splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]); + this.cipherType = cipherType; this.description = this.algorithm + "/" + (keySize << 3); this.keySize = keySize; this.ivSize = ivSize; + this.fixedIvSize = fixedIvSize; this.allowed = allowed; this.expandedKeySize = keySize; @@ -486,16 +510,20 @@ * Test if this bulk cipher is available. For use by CipherSuite. * * Currently all supported ciphers except AES are always available - * via the JSSE internal implementations. We also assume AES/128 - * is always available since it is shipped with the SunJCE provider. - * However, AES/256 is unavailable when the default JCE policy - * jurisdiction files are installed because of key length restrictions. + * via the JSSE internal implementations. We also assume AES/128 of + * CBC mode is always available since it is shipped with the SunJCE + * provider. However, AES/256 is unavailable when the default JCE + * policy jurisdiction files are installed because of key length + * restrictions, and AEAD is unavailable when the underlying providers + * do not support AEAD/GCM mode. */ boolean isAvailable() { if (allowed == false) { return false; } - if (this == B_AES_256) { + + if ((this == B_AES_256) || + (this.cipherType == CipherType.AEAD_CIPHER)) { return isAvailable(this); } @@ -513,19 +541,50 @@ private static synchronized boolean isAvailable(BulkCipher cipher) { Boolean b = availableCache.get(cipher); if (b == null) { - try { - SecretKey key = new SecretKeySpec - (new byte[cipher.expandedKeySize], cipher.algorithm); - IvParameterSpec iv = - new IvParameterSpec(new byte[cipher.ivSize]); - cipher.newCipher(ProtocolVersion.DEFAULT, + int keySizeInBits = cipher.keySize * 8; + if (keySizeInBits > 128) { // need the JCE unlimited + // strength jurisdiction policy + try { + if (Cipher.getMaxAllowedKeyLength( + cipher.transformation) < keySizeInBits) { + b = Boolean.FALSE; + } + } catch (Exception e) { + b = Boolean.FALSE; + } + } + + if (b == null) { + b = Boolean.FALSE; // may be reset to TRUE if + // the cipher is available + CipherBox temporary = null; + try { + SecretKey key = new SecretKeySpec( + new byte[cipher.expandedKeySize], + cipher.algorithm); + IvParameterSpec iv; + if (cipher.cipherType == CipherType.AEAD_CIPHER) { + iv = new IvParameterSpec( + new byte[cipher.fixedIvSize]); + } else { + iv = new IvParameterSpec(new byte[cipher.ivSize]); + } + temporary = cipher.newCipher( + ProtocolVersion.DEFAULT, key, iv, secureRandom, true); - b = Boolean.TRUE; - } catch (NoSuchAlgorithmException e) { - b = Boolean.FALSE; + b = temporary.isAvailable(); + } catch (NoSuchAlgorithmException e) { + // not available + } finally { + if (temporary != null) { + temporary.dispose(); + } + } } + availableCache.put(cipher, b); } + return b.booleanValue(); } @@ -573,27 +632,31 @@ // export strength ciphers final static BulkCipher B_NULL = - new BulkCipher("NULL", 0, 0, 0, true); + new BulkCipher("NULL", STREAM_CIPHER, 0, 0, 0, 0, true); final static BulkCipher B_RC4_40 = - new BulkCipher(CIPHER_RC4, 5, 16, 0, true); + new BulkCipher(CIPHER_RC4, STREAM_CIPHER, 5, 16, 0, 0, true); final static BulkCipher B_RC2_40 = - new BulkCipher("RC2", 5, 16, 8, false); + new BulkCipher("RC2", BLOCK_CIPHER, 5, 16, 8, 0, false); final static BulkCipher B_DES_40 = - new BulkCipher(CIPHER_DES, 5, 8, 8, true); + new BulkCipher(CIPHER_DES, BLOCK_CIPHER, 5, 8, 8, 0, true); // domestic strength ciphers final static BulkCipher B_RC4_128 = - new BulkCipher(CIPHER_RC4, 16, 0, true); + new BulkCipher(CIPHER_RC4, STREAM_CIPHER, 16, 0, 0, true); final static BulkCipher B_DES = - new BulkCipher(CIPHER_DES, 8, 8, true); + new BulkCipher(CIPHER_DES, BLOCK_CIPHER, 8, 8, 0, true); final static BulkCipher B_3DES = - new BulkCipher(CIPHER_3DES, 24, 8, true); + new BulkCipher(CIPHER_3DES, BLOCK_CIPHER, 24, 8, 0, true); final static BulkCipher B_IDEA = - new BulkCipher("IDEA", 16, 8, false); + new BulkCipher("IDEA", BLOCK_CIPHER, 16, 8, 0, false); final static BulkCipher B_AES_128 = - new BulkCipher(CIPHER_AES, 16, 16, true); + new BulkCipher(CIPHER_AES, BLOCK_CIPHER, 16, 16, 0, true); final static BulkCipher B_AES_256 = - new BulkCipher(CIPHER_AES, 32, 16, true); + new BulkCipher(CIPHER_AES, BLOCK_CIPHER, 32, 16, 0, true); + final static BulkCipher B_AES_128_GCM = + new BulkCipher(CIPHER_AES_GCM, AEAD_CIPHER, 16, 12, 4, true); + final static BulkCipher B_AES_256_GCM = + new BulkCipher(CIPHER_AES_GCM, AEAD_CIPHER, 32, 12, 4, true); // MACs final static MacAlg M_NULL = new MacAlg("NULL", 0); @@ -893,11 +956,12 @@ * Definition of the CipherSuites that are enabled by default. * They are listed in preference order, most preferred first, using * the following criteria: - * 1. Prefer the stronger buld cipher, in the order of AES_256, - * AES_128, RC-4, 3DES-EDE. - * 2. Prefer the stronger MAC algorithm, in the order of SHA384, + * 1. Prefer Suite B compliant cipher suites, see RFC6460. + * 2. Prefer the stronger bulk cipher, in the order of AES_256(GCM), + * AES_128(GCM), AES_256, AES_128, RC-4, 3DES-EDE. + * 3. Prefer the stronger MAC algorithm, in the order of SHA384, * SHA256, SHA, MD5. - * 3. Prefer the better performance of key exchange and digital + * 4. Prefer the better performance of key exchange and digital * signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA, * RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS. */ @@ -910,6 +974,16 @@ // ID Key Exchange Cipher A obs suprt PRF // ====== ============ ========= = === ===== ======== + + + // Placeholder for cipher suites in GCM mode. + // + // For better compatibility and interoperability, we decrease the + // priority of cipher suites in GCM mode for a while as GCM + // technologies mature in the industry. Eventually we'll move + // the GCM suites here. + + // AES_256(CBC) add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384); add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", @@ -940,6 +1014,7 @@ add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 0x0038, --p, K_DHE_DSS, B_AES_256, T); + // AES_128(CBC) add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256); add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", @@ -970,6 +1045,7 @@ add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 0x0032, --p, K_DHE_DSS, B_AES_128, T); + // RC-4 add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N); add("TLS_ECDHE_RSA_WITH_RC4_128_SHA", @@ -981,6 +1057,51 @@ add("TLS_ECDH_RSA_WITH_RC4_128_SHA", 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N); + // Cipher suites in GCM mode, see RFC 5288/5289. + // + // We may increase the priority of cipher suites in GCM mode when + // GCM technologies become mature in the industry. + + // Suite B compliant cipher suites, see RFC 6460. + // + // Note that, at present this provider is not Suite B compliant. The + // preference order of the GCM cipher suites does not follow the spec + // of RFC 6460. + add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + 0xc02c, --p, K_ECDHE_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384); + add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + 0xc02b, --p, K_ECDHE_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256); + + // AES_256(GCM) + add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + 0xc030, --p, K_ECDHE_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384); + add("TLS_RSA_WITH_AES_256_GCM_SHA384", + 0x009d, --p, K_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384); + add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", + 0xc02e, --p, K_ECDH_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384); + add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", + 0xc032, --p, K_ECDH_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384); + add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", + 0x009f, --p, K_DHE_RSA, B_AES_256_GCM, T, max, tls12, P_SHA384); + add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", + 0x00a3, --p, K_DHE_DSS, B_AES_256_GCM, T, max, tls12, P_SHA384); + + // AES_128(GCM) + add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + 0xc02f, --p, K_ECDHE_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256); + add("TLS_RSA_WITH_AES_128_GCM_SHA256", + 0x009c, --p, K_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256); + add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", + 0xc02d, --p, K_ECDH_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256); + add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", + 0xc031, --p, K_ECDH_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256); + add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", + 0x009e, --p, K_DHE_RSA, B_AES_128_GCM, T, max, tls12, P_SHA256); + add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", + 0x00a2, --p, K_DHE_DSS, B_AES_128_GCM, T, max, tls12, P_SHA256); + // End of cipher suites in GCM mode. + + // 3DES_EDE add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 0xC008, --p, K_ECDHE_ECDSA, B_3DES, T); add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", @@ -1024,17 +1145,22 @@ */ p = DEFAULT_SUITES_PRIORITY; + add("TLS_DH_anon_WITH_AES_256_GCM_SHA384", + 0x00a7, --p, K_DH_ANON, B_AES_256_GCM, N, max, tls12, P_SHA384); + add("TLS_DH_anon_WITH_AES_128_GCM_SHA256", + 0x00a6, --p, K_DH_ANON, B_AES_128_GCM, N, max, tls12, P_SHA256); + add("TLS_DH_anon_WITH_AES_256_CBC_SHA256", 0x006d, --p, K_DH_ANON, B_AES_256, N, max, tls12, P_SHA256); add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA", - 0xC019, --p, K_ECDH_ANON, B_AES_256, T); + 0xC019, --p, K_ECDH_ANON, B_AES_256, N); add("TLS_DH_anon_WITH_AES_256_CBC_SHA", 0x003a, --p, K_DH_ANON, B_AES_256, N); add("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x006c, --p, K_DH_ANON, B_AES_128, N, max, tls12, P_SHA256); add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA", - 0xC018, --p, K_ECDH_ANON, B_AES_128, T); + 0xC018, --p, K_ECDH_ANON, B_AES_128, N); add("TLS_DH_anon_WITH_AES_128_CBC_SHA", 0x0034, --p, K_DH_ANON, B_AES_128, N); @@ -1044,7 +1170,7 @@ 0x0018, --p, K_DH_ANON, B_RC4_128, N); add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", - 0xC017, --p, K_ECDH_ANON, B_3DES, T); + 0xC017, --p, K_ECDH_ANON, B_3DES, N); add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", 0x001b, --p, K_DH_ANON, B_3DES, N); @@ -1199,18 +1325,10 @@ add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069); // Unsupported cipher suites from RFC 5288 - add("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c); - add("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x009d); - add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x009e); - add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x009f); add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 0x00a0); add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0x00a1); - add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x00a2); - add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x00a3); add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 0x00a4); add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0x00a5); - add("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x00a6); - add("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x00a7); // Unsupported cipher suites from RFC 5487 add("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8); @@ -1269,16 +1387,6 @@ add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021); add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022); - // Unsupported cipher suites from RFC 5289 - add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b); - add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c); - add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d); - add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02e); - add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0xc02f); - add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030); - add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031); - add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032); - // Unsupported cipher suites from RFC 5489 add("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033); add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034);
--- a/src/share/classes/sun/security/ssl/EngineInputRecord.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/EngineInputRecord.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -178,71 +178,6 @@ } /* - * Verifies and removes the MAC value. Returns true if - * the MAC checks out OK. - * - * On entry: - * position = beginning of app/MAC data - * limit = end of MAC data. - * - * On return: - * position = beginning of app data - * limit = end of app data - */ - boolean checkMAC(MAC signer, ByteBuffer bb) { - if (internalData) { - return checkMAC(signer); - } - - int len = signer.MAClen(); - if (len == 0) { // no mac - return true; - } - - /* - * Grab the original limit - */ - int lim = bb.limit(); - - /* - * Delineate the area to apply a MAC on. - */ - int macData = lim - len; - bb.limit(macData); - - byte[] mac = signer.compute(contentType(), bb); - - if (len != mac.length) { - throw new RuntimeException("Internal MAC error"); - } - - /* - * Delineate the MAC values, position was already set - * by doing the compute above. - * - * We could zero the MAC area, but not much useful information - * there anyway. - */ - bb.position(macData); - bb.limit(lim); - - try { - for (int i = 0; i < len; i++) { - if (bb.get() != mac[i]) { // No BB.equals(byte []); ! - return false; - } - } - return true; - } finally { - /* - * Position to the data. - */ - bb.rewind(); - bb.limit(macData); - } - } - - /* * Pass the data down if it's internally cached, otherwise * do it here. * @@ -251,16 +186,85 @@ * If external data(app), return a new ByteBuffer with data to * process. */ - ByteBuffer decrypt(CipherBox box, ByteBuffer bb) - throws BadPaddingException { + ByteBuffer decrypt(Authenticator authenticator, + CipherBox box, ByteBuffer bb) throws BadPaddingException { if (internalData) { - decrypt(box); + decrypt(authenticator, box); // MAC is checked during decryption return tmpBB; } - box.decrypt(bb); - bb.rewind(); + BadPaddingException bpe = null; + if (!box.isNullCipher()) { + try { + // apply explicit nonce for AEAD/CBC cipher suites if needed + int nonceSize = + box.applyExplicitNonce(authenticator, contentType(), bb); + + // decrypt the content + if (box.isAEADMode()) { + // DON'T encrypt the nonce_explicit for AEAD mode + bb.position(bb.position() + nonceSize); + } // The explicit IV for CBC mode can be decrypted. + + box.decrypt(bb); + bb.position(nonceSize); // We don't actually remove the nonce. + } catch (BadPaddingException e) { + // RFC 2246 states that decryption_failed should be used + // for this purpose. However, that allows certain attacks, + // so we just send bad record MAC. We also need to make + // sure to always check the MAC to avoid a timing attack + // for the same issue. See paper by Vaudenay et al and the + // update in RFC 4346/5246. + // + // Failover to message authentication code checking. + bpe = new BadPaddingException("invalid padding"); + } + } + + // Requires message authentication code for null, stream and block + // cipher suites. + if (authenticator instanceof MAC) { + MAC signer = (MAC)authenticator; + int macLen = signer.MAClen(); + if (macLen != 0) { + if (bb.remaining() < macLen) { + // negative data length, something is wrong + throw new BadPaddingException("bad record"); + } + + int position = bb.position(); + int limit = bb.limit(); + int macOffset = limit - macLen; + + bb.limit(macOffset); + byte[] hash = signer.compute(contentType(), bb); + if (hash == null || macLen != hash.length) { + // something is wrong with MAC implementation + throw new RuntimeException("Internal MAC error"); + } + + bb.position(macOffset); + bb.limit(limit); + + try { + for (byte b : hash) { // No BB.equals(byte []); ! + if (bb.get() != b) { + throw new BadPaddingException("bad record MAC"); + } + } + } finally { + // reset to the data + bb.position(position); + bb.limit(macOffset); + } + } + } + + // Is it a failover? + if (bpe != null) { + throw bpe; + } return bb.slice(); } @@ -338,8 +342,8 @@ if (debug != null && Debug.isOn("packet")) { try { HexDumpEncoder hd = new HexDumpEncoder(); - srcBB.limit(srcPos + len); ByteBuffer bb = srcBB.duplicate(); // Use copy of BB + bb.limit(srcPos + len); System.out.println("[Raw read (bb)]: length = " + len); hd.encodeBuffer(bb, System.out);
--- a/src/share/classes/sun/security/ssl/EngineOutputRecord.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/EngineOutputRecord.java Sat Mar 02 11:06:58 2013 -0400 @@ -29,7 +29,6 @@ import java.io.*; import java.nio.*; - /** * A OutputRecord class extension which uses external ByteBuffers * or the internal ByteArrayOutputStream for data manipulations. @@ -101,51 +100,6 @@ return finishedMsg; } - - /** - * Calculate the MAC value, storing the result either in - * the internal buffer, or at the end of the destination - * ByteBuffer. - * <P> - * We assume that the higher levels have assured us enough - * room, otherwise we'll indirectly throw a - * BufferOverFlowException runtime exception. - * - * position should equal limit, and points to the next - * free spot. - */ - private void addMAC(MAC signer, ByteBuffer bb) - throws IOException { - - if (signer.MAClen() != 0) { - byte[] hash = signer.compute(contentType(), bb); - - /* - * position was advanced to limit in compute above. - * - * Mark next area as writable (above layers should have - * established that we have plenty of room), then write - * out the hash. - */ - bb.limit(bb.limit() + hash.length); - bb.put(hash); - } - } - - /* - * Encrypt a ByteBuffer. - * - * We assume that the higher levels have assured us enough - * room for the encryption (plus padding), otherwise we'll - * indirectly throw a BufferOverFlowException runtime exception. - * - * position and limit will be the same, and points to the - * next free spot. - */ - void encrypt(CipherBox box, ByteBuffer bb) { - box.encrypt(bb); - } - /* * Override the actual write below. We do things this way to be * consistent with InputRecord. InputRecord may try to write out @@ -160,7 +114,8 @@ * Copy data out of buffer, it's ready to go. */ ByteBuffer netBB = (ByteBuffer) - ByteBuffer.allocate(len).put(buf, 0, len).flip(); + ByteBuffer.allocate(len).put(buf, off, len).flip(); + writer.putOutboundData(netBB); } @@ -168,17 +123,19 @@ * Main method for writing non-application data. * We MAC/encrypt, then send down for processing. */ - void write(MAC writeMAC, CipherBox writeCipher) throws IOException { + void write(Authenticator authenticator, CipherBox writeCipher) + throws IOException { + /* * Sanity check. */ switch (contentType()) { - case ct_change_cipher_spec: - case ct_alert: - case ct_handshake: - break; - default: - throw new RuntimeException("unexpected byte buffers"); + case ct_change_cipher_spec: + case ct_alert: + case ct_handshake: + break; + default: + throw new RuntimeException("unexpected byte buffers"); } /* @@ -193,10 +150,10 @@ */ if (!isEmpty()) { // compress(); // eventually - addMAC(writeMAC); - encrypt(writeCipher); - write((OutputStream)null, false, // send down for processing - (ByteArrayOutputStream)null); + encrypt(authenticator, writeCipher); + + // send down for processing + write((OutputStream)null, false, (ByteArrayOutputStream)null); } return; } @@ -204,8 +161,8 @@ /** * Main wrap/write driver. */ - void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher) - throws IOException { + void write(EngineArgs ea, Authenticator authenticator, + CipherBox writeCipher) throws IOException { /* * sanity check to make sure someone didn't inadvertantly * send us an impossible combination we don't know how @@ -217,7 +174,7 @@ * Have we set the MAC's yet? If not, we're not ready * to process application data yet. */ - if (writeMAC == MAC.NULL) { + if (authenticator == MAC.NULL) { return; } @@ -255,7 +212,7 @@ */ int length; if (engine.needToSplitPayload(writeCipher, protocolVersion)) { - write(ea, writeMAC, writeCipher, 0x01); + write(ea, authenticator, writeCipher, 0x01); ea.resetLim(); // reset application data buffer limit length = Math.min(ea.getAppRemaining(), maxDataSizeMinusOneByteRecord); @@ -265,14 +222,14 @@ // Don't bother to really write empty records. if (length > 0) { - write(ea, writeMAC, writeCipher, length); + write(ea, authenticator, writeCipher, length); } return; } - void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher, - int length) throws IOException { + void write(EngineArgs ea, Authenticator authenticator, + CipherBox writeCipher, int length) throws IOException { /* * Copy out existing buffer values. */ @@ -286,39 +243,76 @@ * Don't need to worry about SSLv2 rewrites, if we're here, * that's long since done. */ - int dstData = dstPos + headerSize; + int dstData = dstPos + headerSize + writeCipher.getExplicitNonceSize(); dstBB.position(dstData); + /* + * transfer application data into the network data buffer + */ ea.gather(length); + dstBB.limit(dstBB.position()); + dstBB.position(dstData); /* * "flip" but skip over header again, add MAC & encrypt - * addMAC will expand the limit to reflect the new - * data. */ - dstBB.limit(dstBB.position()); - dstBB.position(dstData); - addMAC(writeMAC, dstBB); + if (authenticator instanceof MAC) { + MAC signer = (MAC)authenticator; + if (signer.MAClen() != 0) { + byte[] hash = signer.compute(contentType(), dstBB); + + /* + * position was advanced to limit in compute above. + * + * Mark next area as writable (above layers should have + * established that we have plenty of room), then write + * out the hash. + */ + dstBB.limit(dstBB.limit() + hash.length); + dstBB.put(hash); + + // reset the position and limit + dstBB.limit(dstBB.position()); + dstBB.position(dstData); + } + } - /* - * Encrypt may pad, so again the limit may have changed. - */ - dstBB.limit(dstBB.position()); - dstBB.position(dstData); - encrypt(writeCipher, dstBB); + if (!writeCipher.isNullCipher()) { + /* + * Requires explicit IV/nonce for CBC/AEAD cipher suites for TLS 1.1 + * or later. + */ + if (protocolVersion.v >= ProtocolVersion.TLS11.v && + (writeCipher.isCBCMode() || writeCipher.isAEADMode())) { + byte[] nonce = writeCipher.createExplicitNonce( + authenticator, contentType(), dstBB.remaining()); + dstBB.position(dstPos + headerSize); + dstBB.put(nonce); + if (!writeCipher.isAEADMode()) { + // The explicit IV in TLS 1.1 and later can be encrypted. + dstBB.position(dstPos + headerSize); + } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode + } - if (debug != null - && (Debug.isOn("record") || Debug.isOn("handshake"))) { - if ((debug != null && Debug.isOn("record")) - || contentType() == ct_change_cipher_spec) + /* + * Encrypt may pad, so again the limit may have changed. + */ + writeCipher.encrypt(dstBB, dstLim); + + if ((debug != null) && (Debug.isOn("record") || + (Debug.isOn("handshake") && + (contentType() == ct_change_cipher_spec)))) { System.out.println(Thread.currentThread().getName() // v3.0/v3.1 ... + ", WRITE: " + protocolVersion + " " + InputRecord.contentName(contentType()) + ", length = " + length); + } + } else { + dstBB.position(dstBB.limit()); } - int packetLength = dstBB.limit() - dstData; + int packetLength = dstBB.limit() - dstPos - headerSize; /* * Finish out the record header. @@ -333,7 +327,5 @@ * Position was already set by encrypt() above. */ dstBB.limit(dstLim); - - return; } }
--- a/src/share/classes/sun/security/ssl/EngineWriter.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/EngineWriter.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -99,7 +99,8 @@ * other writeRecord. */ synchronized void writeRecord(EngineOutputRecord outputRecord, - MAC writeMAC, CipherBox writeCipher) throws IOException { + Authenticator authenticator, + CipherBox writeCipher) throws IOException { /* * Only output if we're still open. @@ -108,7 +109,7 @@ throw new IOException("writer side was already closed."); } - outputRecord.write(writeMAC, writeCipher); + outputRecord.write(authenticator, writeCipher); /* * Did our handshakers notify that we just sent the @@ -151,7 +152,8 @@ * Return any determined status. */ synchronized HandshakeStatus writeRecord( - EngineOutputRecord outputRecord, EngineArgs ea, MAC writeMAC, + EngineOutputRecord outputRecord, EngineArgs ea, + Authenticator authenticator, CipherBox writeCipher) throws IOException { /* @@ -181,7 +183,7 @@ throw new IOException("The write side was already closed"); } - outputRecord.write(ea, writeMAC, writeCipher); + outputRecord.write(ea, authenticator, writeCipher); if (debug != null && Debug.isOn("packet")) { dumpPacket(ea, false);
--- a/src/share/classes/sun/security/ssl/Handshaker.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/Handshaker.java Sat Mar 02 11:06:58 2013 -0400 @@ -49,6 +49,7 @@ import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; +import static sun.security.ssl.CipherSuite.CipherType.*; /** * Handshaker ... processes handshake records from an SSL V3.0 @@ -714,33 +715,47 @@ /** * Create a new read MAC and return it to caller. */ - MAC newReadMAC() throws NoSuchAlgorithmException, InvalidKeyException { - MacAlg macAlg = cipherSuite.macAlg; - MAC mac; - if (isClient) { - mac = macAlg.newMac(protocolVersion, svrMacSecret); - svrMacSecret = null; + Authenticator newReadAuthenticator() + throws NoSuchAlgorithmException, InvalidKeyException { + + Authenticator authenticator = null; + if (cipherSuite.cipher.cipherType == AEAD_CIPHER) { + authenticator = new Authenticator(protocolVersion); } else { - mac = macAlg.newMac(protocolVersion, clntMacSecret); - clntMacSecret = null; + MacAlg macAlg = cipherSuite.macAlg; + if (isClient) { + authenticator = macAlg.newMac(protocolVersion, svrMacSecret); + svrMacSecret = null; + } else { + authenticator = macAlg.newMac(protocolVersion, clntMacSecret); + clntMacSecret = null; + } } - return mac; + + return authenticator; } /** * Create a new write MAC and return it to caller. */ - MAC newWriteMAC() throws NoSuchAlgorithmException, InvalidKeyException { - MacAlg macAlg = cipherSuite.macAlg; - MAC mac; - if (isClient) { - mac = macAlg.newMac(protocolVersion, clntMacSecret); - clntMacSecret = null; + Authenticator newWriteAuthenticator() + throws NoSuchAlgorithmException, InvalidKeyException { + + Authenticator authenticator = null; + if (cipherSuite.cipher.cipherType == AEAD_CIPHER) { + authenticator = new Authenticator(protocolVersion); } else { - mac = macAlg.newMac(protocolVersion, svrMacSecret); - svrMacSecret = null; + MacAlg macAlg = cipherSuite.macAlg; + if (isClient) { + authenticator = macAlg.newMac(protocolVersion, clntMacSecret); + clntMacSecret = null; + } else { + authenticator = macAlg.newMac(protocolVersion, svrMacSecret); + svrMacSecret = null; + } } - return mac; + + return authenticator; } /* @@ -1189,11 +1204,23 @@ int prfHashLength = prf.getPRFHashLength(); int prfBlockSize = prf.getPRFBlockSize(); + // TLS v1.1 or later uses an explicit IV in CBC cipher suites to + // protect against the CBC attacks. AEAD/GCM cipher suites in TLS + // v1.2 or later use a fixed IV as the implicit part of the partially + // implicit nonce technique described in RFC 5116. + int ivSize = cipher.ivSize; + if (cipher.cipherType == AEAD_CIPHER) { + ivSize = cipher.fixedIvSize; + } else if (protocolVersion.v >= ProtocolVersion.TLS11.v && + cipher.cipherType == BLOCK_CIPHER) { + ivSize = 0; + } + TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec( masterKey, protocolVersion.major, protocolVersion.minor, clnt_random.random_bytes, svr_random.random_bytes, cipher.algorithm, cipher.keySize, expandedKeySize, - cipher.ivSize, hashSize, + ivSize, hashSize, prfHashAlg, prfHashLength, prfBlockSize); try { @@ -1201,14 +1228,15 @@ kg.init(spec); TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey(); + // Return null if cipher keys are not supposed to be generated. clntWriteKey = keySpec.getClientCipherKey(); svrWriteKey = keySpec.getServerCipherKey(); // Return null if IVs are not supposed to be generated. - // e.g. TLS 1.1+. clntWriteIV = keySpec.getClientIv(); svrWriteIV = keySpec.getServerIv(); + // Return null if MAC keys are not supposed to be generated. clntMacSecret = keySpec.getClientMacKey(); svrMacSecret = keySpec.getServerMacKey(); } catch (GeneralSecurityException e) { @@ -1233,10 +1261,14 @@ printHex(dump, masterKey.getEncoded()); // Outputs: - System.out.println("Client MAC write Secret:"); - printHex(dump, clntMacSecret.getEncoded()); - System.out.println("Server MAC write Secret:"); - printHex(dump, svrMacSecret.getEncoded()); + if (clntMacSecret != null) { + System.out.println("Client MAC write Secret:"); + printHex(dump, clntMacSecret.getEncoded()); + System.out.println("Server MAC write Secret:"); + printHex(dump, svrMacSecret.getEncoded()); + } else { + System.out.println("... no MAC keys used for this cipher"); + } if (clntWriteKey != null) { System.out.println("Client write key:");
--- a/src/share/classes/sun/security/ssl/InputRecord.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/InputRecord.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, 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,6 +77,17 @@ /* * Construct the record to hold the maximum sized input record. * Data will be filled in separately. + * + * The structure of the byte buffer looks like: + * + * |--------+---------+---------------------------------| + * | header | IV | content, MAC/TAG, padding, etc. | + * | headerPlusIVSize | + * + * header: the header of an SSL records + * IV: the optional IV/nonce field, it is only required for block + * (TLS 1.1 or later) and AEAD cipher suites. + * */ InputRecord() { super(new byte[maxRecordSize]); @@ -133,44 +144,83 @@ return handshakeHash; } - /* - * Verify and remove the MAC ... used for all records. - */ - boolean checkMAC(MAC signer) { - int len = signer.MAClen(); - if (len == 0) { // no mac - return true; - } + void decrypt(Authenticator authenticator, + CipherBox box) throws BadPaddingException { + + BadPaddingException bpe = null; + if (!box.isNullCipher()) { + try { + int cipheredLength = count - headerSize; + + // apply explicit nonce for AEAD/CBC cipher suites if needed + int nonceSize = box.applyExplicitNonce(authenticator, + contentType(), buf, headerSize, cipheredLength); + pos = headerSize + nonceSize; + lastHashed = pos; // don't digest the explicit nonce - int offset = count - len; + // decrypt the content + int offset = headerSize; + if (box.isAEADMode()) { + // DON'T encrypt the nonce_explicit for AEAD mode + offset += nonceSize; + } // The explicit IV for CBC mode can be decrypted. + + count = offset + box.decrypt(buf, offset, count - offset); - if (offset < headerSize) { - // data length would be negative, something is wrong - return false; + // Note that we don't remove the nonce from the buffer. + } catch (BadPaddingException e) { + // RFC 2246 states that decryption_failed should be used + // for this purpose. However, that allows certain attacks, + // so we just send bad record MAC. We also need to make + // sure to always check the MAC to avoid a timing attack + // for the same issue. See paper by Vaudenay et al and the + // update in RFC 4346/5246. + // + // Failover to message authenticatoin code checking. + bpe = new BadPaddingException("invalid padding"); + } } - byte[] mac = signer.compute(contentType(), buf, - headerSize, offset - headerSize); + // Requires message authentication code for null, stream and block + // cipher suites. + if (authenticator instanceof MAC) { + MAC signer = (MAC)authenticator; + int macLen = signer.MAClen(); + if (macLen != 0) { + int macOffset = count - macLen; + int contentLen = macOffset - pos; + if (contentLen < 0) { + // negative data length, something is wrong + throw new BadPaddingException("bad record"); + } - if (len != mac.length) { - throw new RuntimeException("Internal MAC error"); + count -= macLen; // Set the count before any MAC checking + // exception occurs, so that the following + // process can read the actual decrypted + // content (minus the MAC) in the fragment + // if necessary. + byte[] hash = signer.compute(contentType(), + buf, pos, contentLen); + if (hash == null || macLen != hash.length) { + // something is wrong with MAC implementation + throw new RuntimeException("Internal MAC error"); + } + + int offset = macOffset; + for (byte b : hash) { + if (buf[offset++] != b) { + throw new BadPaddingException("bad record MAC"); + } + } + } } - for (int i = 0; i < len; i++) { - if (buf[offset + i] != mac[i]) { - return false; - } + // Is it a failover? + if (bpe != null) { + throw bpe; } - count -= len; - return true; } - void decrypt(CipherBox box) throws BadPaddingException { - int len = count - headerSize; - count = headerSize + box.decrypt(buf, headerSize, len); - } - - /* * Well ... hello_request messages are _never_ hashed since we can't * know when they'd appear in the sequence.
--- a/src/share/classes/sun/security/ssl/JsseJce.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/JsseJce.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, 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,6 +155,11 @@ */ final static String CIPHER_AES = "AES/CBC/NoPadding"; /** + * JCE transformation string for AES in GCM mode + * without padding. + */ + final static String CIPHER_AES_GCM = "AES/GCM/NoPadding"; + /** * JCA identifier string for DSA, i.e. a DSA with SHA-1. */ final static String SIGNATURE_DSA = "DSA";
--- a/src/share/classes/sun/security/ssl/MAC.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/MAC.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, 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,19 +39,15 @@ /** * This class computes the "Message Authentication Code" (MAC) for each - * SSL message. This is essentially a shared-secret signature, used to - * provide integrity protection for SSL messages. The MAC is actually - * one of several keyed hashes, as associated with the cipher suite and - * protocol version. (SSL v3.0 uses one construct, TLS uses another.) - * - * <P>NOTE: MAC computation is the only place in the SSL protocol that the - * sequence number is used. It's also reset to zero with each change of - * a cipher spec, so this is the only place this state is needed. + * SSL stream and block cipher message. This is essentially a shared-secret + * signature, used to provide integrity protection for SSL messages. The + * MAC is actually one of several keyed hashes, as associated with the cipher + * suite and protocol version. (SSL v3.0 uses one construct, TLS uses another.) * * @author David Brownell * @author Andreas Sterbenz */ -final class MAC { +final class MAC extends Authenticator { final static MAC NULL = new MAC(); @@ -64,26 +60,9 @@ // JCE Mac object private final Mac mac; - // byte array containing the additional information we MAC in each record - // (see below) - private final byte[] block; - - // sequence number + record type + + record length - private static final int BLOCK_SIZE_SSL = 8 + 1 + 2; - - // sequence number + record type + protocol version + record length - private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2; - - // offset of record type in block - private static final int BLOCK_OFFSET_TYPE = 8; - - // offset of protocol version number in block (TLS only) - private static final int BLOCK_OFFSET_VERSION = 8 + 1; - private MAC() { macSize = 0; mac = null; - block = null; } /** @@ -91,6 +70,8 @@ */ MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key) throws NoSuchAlgorithmException, InvalidKeyException { + super(protocolVersion); + this.macSize = macAlg.size; String algorithm; @@ -110,14 +91,6 @@ mac = JsseJce.getMac(algorithm); mac.init(key); - - if (tls) { - block = new byte[BLOCK_SIZE_TLS]; - block[BLOCK_OFFSET_VERSION] = protocolVersion.major; - block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor; - } else { - block = new byte[BLOCK_SIZE_SSL]; - } } /** @@ -136,7 +109,15 @@ * @param len the size of the compressed record */ final byte[] compute(byte type, byte buf[], int offset, int len) { - return compute(type, null, buf, offset, len); + if (macSize == 0) { + return nullMAC; + } + + byte[] additional = acquireAuthenticationBytes(type, len); + mac.update(additional); + mac.update(buf, offset, len); + + return mac.doFinal(); } /** @@ -151,78 +132,13 @@ * demarcate the data to be MAC'd. */ final byte[] compute(byte type, ByteBuffer bb) { - return compute(type, bb, null, 0, bb.remaining()); - } - - /** - * Check whether the sequence number is close to wrap - * - * Sequence numbers are of type uint64 and may not exceed 2^64-1. - * Sequence numbers do not wrap. When the sequence number is near - * to wrap, we need to close the connection immediately. - */ - final boolean seqNumOverflow() { - /* - * Conservatively, we don't allow more records to be generated - * when there are only 2^8 sequence numbers left. - */ - return (block != null && mac != null && - block[0] == (byte)0xFF && block[1] == (byte)0xFF && - block[2] == (byte)0xFF && block[3] == (byte)0xFF && - block[4] == (byte)0xFF && block[5] == (byte)0xFF && - block[6] == (byte)0xFF); - } - - /* - * Check whether to renew the sequence number - * - * Sequence numbers are of type uint64 and may not exceed 2^64-1. - * Sequence numbers do not wrap. If a TLS - * implementation would need to wrap a sequence number, it must - * renegotiate instead. - */ - final boolean seqNumIsHuge() { - /* - * Conservatively, we should ask for renegotiation when there are - * only 2^48 sequence numbers left. - */ - return (block != null && mac != null && - block[0] == (byte)0xFF && block[1] == (byte)0xFF); - } - - // increment the sequence number in the block array - // it is a 64-bit number stored in big-endian format - private void incrementSequenceNumber() { - int k = 7; - while ((k >= 0) && (++block[k] == 0)) { - k--; - } - } - - /* - * Compute based on either buffer type, either bb.position/limit - * or buf/offset/len. - */ - private byte[] compute(byte type, ByteBuffer bb, byte[] buf, - int offset, int len) { - if (macSize == 0) { return nullMAC; } - block[BLOCK_OFFSET_TYPE] = type; - block[block.length - 2] = (byte)(len >> 8); - block[block.length - 1] = (byte)(len ); - - mac.update(block); - incrementSequenceNumber(); - - // content - if (bb != null) { - mac.update(bb); - } else { - mac.update(buf, offset, len); - } + byte[] additional = acquireAuthenticationBytes(type, bb.remaining()); + mac.update(additional); + mac.update(bb); return mac.doFinal(); }
--- a/src/share/classes/sun/security/ssl/OutputRecord.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/OutputRecord.java Sat Mar 02 11:06:58 2013 -0400 @@ -54,6 +54,7 @@ private int lastHashed; private boolean firstMessage; final private byte contentType; + private int headerOffset; // current protocol version, sent as record version ProtocolVersion protocolVersion; @@ -70,6 +71,23 @@ * Default constructor makes a record supporting the maximum * SSL record size. It allocates the header bytes directly. * + * The structure of the byte buffer looks like: + * + * |---------+--------+-------+---------------------------------| + * | unused | header | IV | content, MAC/TAG, padding, etc. | + * | headerPlusMaxIVSize | + * + * unused: unused part of the buffer of size + * + * headerPlusMaxIVSize - header size - IV size + * + * When this object is created, we don't know the protocol + * version number, IV length, etc., so reserve space in front + * to avoid extra data movement (copies). + * header: the header of an SSL record + * IV: the optional IV/nonce field, it is only required for block + * (TLS 1.1 or later) and AEAD cipher suites. + * * @param type the content type for the record */ OutputRecord(byte type, int size) { @@ -77,9 +95,10 @@ this.protocolVersion = ProtocolVersion.DEFAULT; this.helloVersion = ProtocolVersion.DEFAULT_HELLO; firstMessage = true; - count = headerSize; + count = headerPlusMaxIVSize; contentType = type; lastHashed = count; + headerOffset = headerPlusMaxIVSize - headerSize; } OutputRecord(byte type) { @@ -119,8 +138,9 @@ @Override public synchronized void reset() { super.reset(); - count = headerSize; + count = headerPlusMaxIVSize; lastHashed = count; + headerOffset = headerPlusMaxIVSize - headerSize; } /* @@ -173,58 +193,84 @@ * of sending empty records over the network. */ boolean isEmpty() { - return count == headerSize; + return count == headerPlusMaxIVSize; } /* - * Return true if the record is of a given alert. + * Return true if the record is of an alert of the given description. + * + * Per SSL/TLS specifications, alert messages convey the severity of the + * message (warning or fatal) and a description of the alert. An alert + * is defined with a two bytes struct, {byte level, byte description}, + * following after the header bytes. */ boolean isAlert(byte description) { - // An alert is defined with a two bytes struct, - // {byte level, byte description}, following after the header bytes. - if (count > (headerSize + 1) && contentType == ct_alert) { - return buf[headerSize + 1] == description; + if ((count > (headerPlusMaxIVSize + 1)) && (contentType == ct_alert)) { + return buf[headerPlusMaxIVSize + 1] == description; } return false; } /* - * Compute the MAC and append it to this record. In case we - * are automatically flushing a handshake stream, make sure we - * have hashed the message first. + * Encrypt ... length may grow due to block cipher padding, or + * message authentication code or tag. */ - void addMAC(MAC signer) throws IOException { + void encrypt(Authenticator authenticator, CipherBox box) + throws IOException { + + // In case we are automatically flushing a handshake stream, make + // sure we have hashed the message first. // // when we support compression, hashing can't go here // since it'll need to be done on the uncompressed data, // and the MAC applies to the compressed data. - // if (contentType == ct_handshake) { doHashes(); } - if (signer.MAClen() != 0) { - byte[] hash = signer.compute(contentType, buf, - headerSize, count - headerSize); - write(hash); + + // Requires message authentication code for stream and block + // cipher suites. + if (authenticator instanceof MAC) { + MAC signer = (MAC)authenticator; + if (signer.MAClen() != 0) { + byte[] hash = signer.compute(contentType, buf, + headerPlusMaxIVSize, count - headerPlusMaxIVSize); + write(hash); + } + } + + if (!box.isNullCipher()) { + // Requires explicit IV/nonce for CBC/AEAD cipher suites for + // TLS 1.1 or later. + if ((protocolVersion.v >= ProtocolVersion.TLS11.v) && + (box.isCBCMode() || box.isAEADMode())) { + byte[] nonce = box.createExplicitNonce(authenticator, + contentType, count - headerPlusMaxIVSize); + int offset = headerPlusMaxIVSize - nonce.length; + System.arraycopy(nonce, 0, buf, offset, nonce.length); + headerOffset = offset - headerSize; + } else { + headerOffset = headerPlusMaxIVSize - headerSize; + } + + // encrypt the content + int offset = headerPlusMaxIVSize; + if (!box.isAEADMode()) { + // The explicit IV can be encrypted. + offset = headerOffset + headerSize; + } // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode + + count = offset + box.encrypt(buf, offset, count - offset); } } /* - * Encrypt ... length may grow due to block cipher padding - */ - void encrypt(CipherBox box) { - int len = count - headerSize; - count = headerSize + box.encrypt(buf, headerSize, len); - } - - - /* * Tell how full the buffer is ... for filling it with application or * handshake data. */ final int availableDataBytes() { - int dataSize = count - headerSize; + int dataSize = count - headerPlusMaxIVSize; return maxDataSize - dataSize; } @@ -270,11 +316,11 @@ * Don't emit content-free records. (Even change cipher spec * messages have a byte of data!) */ - if (count == headerSize) { + if (count == headerPlusMaxIVSize) { return; } - int length = count - headerSize; + int length = count - headerOffset - headerSize; // "should" really never write more than about 14 Kb... if (length < 0) { throw new SSLException("output record size too small: " @@ -299,7 +345,9 @@ */ if (firstMessage && useV2Hello()) { byte[] v3Msg = new byte[length - 4]; - System.arraycopy(buf, headerSize + 4, v3Msg, 0, v3Msg.length); + System.arraycopy(buf, headerPlusMaxIVSize + 4, + v3Msg, 0, v3Msg.length); + headerOffset = 0; // reset the header offset V3toV2ClientHello(v3Msg); handshakeHash.reset(); lastHashed = 2; @@ -314,11 +362,11 @@ /* * Fill out the header, write it and the message. */ - buf[0] = contentType; - buf[1] = protocolVersion.major; - buf[2] = protocolVersion.minor; - buf[3] = (byte)(length >> 8); - buf[4] = (byte)(length); + buf[headerOffset + 0] = contentType; + buf[headerOffset + 1] = protocolVersion.major; + buf[headerOffset + 2] = protocolVersion.minor; + buf[headerOffset + 3] = (byte)(length >> 8); + buf[headerOffset + 4] = (byte)(length); } firstMessage = false; @@ -338,7 +386,8 @@ * when holdRecord is true, the implementation in this class * will be used. */ - writeBuffer(heldRecordBuffer, buf, 0, count, debugOffset); + writeBuffer(heldRecordBuffer, + buf, headerOffset, count - headerOffset, debugOffset); } else { // It's time to send, do we have buffered data? // May or may not have a heldRecordBuffer. @@ -346,15 +395,18 @@ int heldLen = heldRecordBuffer.size(); // Ensure the capacity of this buffer. - ensureCapacity(count + heldLen); + int newCount = count + heldLen - headerOffset; + ensureCapacity(newCount); // Slide everything in the buffer to the right. - System.arraycopy(buf, 0, buf, heldLen, count); + System.arraycopy(buf, headerOffset, + buf, heldLen, count - headerOffset); // Prepend the held record to the buffer. System.arraycopy( heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen); - count += heldLen; + count = newCount; + headerOffset = 0; // Clear the held buffer. heldRecordBuffer.reset(); @@ -362,7 +414,8 @@ // The held buffer has been dumped, set the debug dump offset. debugOffset = heldLen; } - writeBuffer(s, buf, 0, count, debugOffset); + writeBuffer(s, buf, headerOffset, + count - headerOffset, debugOffset); } reset(); @@ -382,12 +435,11 @@ if (debug != null && Debug.isOn("packet")) { try { HexDumpEncoder hd = new HexDumpEncoder(); - ByteBuffer bb = ByteBuffer.wrap( - buf, off + debugOffset, len - debugOffset); System.out.println("[Raw write]: length = " + - bb.remaining()); - hd.encodeBuffer(bb, System.out); + (len - debugOffset)); + hd.encodeBuffer(new ByteArrayInputStream(buf, + off + debugOffset, len - debugOffset), System.out); } catch (IOException e) { } } } @@ -400,8 +452,13 @@ return firstMessage && (helloVersion == ProtocolVersion.SSL20Hello) && (contentType == ct_handshake) - && (buf[5] == HandshakeMessage.ht_client_hello) - && (buf[headerSize + 4+2+32] == 0); // V3 session ID is empty + && (buf[headerOffset + 5] == HandshakeMessage.ht_client_hello) + // 5: recode header size + && (buf[headerPlusMaxIVSize + 4 + 2 + 32] == 0); + // V3 session ID is empty + // 4: handshake header size + // 2: client_version in ClientHello + // 32: random in ClientHello } /*
--- a/src/share/classes/sun/security/ssl/Record.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/Record.java Sat Mar 02 11:06:58 2013 -0400 @@ -52,20 +52,29 @@ static final int trailerSize = 20; // SHA1 hash size static final int maxDataSize = 16384; // 2^14 bytes of data static final int maxPadding = 256; // block cipher padding - static final int maxIVLength = 256; // block length + static final int maxIVLength = 256; // IV length + + /* + * The size of the header plus the max IV length + */ + static final int headerPlusMaxIVSize = + headerSize // header + + maxIVLength; // iv /* * SSL has a maximum record size. It's header, (compressed) data, - * padding, and a trailer for the MAC. + * padding, and a trailer for the message authentication information (MAC + * for block and stream ciphers, and message authentication tag for AEAD + * ciphers). + * * Some compression algorithms have rare cases where they expand the data. * As we don't support compression at this time, leave that out. */ static final int maxRecordSize = - headerSize // header - + maxIVLength // iv - + maxDataSize // data - + maxPadding // padding - + trailerSize; // MAC + headerPlusMaxIVSize // header + iv + + maxDataSize // data + + maxPadding // padding + + trailerSize; // MAC or AEAD tag static final boolean enableCBCProtection = Debug.getBooleanProperty("jsse.enableCBCProtection", true); @@ -77,8 +86,7 @@ static final int maxDataSizeMinusOneByteRecord = maxDataSize // max data size - ( // max one byte record size - headerSize // header - + maxIVLength // iv + headerPlusMaxIVSize // header + iv + 1 // one byte data + maxPadding // padding + trailerSize // MAC @@ -104,11 +112,10 @@ * Allocate a smaller array. */ static final int maxAlertRecordSize = - headerSize // header - + maxIVLength // iv - + 2 // alert - + maxPadding // padding - + trailerSize; // MAC + headerPlusMaxIVSize // header + iv + + 2 // alert + + maxPadding // padding + + trailerSize; // MAC /* * The overflow values of integers of 8, 16 and 24 bits.
--- a/src/share/classes/sun/security/ssl/SSLEngineImpl.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/SSLEngineImpl.java Sat Mar 02 11:06:58 2013 -0400 @@ -280,7 +280,7 @@ /* * Crypto state that's reinitialized when the session changes. */ - private MAC readMAC, writeMAC; + private Authenticator readAuthenticator, writeAuthenticator; private CipherBox readCipher, writeCipher; // NOTE: compression state would be saved here @@ -377,9 +377,9 @@ * Note: compression support would go here too */ readCipher = CipherBox.NULL; - readMAC = MAC.NULL; + readAuthenticator = MAC.NULL; writeCipher = CipherBox.NULL; - writeMAC = MAC.NULL; + writeAuthenticator = MAC.NULL; // default security parameters for secure renegotiation secureRenegotiation = false; @@ -586,7 +586,7 @@ try { readCipher = handshaker.newReadCipher(); - readMAC = handshaker.newReadMAC(); + readAuthenticator = handshaker.newReadAuthenticator(); } catch (GeneralSecurityException e) { // "can't happen" throw new SSLException("Algorithm missing: ", e); @@ -622,7 +622,7 @@ try { writeCipher = handshaker.newWriteCipher(); - writeMAC = handshaker.newWriteMAC(); + writeAuthenticator = handshaker.newWriteAuthenticator(); } catch (GeneralSecurityException e) { // "can't happen" throw new SSLException("Algorithm missing: ", e); @@ -958,34 +958,15 @@ * throw a fatal alert if the integrity check fails. */ try { - decryptedBB = inputRecord.decrypt(readCipher, readBB); + decryptedBB = inputRecord.decrypt( + readAuthenticator, readCipher, readBB); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - // - // rewind the BB if necessary. - readBB.rewind(); - - inputRecord.checkMAC(readMAC, readBB); - // use the same alert types as for MAC failure below byte alertType = (inputRecord.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); - } - - if (!inputRecord.checkMAC(readMAC, decryptedBB)) { - if (inputRecord.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } + fatal(alertType, e.getMessage(), e); } // if (!inputRecord.decompress(c)) @@ -1137,7 +1118,7 @@ hsStatus = getHSStatus(hsStatus); if (connectionState < cs_ERROR && !isInboundDone() && (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { - if (checkSequenceNumber(readMAC, + if (checkSequenceNumber(readAuthenticator, inputRecord.contentType())) { hsStatus = getHSStatus(null); } @@ -1290,7 +1271,7 @@ // eventually compress as well. HandshakeStatus hsStatus = - writer.writeRecord(eor, ea, writeMAC, writeCipher); + writer.writeRecord(eor, ea, writeAuthenticator, writeCipher); /* * We only need to check the sequence number state for @@ -1307,7 +1288,7 @@ hsStatus = getHSStatus(hsStatus); if (connectionState < cs_ERROR && !isOutboundDone() && (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { - if (checkSequenceNumber(writeMAC, eor.contentType())) { + if (checkSequenceNumber(writeAuthenticator, eor.contentType())) { hsStatus = getHSStatus(null); } } @@ -1346,7 +1327,7 @@ */ void writeRecord(EngineOutputRecord eor) throws IOException { // eventually compress as well. - writer.writeRecord(eor, writeMAC, writeCipher); + writer.writeRecord(eor, writeAuthenticator, writeCipher); /* * Check the sequence number state @@ -1360,7 +1341,7 @@ * of the last record cannot be wrapped. */ if ((connectionState < cs_ERROR) && !isOutboundDone()) { - checkSequenceNumber(writeMAC, eor.contentType()); + checkSequenceNumber(writeAuthenticator, eor.contentType()); } } @@ -1378,14 +1359,14 @@ * * Return true if the handshake status may be changed. */ - private boolean checkSequenceNumber(MAC mac, byte type) + private boolean checkSequenceNumber(Authenticator authenticator, byte type) throws IOException { /* * Don't bother to check the sequence number for error or * closed connections, or NULL MAC */ - if (connectionState >= cs_ERROR || mac == MAC.NULL) { + if (connectionState >= cs_ERROR || authenticator == MAC.NULL) { return false; } @@ -1393,7 +1374,7 @@ * Conservatively, close the connection immediately when the * sequence number is close to overflow */ - if (mac.seqNumOverflow()) { + if (authenticator.seqNumOverflow()) { /* * TLS protocols do not define a error alert for sequence * number overflow. We use handshake_failure error alert @@ -1416,7 +1397,7 @@ * Don't bother to kickstart the renegotiation when the local is * asking for it. */ - if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) { + if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) { if (debug != null && Debug.isOn("ssl")) { System.out.println(Thread.currentThread().getName() + ", request renegotiation " +
--- a/src/share/classes/sun/security/ssl/SSLSocketImpl.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/ssl/SSLSocketImpl.java Sat Mar 02 11:06:58 2013 -0400 @@ -292,7 +292,7 @@ /* * Crypto state that's reinitialized when the session changes. */ - private MAC readMAC, writeMAC; + private Authenticator readAuthenticator, writeAuthenticator; private CipherBox readCipher, writeCipher; // NOTE: compression state would be saved here @@ -586,9 +586,9 @@ * Note: compression support would go here too */ readCipher = CipherBox.NULL; - readMAC = MAC.NULL; + readAuthenticator = MAC.NULL; writeCipher = CipherBox.NULL; - writeMAC = MAC.NULL; + writeAuthenticator = MAC.NULL; // initial security parameters for secure renegotiation secureRenegotiation = false; @@ -829,8 +829,7 @@ boolean holdRecord) throws IOException { // r.compress(c); - r.addMAC(writeMAC); - r.encrypt(writeCipher); + r.encrypt(writeAuthenticator, writeCipher); if (holdRecord) { // If we were requested to delay the record due to possibility @@ -861,7 +860,7 @@ * of the last record cannot be wrapped. */ if (connectionState < cs_ERROR) { - checkSequenceNumber(writeMAC, r.contentType()); + checkSequenceNumber(writeAuthenticator, r.contentType()); } // turn off the flag of the first application record @@ -986,29 +985,14 @@ * throw a fatal alert if the integrity check fails. */ try { - r.decrypt(readCipher); + r.decrypt(readAuthenticator, readCipher); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - r.checkMAC(readMAC); // use the same alert types as for MAC failure below byte alertType = (r.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); + fatal(alertType, e.getMessage(), e); } - if (!r.checkMAC(readMAC)) { - if (r.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } - } - // if (!r.decompress(c)) // fatal(Alerts.alert_decompression_failure, @@ -1159,7 +1143,7 @@ * of the last record cannot be wrapped. */ if (connectionState < cs_ERROR) { - checkSequenceNumber(readMAC, r.contentType()); + checkSequenceNumber(readAuthenticator, r.contentType()); } return; @@ -1182,14 +1166,14 @@ * implementation would need to wrap a sequence number, it must * renegotiate instead." */ - private void checkSequenceNumber(MAC mac, byte type) + private void checkSequenceNumber(Authenticator authenticator, byte type) throws IOException { /* * Don't bother to check the sequence number for error or * closed connections, or NULL MAC. */ - if (connectionState >= cs_ERROR || mac == MAC.NULL) { + if (connectionState >= cs_ERROR || authenticator == MAC.NULL) { return; } @@ -1197,7 +1181,7 @@ * Conservatively, close the connection immediately when the * sequence number is close to overflow */ - if (mac.seqNumOverflow()) { + if (authenticator.seqNumOverflow()) { /* * TLS protocols do not define a error alert for sequence * number overflow. We use handshake_failure error alert @@ -1219,7 +1203,7 @@ * Don't bother to kickstart the renegotiation when the local is * asking for it. */ - if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) { + if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) { if (debug != null && Debug.isOn("ssl")) { System.out.println(Thread.currentThread().getName() + ", request renegotiation " + @@ -2081,7 +2065,7 @@ try { readCipher = handshaker.newReadCipher(); - readMAC = handshaker.newReadMAC(); + readAuthenticator = handshaker.newReadAuthenticator(); } catch (GeneralSecurityException e) { // "can't happen" throw new SSLException("Algorithm missing: ", e); @@ -2112,7 +2096,7 @@ try { writeCipher = handshaker.newWriteCipher(); - writeMAC = handshaker.newWriteMAC(); + writeAuthenticator = handshaker.newWriteAuthenticator(); } catch (GeneralSecurityException e) { // "can't happen" throw new SSLException("Algorithm missing: ", e);
--- a/src/share/classes/sun/security/util/SecurityConstants.java Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/classes/sun/security/util/SecurityConstants.java Sat Mar 02 11:06:58 2013 -0400 @@ -71,31 +71,6 @@ public static final AllPermission ALL_PERMISSION = new AllPermission(); /** - * Permission type used when AWT is not present. - */ - private static class FakeAWTPermission extends BasicPermission { - private static final long serialVersionUID = -1L; - public FakeAWTPermission(String name) { - super(name); - } - public String toString() { - return "(\"java.awt.AWTPermission\" \"" + getName() + "\")"; - } - } - - /** - * Permission factory used when AWT is not present. - */ - private static class FakeAWTPermissionFactory - implements PermissionFactory<FakeAWTPermission> - { - @Override - public FakeAWTPermission newPermission(String name) { - return new FakeAWTPermission(name); - } - } - - /** * AWT Permissions used in the JDK. */ public static class AWT { @@ -107,37 +82,29 @@ private static final String AWTFactory = "sun.awt.AWTPermissionFactory"; /** - * The PermissionFactory to create AWT permissions (or fake permissions - * if AWT is not present). + * The PermissionFactory to create AWT permissions (or null if AWT is + * not present) */ private static final PermissionFactory<?> factory = permissionFactory(); private static PermissionFactory<?> permissionFactory() { - Class<?> c = AccessController - .doPrivileged(new PrivilegedAction<Class<?>>() { - public Class<?> run() { - try { - return Class.forName(AWTFactory, true, null); - } catch (ClassNotFoundException e) { - // not available - return null; - } - }}); - if (c != null) { - // AWT present - try { - return (PermissionFactory<?>)c.newInstance(); - } catch (ReflectiveOperationException x) { - throw new InternalError(x.getMessage(), x); - } - } else { - // AWT not present - return new FakeAWTPermissionFactory(); + Class<?> c; + try { + c = Class.forName(AWTFactory, false, AWT.class.getClassLoader()); + } catch (ClassNotFoundException e) { + // not available + return null; + } + // AWT present + try { + return (PermissionFactory<?>)c.newInstance(); + } catch (ReflectiveOperationException x) { + throw new InternalError(x); } } private static Permission newAWTPermission(String name) { - return factory.newPermission(name); + return (factory == null) ? null : factory.newPermission(name); } // java.lang.SecurityManager
--- a/src/share/native/java/lang/System.c Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/native/java/lang/System.c Sat Mar 02 11:06:58 2013 -0400 @@ -212,6 +212,10 @@ PUTPROP(props, "os.version", sprops->os_version); PUTPROP(props, "os.arch", sprops->os_arch); +#ifdef JDK_ARCH_ABI_PROP_NAME + PUTPROP(props, "sun.arch.abi", sprops->sun_arch_abi); +#endif + /* file system properties */ PUTPROP(props, "file.separator", sprops->file_separator); PUTPROP(props, "path.separator", sprops->path_separator);
--- a/src/share/native/java/lang/java_props.h Fri Feb 22 23:36:47 2013 -0400 +++ b/src/share/native/java/lang/java_props.h Sat Mar 02 11:06:58 2013 -0400 @@ -41,6 +41,10 @@ char *os_version; char *os_arch; +#ifdef JDK_ARCH_ABI_PROP_NAME + char *sun_arch_abi; +#endif + nchar *tmp_dir; nchar *font_dir; nchar *user_dir;
--- a/src/solaris/native/java/lang/java_props_md.c Fri Feb 22 23:36:47 2013 -0400 +++ b/src/solaris/native/java/lang/java_props_md.c Sat Mar 02 11:06:58 2013 -0400 @@ -514,6 +514,11 @@ } } + /* ABI property (optional) */ +#ifdef JDK_ARCH_ABI_PROP_NAME + sprops.sun_arch_abi = JDK_ARCH_ABI_PROP_NAME; +#endif + /* Determine the language, country, variant, and encoding from the host, * and store these in the user.language, user.country, user.variant and * file.encoding system properties. */
--- a/test/ProblemList.txt Fri Feb 22 23:36:47 2013 -0400 +++ b/test/ProblemList.txt Sat Mar 02 11:06:58 2013 -0400 @@ -327,9 +327,6 @@ # 7150569 tools/launcher/UnicodeTest.java macosx-all -# 8006039 -tools/launcher/I18NJarTest.java macosx-all - # 8007410 tools/launcher/FXLauncherTest.java linux-all
--- a/test/java/lang/SecurityManager/NoAWT.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/java/lang/SecurityManager/NoAWT.java Sat Mar 02 11:06:58 2013 -0400 @@ -22,14 +22,43 @@ */ /* @test - * @bug 8004502 + * @bug 8004502 8008793 * @summary Sanity check that SecurityManager methods that check AWTPermission * behave as expected when AWT is not present */ +import java.security.AllPermission; +import java.security.Permission; + public class NoAWT { + + static class MySecurityManager extends SecurityManager { + Class<?> expectedClass; + + void setExpectedPermissionClass(Class<?> c) { + expectedClass = c; + } + + @Override + public void checkPermission(Permission perm) { + if (perm.getClass() != expectedClass) + throw new RuntimeException("Got: " + perm.getClass() + ", expected: " + expectedClass); + super.checkPermission(perm); + } + } + public static void main(String[] args) { - SecurityManager sm = new SecurityManager(); + Class<?> awtPermissionClass = null; + try { + awtPermissionClass = Class.forName("java.awt.AWTPermission"); + } catch (ClassNotFoundException ignore) { } + + MySecurityManager sm = new MySecurityManager(); + if (awtPermissionClass != null) { + sm.setExpectedPermissionClass(awtPermissionClass); + } else { + sm.setExpectedPermissionClass(AllPermission.class); + } try { sm.checkAwtEventQueueAccess();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/7087570/Test7087570.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* @test + * @bug 7087570 + * @summary REF_invokeSpecial DMHs (which are unusual) get marked explicitly; tweak the MHI to use this bit + * + * @run main Test7087570 + */ + +import java.lang.invoke.*; +import java.lang.reflect.*; +import java.util.*; + +import static java.lang.invoke.MethodHandles.*; +import static java.lang.invoke.MethodType.*; + +public class Test7087570 { + // XXX may remove the following constant declarations when MethodHandleInfo is made public + private static final int + REF_getField = 1, + REF_getStatic = 2, + REF_putField = 3, + REF_putStatic = 4, + REF_invokeVirtual = 5, + REF_invokeStatic = 6, + REF_invokeSpecial = 7, + REF_newInvokeSpecial = 8, + REF_invokeInterface = 9, + REF_LIMIT = 10; + + private static final TestMethodData[] TESTS = new TestMethodData[] { + // field accessors + data(DummyFieldHolder.class, "instanceField", getterMethodType(String.class), DummyFieldHolder.class, REF_getField), + data(DummyFieldHolder.class, "instanceField", setterMethodType(String.class), DummyFieldHolder.class, REF_putField), + data(DummyFieldHolder.class, "staticField", getterMethodType(Integer.class), DummyFieldHolder.class, REF_getStatic), + data(DummyFieldHolder.class, "staticField", setterMethodType(Integer.class), DummyFieldHolder.class, REF_putStatic), + data(DummyFieldHolder.class, "instanceByteField", getterMethodType(byte.class), DummyFieldHolder.class, REF_getField), + data(DummyFieldHolder.class, "instanceByteField", setterMethodType(byte.class), DummyFieldHolder.class, REF_putField), + + // REF_invokeVirtual + data(Object.class, "hashCode", methodType(int.class), Object.class, REF_invokeVirtual), + + // REF_invokeVirtual strength-reduced to REF_invokeSpecial, + // test if it normalizes back to REF_invokeVirtual in MethodHandleInfo as expected + data(String.class, "hashCode", methodType(int.class), String.class, REF_invokeVirtual), + + // REF_invokeStatic + data(Collections.class, "sort", methodType(void.class, List.class), Collections.class, REF_invokeStatic), + data(Arrays.class, "asList", methodType(List.class, Object[].class), Arrays.class, REF_invokeStatic), // varargs case + + // REF_invokeSpecial + data(Object.class, "hashCode", methodType(int.class), Object.class, REF_invokeSpecial), + + // REF_newInvokeSpecial + data(String.class, "<init>", methodType(void.class, char[].class), String.class, REF_newInvokeSpecial), + data(DummyFieldHolder.class, "<init>", methodType(void.class, byte.class, Long[].class), DummyFieldHolder.class, REF_newInvokeSpecial), // varargs case + + // REF_invokeInterface + data(List.class, "size", methodType(int.class), List.class, REF_invokeInterface) + }; + + public static void main(String... args) throws Throwable { + testWithLookup(); + testWithUnreflect(); + } + + private static void doTest(MethodHandle mh, TestMethodData testMethod) { + Object mhi = newMethodHandleInfo(mh); + + System.out.printf("%s.%s: %s, nominal refKind: %s, actual refKind: %s\n", + testMethod.clazz.getName(), testMethod.name, testMethod.methodType, + REF_KIND_NAMES[testMethod.referenceKind], + REF_KIND_NAMES[getReferenceKind(mhi)]); + assertEquals(testMethod.name, getName(mhi)); + assertEquals(testMethod.methodType, getMethodType(mhi)); + assertEquals(testMethod.declaringClass, getDeclaringClass(mhi)); + assertEquals(testMethod.referenceKind == REF_invokeSpecial, isInvokeSpecial(mh)); + assertRefKindEquals(testMethod.referenceKind, getReferenceKind(mhi)); + } + + private static void testWithLookup() throws Throwable { + for (TestMethodData testMethod : TESTS) { + MethodHandle mh = lookupFrom(testMethod); + doTest(mh, testMethod); + } + } + + private static void testWithUnreflect() throws Throwable { + for (TestMethodData testMethod : TESTS) { + MethodHandle mh = unreflectFrom(testMethod); + doTest(mh, testMethod); + } + } + + private static MethodType getterMethodType(Class<?> clazz) { + return methodType(clazz); + } + + private static MethodType setterMethodType(Class<?> clazz) { + return methodType(void.class, clazz); + } + + private static final String[] REF_KIND_NAMES = { + "MH::invokeBasic", + "REF_getField", "REF_getStatic", "REF_putField", "REF_putStatic", + "REF_invokeVirtual", "REF_invokeStatic", "REF_invokeSpecial", + "REF_newInvokeSpecial", "REF_invokeInterface" + }; + + private static final Lookup LOOKUP = lookup(); + + // XXX may remove the following reflective logic when MethodHandleInfo is made public + private static final MethodHandle MH_IS_INVOKESPECIAL; + private static final MethodHandle MHI_CONSTRUCTOR; + private static final MethodHandle MHI_GET_NAME; + private static final MethodHandle MHI_GET_METHOD_TYPE; + private static final MethodHandle MHI_GET_DECLARING_CLASS; + private static final MethodHandle MHI_GET_REFERENCE_KIND; + + static { + try { + // This is white box testing. Use reflection to grab private implementation bits. + String magicName = "IMPL_LOOKUP"; + Field magicLookup = MethodHandles.Lookup.class.getDeclaredField(magicName); + // This unit test will fail if a security manager is installed. + magicLookup.setAccessible(true); + // Forbidden fruit... + Lookup directInvokeLookup = (Lookup) magicLookup.get(null); + Class<?> mhiClass = Class.forName("java.lang.invoke.MethodHandleInfo", false, MethodHandle.class.getClassLoader()); + MH_IS_INVOKESPECIAL = directInvokeLookup + .findVirtual(MethodHandle.class, "isInvokeSpecial", methodType(boolean.class)); + MHI_CONSTRUCTOR = directInvokeLookup + .findConstructor(mhiClass, methodType(void.class, MethodHandle.class)); + MHI_GET_NAME = directInvokeLookup + .findVirtual(mhiClass, "getName", methodType(String.class)); + MHI_GET_METHOD_TYPE = directInvokeLookup + .findVirtual(mhiClass, "getMethodType", methodType(MethodType.class)); + MHI_GET_DECLARING_CLASS = directInvokeLookup + .findVirtual(mhiClass, "getDeclaringClass", methodType(Class.class)); + MHI_GET_REFERENCE_KIND = directInvokeLookup + .findVirtual(mhiClass, "getReferenceKind", methodType(int.class)); + } catch (ReflectiveOperationException ex) { + throw new Error(ex); + } + } + + private static class TestMethodData { + final Class<?> clazz; + final String name; + final MethodType methodType; + final Class<?> declaringClass; + final int referenceKind; // the nominal refKind + + public TestMethodData(Class<?> clazz, String name, + MethodType methodType, Class<?> declaringClass, + int referenceKind) { + this.clazz = clazz; + this.name = name; + this.methodType = methodType; + this.declaringClass = declaringClass; + this.referenceKind = referenceKind; + } + } + + private static TestMethodData data(Class<?> clazz, String name, + MethodType methodType, Class<?> declaringClass, + int referenceKind) { + return new TestMethodData(clazz, name, methodType, declaringClass, referenceKind); + } + + private static MethodHandle lookupFrom(TestMethodData testMethod) + throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException { + switch (testMethod.referenceKind) { + case REF_getField: + return LOOKUP.findGetter(testMethod.clazz, testMethod.name, testMethod.methodType.returnType()); + case REF_putField: + return LOOKUP.findSetter(testMethod.clazz, testMethod.name, testMethod.methodType.parameterType(0)); + case REF_getStatic: + return LOOKUP.findStaticGetter(testMethod.clazz, testMethod.name, testMethod.methodType.returnType()); + case REF_putStatic: + return LOOKUP.findStaticSetter(testMethod.clazz, testMethod.name, testMethod.methodType.parameterType(0)); + case REF_invokeVirtual: + case REF_invokeInterface: + return LOOKUP.findVirtual(testMethod.clazz, testMethod.name, testMethod.methodType); + case REF_invokeStatic: + return LOOKUP.findStatic(testMethod.clazz, testMethod.name, testMethod.methodType); + case REF_invokeSpecial: + Class<?> thisClass = LOOKUP.lookupClass(); + return LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass); + case REF_newInvokeSpecial: + return LOOKUP.findConstructor(testMethod.clazz, testMethod.methodType); + default: + throw new Error("ERROR: unexpected referenceKind in test data"); + } + } + + private static MethodHandle unreflectFrom(TestMethodData testMethod) + throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException { + switch (testMethod.referenceKind) { + case REF_getField: + case REF_getStatic: { + Field f = testMethod.clazz.getDeclaredField(testMethod.name); + return LOOKUP.unreflectGetter(f); + } + case REF_putField: + case REF_putStatic: { + Field f = testMethod.clazz.getDeclaredField(testMethod.name); + return LOOKUP.unreflectSetter(f); + } + case REF_invokeVirtual: + case REF_invokeStatic: + case REF_invokeInterface: { + Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray()); + return LOOKUP.unreflect(m); + } + case REF_invokeSpecial: { + Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray()); + Class<?> thisClass = LOOKUP.lookupClass(); + return LOOKUP.unreflectSpecial(m, thisClass); + } + case REF_newInvokeSpecial: { + Constructor c = testMethod.clazz.getDeclaredConstructor(testMethod.methodType.parameterArray()); + return LOOKUP.unreflectConstructor(c); + } + default: + throw new Error("ERROR: unexpected referenceKind in test data"); + } + } + + private static Object newMethodHandleInfo(MethodHandle mh) { + try { + return MHI_CONSTRUCTOR.invoke(mh); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static boolean isInvokeSpecial(MethodHandle mh) { + try { + return (boolean) MH_IS_INVOKESPECIAL.invokeExact(mh); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static String getName(Object mhi) { + try { + return (String) MHI_GET_NAME.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static MethodType getMethodType(Object mhi) { + try { + return (MethodType) MHI_GET_METHOD_TYPE.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static Class<?> getDeclaringClass(Object mhi) { + try { + return (Class<?>) MHI_GET_DECLARING_CLASS.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static int getReferenceKind(Object mhi) { + try { + return (int) MHI_GET_REFERENCE_KIND.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static void assertRefKindEquals(int expect, int observed) { + if (expect == observed) return; + + String msg = "expected " + REF_KIND_NAMES[(int) expect] + + " but observed " + REF_KIND_NAMES[(int) observed]; + System.out.println("FAILED: " + msg); + throw new AssertionError(msg); + } + + private static void assertEquals(Object expect, Object observed) { + if (java.util.Objects.equals(expect, observed)) return; + + String msg = "expected " + expect + " but observed " + observed; + System.out.println("FAILED: " + msg); + throw new AssertionError(msg); + } +} + +class DummyFieldHolder { + public static Integer staticField; + public String instanceField; + public byte instanceByteField; + + public DummyFieldHolder(byte unused1, Long... unused2) { + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/LambdaClassLoaderSerialization.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* +@test +@bug 8004970 +@summary Lambda serialization in the presence of class loaders +@author Peter Levart +*/ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Arrays; + +public class LambdaClassLoaderSerialization { + + public interface SerializableRunnable extends Runnable, Serializable {} + + public static class MyCode implements SerializableRunnable { + + private byte[] serialize(Object o) { + ByteArrayOutputStream baos; + try ( + ObjectOutputStream oos = + new ObjectOutputStream(baos = new ByteArrayOutputStream()) + ) { + oos.writeObject(o); + } + catch (IOException e) { + throw new RuntimeException(e); + } + return baos.toByteArray(); + } + + private <T> T deserialize(byte[] bytes) { + try ( + ObjectInputStream ois = + new ObjectInputStream(new ByteArrayInputStream(bytes)) + ) { + return (T) ois.readObject(); + } + catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public void run() { + System.out.println(" this: " + this); + + SerializableRunnable deSerializedThis = deserialize(serialize(this)); + System.out.println(" deSerializedThis: " + deSerializedThis); + + SerializableRunnable runnable = () -> {System.out.println("HELLO");}; + System.out.println(" runnable: " + runnable); + + SerializableRunnable deSerializedRunnable = deserialize(serialize(runnable)); + System.out.println("deSerializedRunnable: " + deSerializedRunnable); + } + } + + public static void main(String[] args) throws Exception { + ClassLoader myCl = new MyClassLoader( + LambdaClassLoaderSerialization.class.getClassLoader() + ); + Class<?> myCodeClass = Class.forName( + LambdaClassLoaderSerialization.class.getName() + "$MyCode", + true, + myCl + ); + Runnable myCode = (Runnable) myCodeClass.newInstance(); + myCode.run(); + } + + static class MyClassLoader extends ClassLoader { + MyClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (name.indexOf('.') < 0) { + synchronized (getClassLoadingLock(name)) { + Class<?> c = findLoadedClass(name); + if (c == null) { + c = findClass(name); + } + if (resolve) { + resolveClass(c); + } + return c; + } + } else { + return super.loadClass(name, resolve); + } + } + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + String path = name.replace('.', '/').concat(".class"); + try (InputStream is = getResourceAsStream(path)) { + if (is != null) { + byte[] bytes = readFully(is); + return defineClass(name, bytes, 0, bytes.length); + } else { + throw new ClassNotFoundException(name); + } + } + catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + + static byte[] readFully(InputStream is) throws IOException { + byte[] output = {}; + int pos = 0; + while (true) { + int bytesToRead; + if (pos >= output.length) { // Only expand when there's no room + bytesToRead = output.length + 1024; + if (output.length < pos + bytesToRead) { + output = Arrays.copyOf(output, pos + bytesToRead); + } + } else { + bytesToRead = output.length - pos; + } + int cc = is.read(output, pos, bytesToRead); + if (cc < 0) { + if (output.length != pos) { + output = Arrays.copyOf(output, pos); + } + break; + } + pos += cc; + } + return output; + } + } +}
--- a/test/java/lang/invoke/lambda/LambdaSerialization.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/java/lang/invoke/lambda/LambdaSerialization.java Sat Mar 02 11:06:58 2013 -0400 @@ -25,7 +25,6 @@ @test @bug 8004970 @summary Lambda serialization -@run main/othervm LambdaSerialization */ import java.io.*;
--- a/test/java/nio/file/Files/CopyAndMove.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/java/nio/file/Files/CopyAndMove.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 6917021 7006126 6950237 + * @bug 4313887 6838333 6917021 7006126 6950237 8006645 * @summary Unit test for java.nio.file.Files copy and move methods * @library .. * @build CopyAndMove PassThroughFileSystem @@ -37,6 +37,7 @@ import java.nio.file.attribute.*; import java.io.*; import java.util.*; +import java.util.concurrent.TimeUnit; public class CopyAndMove { static final Random rand = new Random(); @@ -94,8 +95,8 @@ // check last modified time if not a symbolic link if (!attrs1.isSymbolicLink()) { - long time1 = attrs1.lastModifiedTime().toMillis(); - long time2 = attrs2.lastModifiedTime().toMillis(); + long time1 = attrs1.lastModifiedTime().to(TimeUnit.SECONDS); + long time2 = attrs2.lastModifiedTime().to(TimeUnit.SECONDS); if (time1 != time2) { System.err.format("File time for %s is %s\n", attrs1.fileKey(), attrs1.lastModifiedTime());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/Map/ToArray.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8008785 + * @summary Ensure toArray() implementations return correct results. + * @author Mike Duigou + */ +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; + +public class ToArray { + + /** + * Number of elements per map. + */ + private static final int TEST_SIZE = 5000; + + private static void realMain(String[] args) throws Throwable { + Map<Integer, Long>[] maps = (Map<Integer, Long>[]) new Map[]{ + new HashMap<>(), + new Hashtable<>(), + new IdentityHashMap<>(), + new LinkedHashMap<>(), + new TreeMap<>(), + new WeakHashMap<>(), + new ConcurrentHashMap<>(), + new ConcurrentSkipListMap<>() + }; + + // for each map type. + for (Map<Integer, Long> map : maps) { + try { + testMap(map); + } catch(Exception all) { + unexpected("Failed for " + map.getClass().getName(), all); + } + } + } + + private static final Integer[] KEYS = new Integer[TEST_SIZE]; + + private static final Long[] VALUES = new Long[TEST_SIZE]; + + static { + for (int each = 0; each < TEST_SIZE; each++) { + KEYS[each] = Integer.valueOf(each); + VALUES[each] = Long.valueOf(each + TEST_SIZE); + } + } + + + private static void testMap(Map<Integer, Long> map) { + System.out.println("Testing " + map.getClass()); + System.out.flush(); + + // Fill the map + for (int each = 0; each < TEST_SIZE; each++) { + map.put(KEYS[each], VALUES[each]); + } + + // check the keys + Object[] keys = map.keySet().toArray(); + Arrays.sort(keys); + + for(int each = 0; each < TEST_SIZE; each++) { + check( "unexpected key", keys[each] == KEYS[each]); + } + + // check the values + Object[] values = map.values().toArray(); + Arrays.sort(values); + + for(int each = 0; each < TEST_SIZE; each++) { + check( "unexpected value", values[each] == VALUES[each]); + } + + // check the entries + Map.Entry<Integer,Long>[] entries = map.entrySet().toArray(new Map.Entry[TEST_SIZE]); + Arrays.sort( entries,new Comparator<Map.Entry<Integer,Long>>() { + public int compare(Map.Entry<Integer,Long> o1, Map.Entry<Integer,Long> o2) { + return o1.getKey().compareTo(o2.getKey()); + }}); + + for(int each = 0; each < TEST_SIZE; each++) { + check( "unexpected entry", entries[each].getKey() == KEYS[each] && entries[each].getValue() == VALUES[each]); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + + static void pass() { + passed++; + } + + static void fail() { + failed++; + (new Error("Failure")).printStackTrace(System.err); + } + + static void fail(String msg) { + failed++; + (new Error("Failure: " + msg)).printStackTrace(System.err); + } + + static void abort() { + fail(); + System.exit(1); + } + + static void abort(String msg) { + fail(msg); + System.exit(1); + } + + static void unexpected(String msg, Throwable t) { + System.err.println("Unexpected: " + msg); + unexpected(t); + } + + static void unexpected(Throwable t) { + failed++; + t.printStackTrace(System.err); + } + + static void check(boolean cond) { + if (cond) { + pass(); + } else { + fail(); + } + } + + static void check(String desc, boolean cond) { + if (cond) { + pass(); + } else { + fail(desc); + } + } + + static void equal(Object x, Object y) { + if (Objects.equals(x, y)) { + pass(); + } else { + fail(x + " not equal to " + y); + } + } + + public static void main(String[] args) throws Throwable { + Thread.currentThread().setName(ToArray.class.getName()); +// Thread.currentThread().setPriority(Thread.MAX_PRIORITY); + try { + realMain(args); + } catch (Throwable t) { + unexpected(t); + } + + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) { + throw new Error("Some tests failed"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/forkjoin/ThreadLessCommon.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,135 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* + * @test + * @bug 8008378 + * @summary Basic checks for parallelism 0, and null returning factory + * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 ThreadLessCommon + * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.threadFactory=ThreadLessCommon$NullForkJoinWorkerThreadFactory ThreadLessCommon + * @author Chris Hegarty + */ + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.RecursiveTask; + +public class ThreadLessCommon { + + static final int THRESHOLD = 1000; + static final boolean debug = true; + + private static void realMain(String[] args) throws Throwable { + if (debug) { + String pp = System.getProperty( + "java.util.concurrent.ForkJoinPool.common.parallelism"); + System.out.println( + "java.util.concurrent.ForkJoinPool.common.parallelism:" + pp); + String tf = System.getProperty( + "java.util.concurrent.ForkJoinPool.common.threadFactory"); + System.out.println( + "java.util.concurrent.ForkJoinPool.common.threadFactory:" + tf); + } + + long from = 0, to = 50000; + RecursiveTask<Long> task = new SumTask(from, to, Thread.currentThread()); + long sum = task.invoke(); + System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum); + + task.fork(); + sum = task.join(); + System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum); + + sum = ForkJoinPool.commonPool().invoke(task.fork()); + System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum); + } + + static class SumTask extends RecursiveTask<Long> { + final Thread expectedThread; + final long from; + final long to; + SumTask(long from, long to, Thread thread) { + this.from = from; this.to = to; expectedThread = thread; + } + + @Override + public Long compute() { + check(Thread.currentThread() == expectedThread, + "Expected " + expectedThread + ", got " + Thread.currentThread()); + long range = to - from; + if (range < THRESHOLD) { + long acc = 0; + for (long i = from; i <= to; i++) + acc = acc + i; + return acc; + } else { + long half = from + range / 2; + SumTask t1 = new SumTask(from, half ,expectedThread); + SumTask t2 = new SumTask(half+1, to ,expectedThread); + if (half % 2 == 0) { + t1.fork(); + return t2.compute() + t1.join(); + } else { + invokeAll(t1, t2); + try { return t1.get() + t2.get(); } + catch (Exception x) { unexpected(x); return 0L;} + } + } + } + } + + public static class NullForkJoinWorkerThreadFactory + implements ForkJoinWorkerThreadFactory + { + @Override + public ForkJoinWorkerThread newThread(ForkJoinPool pool) { + return null; + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; /*Thread.dumpStack();*/} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond, String msg) {if (cond) pass(); else fail(msg);} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/concurrent/forkjoin/ThrowingRunnable.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,85 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* + * @test + * @bug 8008378 + * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.exceptionHandler=ThrowingRunnable + * ThrowingRunnable + * @summary FJP.execute(Runnable), uncaught exception should cause worker thread + * to die. + * @author Chris Hegarty + */ + +import java.lang.Thread.UncaughtExceptionHandler; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeUnit; + +public class ThrowingRunnable implements Runnable, UncaughtExceptionHandler { + + static final Phaser phaser = new Phaser(2); + + private static void realMain(String[] args) throws Throwable { + ThrowingRunnable r = new ThrowingRunnable(); + ForkJoinPool.commonPool().execute(r); + phaser.awaitAdvanceInterruptibly(phaser.arrive(), 10, TimeUnit.SECONDS); + pass(); + } + + @Override + public void run() { + throw new RuntimeException("This is an exception."); + } + + @Override + public void uncaughtException(Thread t, Throwable e) { + pass(); + phaser.arrive(); + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; /*Thread.dumpStack();*/} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond, String msg) {if (cond) pass(); else fail(msg);} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +}
--- a/test/javax/script/CauseExceptionTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/CauseExceptionTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -24,7 +24,7 @@ /* * @test * @bug 6869617 - * @summary RhinoScriptEngine bug : ScriptException cause not set (with fix) + * @summary ScriptEngine bug : ScriptException cause not set (with fix) */ import javax.script.*; @@ -33,12 +33,12 @@ public class CauseExceptionTest { public static void main(String[] args) throws ScriptException, NoSuchMethodException { ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine engine = sem.getEngineByName("js"); + ScriptEngine engine = sem.getEngineByName("nashorn"); if (engine == null) { System.out.println("Warning: No js engine found; test vacuously passes."); return; } - engine.eval("function hello_world() { println('hello world'); throw 'out of here'; } "); + engine.eval("function hello_world() { print('hello world'); throw 'out of here'; } "); Invocable invocable = (Invocable) engine; try { invocable.invokeFunction("hello_world", (Object[])null);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/script/ExceptionTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6474943 6705893 + * @summary Test that script engine exception messages are + * available from ScriptException. + */ + +import java.io.*; +import javax.script.*; + +public class ExceptionTest { + private static final String ERROR_MSG = "error from JavaScript"; + + public static void main(String[] args) throws Exception { + ScriptEngineManager m = new ScriptEngineManager(); + ScriptEngine engine = Helper.getJsEngine(m); + if (engine == null) { + System.out.println("Warning: No js engine found; test vacuously passes."); + return; + } + engine.put("msg", ERROR_MSG); + try { + engine.eval("throw new Error(msg);"); + } catch (ScriptException exp) { + if (exp.getMessage().indexOf(ERROR_MSG) == -1) { + throw exp; + } + } + try { + engine.eval("throw (msg);"); + } catch (ScriptException exp) { + if (exp.getMessage().indexOf(ERROR_MSG) == -1) { + throw exp; + } + } + try { + CompiledScript scr = ((Compilable)engine).compile("throw new Error(msg);"); + scr.eval(); + } catch (ScriptException exp) { + if (exp.getMessage().indexOf(ERROR_MSG) == -1) { + throw exp; + } + } + try { + CompiledScript scr = ((Compilable)engine).compile("throw msg;"); + scr.eval(); + } catch (ScriptException exp) { + if (exp.getMessage().indexOf(ERROR_MSG) == -1) { + throw exp; + } + } + } +}
--- a/test/javax/script/GetInterfaceTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/GetInterfaceTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -22,6 +22,7 @@ */ /* + * @run ignore * @test * @bug 6960211 * @summary JavaScript engine allows creation of interface although methods not available. @@ -32,10 +33,10 @@ public class GetInterfaceTest { public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("js"); + ScriptEngine engine = manager.getEngineByName("nashorn"); if (engine == null) { - System.out.println("Warning: No engine engine found; test vacuously passes."); + System.out.println("Warning: No js engine engine found; test vacuously passes."); return; }
--- a/test/javax/script/Helper.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/Helper.java Sat Mar 02 11:06:58 2013 -0400 @@ -24,13 +24,13 @@ /** * Helper class to consolidate testing requirements for a js engine. - * A js engine is required as part of Sun's product JDK. + * A js engine is required as part of Oracle's product JDK. */ public class Helper { private Helper() {}; // Don't instantiate public static ScriptEngine getJsEngine(ScriptEngineManager m) { - ScriptEngine e = m.getEngineByName("js"); + ScriptEngine e = m.getEngineByName("nashorn"); if (e == null && System.getProperty("java.runtime.name").startsWith("Java(TM)")) { // A js engine is requied for Sun's product JDK
--- a/test/javax/script/RhinoExceptionTest.java Fri Feb 22 23:36:47 2013 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6474943 6705893 - * @summary Test that Rhino exception messages are - * available from ScriptException. - */ - -import java.io.*; -import javax.script.*; - -public class RhinoExceptionTest { - private static final String ERROR_MSG = "error from JavaScript"; - - public static void main(String[] args) throws Exception { - ScriptEngineManager m = new ScriptEngineManager(); - ScriptEngine engine = Helper.getJsEngine(m); - if (engine == null) { - System.out.println("Warning: No js engine found; test vacuously passes."); - return; - } - engine.put("msg", ERROR_MSG); - try { - engine.eval("throw new Error(msg);"); - } catch (ScriptException exp) { - if (exp.getMessage().indexOf(ERROR_MSG) == -1) { - throw exp; - } - } - try { - engine.eval("throw (msg);"); - } catch (ScriptException exp) { - if (exp.getMessage().indexOf(ERROR_MSG) == -1) { - throw exp; - } - } - try { - CompiledScript scr = ((Compilable)engine).compile("throw new Error(msg);"); - scr.eval(); - } catch (ScriptException exp) { - if (exp.getMessage().indexOf(ERROR_MSG) == -1) { - throw exp; - } - } - try { - CompiledScript scr = ((Compilable)engine).compile("throw msg;"); - scr.eval(); - } catch (ScriptException exp) { - if (exp.getMessage().indexOf(ERROR_MSG) == -1) { - throw exp; - } - } - } -}
--- a/test/javax/script/StringWriterPrintTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/StringWriterPrintTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -33,9 +33,9 @@ public class StringWriterPrintTest { public static void main(String[] args) throws ScriptException { ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine engine = sem.getEngineByName("js"); + ScriptEngine engine = sem.getEngineByName("nashorn"); if (engine == null) { - System.out.println("Warning: No js engine found; test vacuously passes."); + System.out.println("Warning: No nashorn engine found; test vacuously passes."); return; } StringWriter sw = new StringWriter();
--- a/test/javax/script/Test3.js Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/Test3.js Sat Mar 02 11:06:58 2013 -0400 @@ -1,22 +1,24 @@ +var ScriptContext = javax.script.ScriptContext; + if (key == undefined || key != 'engine value') { throw "unexpected engine scope value"; } // pre-defined context variable refers to current ScriptContext -if (context.getAttribute('key', context.GLOBAL_SCOPE) != 'global value') { +if (context.getAttribute('key', ScriptContext.GLOBAL_SCOPE) != 'global value') { throw "unexpected global scope value"; } // change the engine scope value key = 'new engine value'; -if (context.getAttribute('key', context.GLOBAL_SCOPE) != 'global value') { +if (context.getAttribute('key', ScriptContext.GLOBAL_SCOPE) != 'global value') { throw "global scope should not change here"; } // delete engine scope value delete key; -if (key == undefined && key != 'xglobal value') { +if (key == undefined && key != 'global value') { throw 'global scope should be visible after engine scope removal'; }
--- a/test/javax/script/Test5.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/Test5.java Sat Mar 02 11:06:58 2013 -0400 @@ -48,16 +48,24 @@ System.out.println("engine scope only"); e.put("count", new Integer(1)); - Reader reader = new FileReader( - new File(System.getProperty("test.src", "."), "Test5.js")); - engine.eval(reader,ctxt); + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test5.js"))) { + engine.eval(reader,ctxt); + } + System.out.println("both scopes"); ctxt.setBindings(g, ScriptContext.GLOBAL_SCOPE); e.put("count", new Integer(2)); - engine.eval(reader,ctxt); + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test5.js"))) { + engine.eval(reader,ctxt); + } System.out.println("only global"); e.put("count", new Integer(3)); - ctxt.setAttribute("key", null, ScriptContext.ENGINE_SCOPE); - engine.eval(reader,ctxt); + ctxt.removeAttribute("key", ScriptContext.ENGINE_SCOPE); + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test5.js"))) { + engine.eval(reader,ctxt); + } } }
--- a/test/javax/script/Test5.js Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/Test5.js Sat Mar 02 11:06:58 2013 -0400 @@ -1,6 +1,5 @@ -var key; -var count; +var ScriptContext = javax.script.ScriptContext; print(count); switch (count) { @@ -9,7 +8,7 @@ if (key != 'value in engine') { throw "unexpected engine scope value"; } - if (context.getAttribute("key", context.GLOBAL_SCOPE ) != null) { + if (context.getAttribute("key", ScriptContext.GLOBAL_SCOPE ) != null) { throw "unexpected global scope value"; } break; @@ -19,7 +18,7 @@ if (key != 'value in engine') { throw "unexpected engine scope value"; } - if (context.getAttribute("key", context.GLOBAL_SCOPE ) != + if (context.getAttribute("key", ScriptContext.GLOBAL_SCOPE ) != "value in global") { throw "unexpected global scope value"; } @@ -30,7 +29,7 @@ if (key != 'value in global') { throw "unexpected global scope value"; } - if (context.getAttribute("key", context.GLOBAL_SCOPE ) != + if (context.getAttribute("key", ScriptContext.GLOBAL_SCOPE ) != "value in global") { throw "unexpected global scope value"; }
--- a/test/javax/script/Test6.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/Test6.java Sat Mar 02 11:06:58 2013 -0400 @@ -40,11 +40,23 @@ System.out.println("Warning: No js engine found; test vacuously passes."); return; } - Reader reader = new FileReader( - new File(System.getProperty("test.src", "."), "Test6.js")); - engine.eval(reader); + + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test6.js"))) { + engine.eval(reader); + } Object res = engine.get("res"); - CompiledScript scr = ((Compilable)engine).compile(reader); + + CompiledScript scr = null; + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test6.js"))) { + scr = ((Compilable)engine).compile(reader); + } + + if (scr == null) { + throw new RuntimeException("compilation failed!"); + } + scr.eval(); Object res1 = engine.get("res"); if (! res.equals(res1)) {
--- a/test/javax/script/Test7.js Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/Test7.js Sat Mar 02 11:06:58 2013 -0400 @@ -1,9 +1,14 @@ //this is the first line of Test7.js var filename; +try { + load("nashorn:mozilla_compat.js"); +} catch (e) { + //ignored +} importPackage(java.io); importPackage(java); var f = new File(filename); var r = new BufferedReader(new InputStreamReader(new FileInputStream(f))); -var firstLine = r.readLine() + ''; +var firstLine = r.readLine(); print(firstLine);
--- a/test/javax/script/UnescapedBracketRegExTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/UnescapedBracketRegExTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -24,7 +24,7 @@ /* * @test * @bug 7012701 - * @summary 7012701 Add a test to check that Rhino's RegExp parser accepts unescaped '[' + * @summary 7012701 Add a test to check that RegExp parser accepts unescaped '[' */ import javax.script.*; @@ -33,9 +33,9 @@ public class UnescapedBracketRegExTest { public static void main(String[] args) throws ScriptException { ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine engine = sem.getEngineByName("js"); + ScriptEngine engine = sem.getEngineByName("nashorn"); if (engine == null) { - System.out.println("Warning: No js engine found; test vacuously passes."); + System.out.println("Warning: No nashorn engine found; test vacuously passes."); return; } // the following throws exception
--- a/test/javax/script/VersionTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/javax/script/VersionTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -31,9 +31,7 @@ import java.io.*; public class VersionTest { - - private static final String JS_LANG_VERSION = "1.8"; - private static final String JS_ENGINE_VERSION = "1.7 release 3 PRERELEASE"; + private static final String JS_LANG_VERSION = "ECMA - 262 Edition 5.1"; public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); @@ -48,9 +46,18 @@ JS_LANG_VERSION); } String engineVersion = jsengine.getFactory().getEngineVersion(); - if (! engineVersion.equals(JS_ENGINE_VERSION)) { - throw new RuntimeException("Expected Rhino version is " + - JS_ENGINE_VERSION); + String expectedVersion = getNashornVersion(); + if (! engineVersion.equals(expectedVersion)) { + throw new RuntimeException("Expected version is " + expectedVersion); + } + } + + private static String getNashornVersion() { + try { + Class versionClass = Class.forName("jdk.nashorn.internal.runtime.Version"); + return (String) versionClass.getMethod("version").invoke(null); + } catch (Exception e) { + return "Version Unknown!"; } } }
--- a/test/sun/security/ec/TestEC.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/security/ec/TestEC.java Sat Mar 02 11:06:58 2013 -0400 @@ -21,6 +21,11 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /** * @test * @bug 6840752 @@ -30,7 +35,7 @@ * @library ../pkcs11/sslecc * @library ../../../java/security/testlibrary * @compile -XDignore.symbol.file TestEC.java - * @run main TestEC + * @run main/othervm TestEC */ import java.security.NoSuchProviderException;
--- a/test/sun/security/pkcs11/fips/CipherTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/security/pkcs11/fips/CipherTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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,25 @@ CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF), + CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + + CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + + CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + // cipher suites obsoleted since TLS 1.2 CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
--- a/test/sun/security/pkcs11/sslecc/CipherTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/security/pkcs11/sslecc/CipherTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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,25 @@ CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF), + CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + + CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + + CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + // cipher suites obsoleted since TLS 1.2 CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/provider/PolicyFile/WildcardPrincipalName.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8008908 + * @summary wildcard principal names are not processed correctly + * @run main/othervm/policy=wildcard.policy WildcardPrincipalName + */ + +import java.security.AccessController; +import java.security.Permission; +import java.security.Principal; +import java.security.PrivilegedAction; +import java.util.HashSet; +import java.util.PropertyPermission; +import java.util.Set; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +public class WildcardPrincipalName { + + public static void main(String[] args) throws Exception { + + X500Principal duke = new X500Principal("CN=Duke"); + PropertyPermission pp = new PropertyPermission("user.home", "read"); + RunAsPrivilegedUserAction runAsPrivilegedUserAction + = new RunAsPrivilegedUserAction(duke, + new CheckPermissionAction(pp)); + AccessController.doPrivileged(runAsPrivilegedUserAction); + System.out.println("test PASSED"); + } + + private static class RunAsPrivilegedUserAction + implements PrivilegedAction<Void> { + private final PrivilegedAction<Void> action; + private final Principal principal; + + RunAsPrivilegedUserAction(Principal principal, + PrivilegedAction<Void> action) { + this.principal = principal; + this.action = action; + } + + @Override public Void run() { + Set<Principal> principals = new HashSet<>(); + Set<Object> publicCredentials = new HashSet<>(); + Set<Object> privateCredentials = new HashSet<>(); + + principals.add(principal); + Subject subject = new Subject(true, + principals, + publicCredentials, + privateCredentials); + + Subject.doAsPrivileged(subject, action, null); + return null; + } + } + + private static class CheckPermissionAction + implements PrivilegedAction<Void> { + private final Permission permission; + + CheckPermissionAction(Permission permission) { + this.permission = permission; + } + + @Override public Void run() { + AccessController.checkPermission(permission); + return null; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/provider/PolicyFile/wildcard.policy Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,7 @@ +grant principal javax.security.auth.x500.X500Principal * { + permission java.util.PropertyPermission "user.home", "read"; +}; + +grant { + permission javax.security.auth.AuthPermission "doAsPrivileged"; +};
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java Sat Mar 02 11:06:58 2013 -0400 @@ -21,14 +21,16 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 7031830 * @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine * @run main/othervm SSLEngineBadBufferArrayAccess - * - * SunJSSE does not support dynamic system properties, no way to re-use - * system properties in samevm/agentvm mode. */ /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java Sat Mar 02 11:06:58 2013 -0400 @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2012, 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. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 7030966 + * @summary Support AEAD CipherSuites + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_128_GCM_SHA256 + */ + +/* + * Need additional key materials to run the following cases. + * + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * + * Need unlimited JCE Unlimited Strength Jurisdiction Policy to run the + * following cases. + * + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_256_GCM_SHA384 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_256_GCM_SHA384 + */ + +import java.net.*; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; +import java.security.Security; +import java.security.KeyStore; +import java.security.KeyFactory; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.*; +import java.security.interfaces.*; +import sun.misc.BASE64Decoder; + + +public class ShortRSAKeyGCM { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + // Certificates and key used in the test. + static String trustedCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + + "KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" + + "ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" + + "iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" + + "vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" + + "MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" + + "BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" + + "pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" + + "XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" + + "-----END CERTIFICATE-----"; + + static String targetCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICNDCCAZ2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTExMTA3MTM1NTUyWhcNMzEwNzI1MTM1NTUyWjBPMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + + "BAMTCWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC3Pb49OSPfOD2G\n" + + "HSXFCFx1GJEZfqG9ZUf7xuIi/ra5dLjPGAaoY5QF2QOa8VnOriQCXDfyXHxsuRnE\n" + + "OomxL7EVAgMBAAGjeDB2MAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUXNCJK3/dtCIc\n" + + "xb+zlA/JINlvs/MwHwYDVR0jBBgwFoAUuXzV2d+nTAOu/Q4nWzGVbMfzdeEwJwYD\n" + + "VR0lBCAwHgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAzANBgkqhkiG9w0B\n" + + "AQQFAAOBgQB2qIDUxA2caMPpGtUACZAPRUtrGssCINIfItETXJZCx/cRuZ5sP4D9\n" + + "N1acoNDn0hCULe3lhXAeTC9NZ97680yJzregQMV5wATjo1FGsKY30Ma+sc/nfzQW\n" + + "+h/7RhYtoG0OTsiaDCvyhI6swkNJzSzrAccPY4+ZgU8HiDLzZTmM3Q==\n" + + "-----END CERTIFICATE-----"; + + // Private key in the format of PKCS#8, key size is 512 bits. + static String targetPrivateKey = + "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtz2+PTkj3zg9hh0l\n" + + "xQhcdRiRGX6hvWVH+8biIv62uXS4zxgGqGOUBdkDmvFZzq4kAlw38lx8bLkZxDqJ\n" + + "sS+xFQIDAQABAkByx/5Oo2hQ/w2q4L8z+NTRlJ3vdl8iIDtC/4XPnfYfnGptnpG6\n" + + "ZThQRvbMZiai0xHQPQMszvAHjZVme1eDl3EBAiEA3aKJHynPVCEJhpfCLWuMwX5J\n" + + "1LntwJO7NTOyU5m8rPECIQDTpzn5X44r2rzWBDna/Sx7HW9IWCxNgUD2Eyi2nA7W\n" + + "ZQIgJerEorw4aCAuzQPxiGu57PB6GRamAihEAtoRTBQlH0ECIQDN08FgTtnesgCU\n" + + "DFYLLcw1CiHvc7fZw4neBDHCrC8NtQIgA8TOUkGnpCZlQ0KaI8KfKWI+vxFcgFnH\n" + + "3fnqsTgaUs4="; + + static char passphrase[] = "passphrase".toCharArray(); + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLContext context = generateSSLContext(null, targetCertStr, + targetPrivateKey); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); + SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort); + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept(); + sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites()); + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write('A'); + sslOS.flush(); + + sslSocket.close(); + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLContext context = generateSSLContext(trustedCertStr, null, null); + SSLSocketFactory sslsf = context.getSocketFactory(); + + SSLSocket sslSocket = + (SSLSocket)sslsf.createSocket("localhost", serverPort); + + // enable TLSv1.2 only + sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"}); + + // enable a block cipher + sslSocket.setEnabledCipherSuites(new String[] {cipherSuite}); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write('B'); + sslOS.flush(); + sslIS.read(); + + sslSocket.close(); + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + private static String tmAlgorithm; // trust manager + private static String cipherSuite; // cipher suite + + private static void parseArguments(String[] args) { + tmAlgorithm = args[0]; + cipherSuite = args[1]; + } + + private static SSLContext generateSSLContext(String trustedCertStr, + String keyCertStr, String keySpecStr) throws Exception { + + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + // create a key store + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, null); + + // import the trused cert + Certificate trusedCert = null; + ByteArrayInputStream is = null; + if (trustedCertStr != null) { + is = new ByteArrayInputStream(trustedCertStr.getBytes()); + trusedCert = cf.generateCertificate(is); + is.close(); + + ks.setCertificateEntry("RSA Export Signer", trusedCert); + } + + if (keyCertStr != null) { + // generate the private key. + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + new BASE64Decoder().decodeBuffer(keySpecStr)); + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPrivateKey priKey = + (RSAPrivateKey)kf.generatePrivate(priKeySpec); + + // generate certificate chain + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = cf.generateCertificate(is); + is.close(); + + Certificate[] chain = null; + if (trusedCert != null) { + chain = new Certificate[2]; + chain[0] = keyCert; + chain[1] = trusedCert; + } else { + chain = new Certificate[1]; + chain[0] = keyCert; + } + + // import the key entry. + ks.setKeyEntry("Whatever", priKey, passphrase, chain); + } + + // create SSL context + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); + tmf.init(ks); + + SSLContext ctx = SSLContext.getInstance("TLS"); + if (keyCertStr != null && !keyCertStr.isEmpty()) { + KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); + kmf.init(ks, passphrase); + + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + ks = null; + } else { + ctx.init(null, tmf.getTrustManagers(), null); + } + + return ctx; + } + + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + // reset the security property to make sure that the algorithms + // and keys used in this test are not disabled. + Security.setProperty("jdk.certpath.disabledAlgorithms", "MD2"); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + /* + * Get the customized arguments. + */ + parseArguments(args); + + /* + * Start the tests. + */ + new ShortRSAKeyGCM(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ShortRSAKeyGCM() throws Exception { + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + // swallow for now. Show later + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + String whichRemote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + whichRemote = "server"; + } else { + remote = clientException; + local = serverException; + whichRemote = "client"; + } + + /* + * If both failed, return the curthread's exception, but also + * print the remote side Exception + */ + if ((local != null) && (remote != null)) { + System.out.println(whichRemote + " also threw:"); + remote.printStackTrace(); + System.out.println(); + throw local; + } + + if (remote != null) { + throw remote; + } + + if (local != null) { + throw local; + } + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..." + e); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..." + e); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +}
--- a/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java Sat Mar 02 11:06:58 2013 -0400 @@ -21,13 +21,15 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 7174244 * @summary NPE in Krb5ProxyImpl.getServerKeys() - * - * SunJSSE does not support dynamic system properties, no way to re-use - * system properties in samevm/agentvm mode. * @run main/othervm CipherSuitesInOrder */ @@ -72,6 +74,22 @@ "SSL_RSA_WITH_RC4_128_SHA", "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", "TLS_ECDH_RSA_WITH_RC4_128_SHA", + + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", + "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", + "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA", @@ -83,6 +101,9 @@ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", + "TLS_DH_anon_WITH_AES_256_GCM_SHA384", + "TLS_DH_anon_WITH_AES_128_GCM_SHA256", + "TLS_DH_anon_WITH_AES_256_CBC_SHA256", "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", "TLS_DH_anon_WITH_AES_256_CBC_SHA",
--- a/test/sun/security/ssl/sanity/interop/CipherTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/security/ssl/sanity/interop/CipherTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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 @@ -148,6 +148,25 @@ CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF), CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF), + CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + + CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + + CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF), + CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF), + // cipher suites obsoleted since TLS 1.2 CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303), CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),
--- a/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, 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 @@ -21,14 +21,15 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 7105780 * @summary Add SSLSocket client/SSLEngine server to templates directory. - * - * SunJSSE does not support dynamic system properties, no way to re-use - * system properties in samevm/agentvm mode. - * * @run main/othervm SSLSocketSSLEngineTemplate */
--- a/test/sun/tools/jrunscript/CheckEngine.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/CheckEngine.java Sat Mar 02 11:06:58 2013 -0400 @@ -33,7 +33,7 @@ public static void main(String... args) { int exitCode = 0; ScriptEngine engine = - (new ScriptEngineManager()).getEngineByName("js"); + (new ScriptEngineManager()).getEngineByName("nashorn"); if (engine == null && !(System.getProperty("java.runtime.name").startsWith("Java(TM)"))) {
--- a/test/sun/tools/jrunscript/jrunscript-DTest.sh Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/jrunscript-DTest.sh Sat Mar 02 11:06:58 2013 -0400 @@ -43,7 +43,7 @@ # to script as java.lang.System property. sysProps is # jrunscript shell built-in variable for System properties. -${JRUNSCRIPT} -Djrunscript.foo=bar <<EOF +${JRUNSCRIPT} -l nashorn -Djrunscript.foo=bar <<EOF if (sysProps["jrunscript.foo"] == "bar") { println("Passed"); exit(0); } // unexpected value println("Unexpected System property value");
--- a/test/sun/tools/jrunscript/jrunscript-argsTest.sh Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/jrunscript-argsTest.sh Sat Mar 02 11:06:58 2013 -0400 @@ -41,7 +41,7 @@ # we check whether "excess" args are passed as script arguments -${JRUNSCRIPT} -J-Djava.awt.headless=true -f - hello world <<EOF +${JRUNSCRIPT} -l nashorn -J-Djava.awt.headless=true -f - hello world <<EOF if (typeof(arguments) == 'undefined') { println("arguments expected"); exit(1); }
--- a/test/sun/tools/jrunscript/jrunscript-cpTest.sh Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/jrunscript-cpTest.sh Sat Mar 02 11:06:58 2013 -0400 @@ -46,7 +46,7 @@ # work with jrunscript. Script should be able to # access Java class "Hello". -${JRUNSCRIPT} -cp . <<EOF +${JRUNSCRIPT} -l nashorn -cp . <<EOF var v; try { v = new Packages.Hello(); } catch (e) { println(e); exit(1) } if (v.string != 'hello') { println("Unexpected property value"); exit(1); } @@ -58,7 +58,7 @@ # -classpath and -cp are synonyms -${JRUNSCRIPT} -classpath . <<EOF +${JRUNSCRIPT} -l nashorn -classpath . <<EOF var v; try { v = new Packages.Hello(); } catch (e) { println(e); exit(1) } if (v.string != 'hello') { println("unexpected property value"); exit(1); }
--- a/test/sun/tools/jrunscript/jrunscript-eTest.sh Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/jrunscript-eTest.sh Sat Mar 02 11:06:58 2013 -0400 @@ -39,21 +39,10 @@ exit 0 fi -rm -f jrunscript-eTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -e "println('hello')" > jrunscript-eTest.out 2>&1 - -$golden_diff jrunscript-eTest.out ${TESTSRC}/dash-e.out -if [ $? != 0 ] -then - echo "Output of jrunscript -e differ from expected output. Failed." - rm -f jrunscript-eTest.out 2>/dev/null - exit 1 -fi - # -e option with JavaScript explicitly choosen as language rm -f jrunscript-eTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -l js -e "println('hello')" > jrunscript-eTest.out 2>&1 +${JRUNSCRIPT} -J-Djava.awt.headless=true -l nashorn -e "println('hello')" > jrunscript-eTest.out 2>&1 $golden_diff jrunscript-eTest.out ${TESTSRC}/dash-e.out if [ $? != 0 ]
--- a/test/sun/tools/jrunscript/jrunscript-fTest.sh Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/jrunscript-fTest.sh Sat Mar 02 11:06:58 2013 -0400 @@ -39,22 +39,11 @@ exit 0 fi -rm -f jrunscript-fTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 - -$golden_diff jrunscript-fTest.out ${TESTSRC}/dash-f.out -if [ $? != 0 ] -then - echo "Output of jrunscript -f differ from expected output. Failed." - rm -f jrunscript-fTest.out 2>/dev/null - exit 1 -fi - # -f option used with JavaScript as language chosen explicitly # with -l option rm -f jrunscript-fTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -l js -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 +${JRUNSCRIPT} -J-Djava.awt.headless=true -l nashorn -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 $golden_diff jrunscript-fTest.out ${TESTSRC}/dash-f.out if [ $? != 0 ]
--- a/test/sun/tools/jrunscript/jrunscriptTest.sh Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/jrunscriptTest.sh Sat Mar 02 11:06:58 2013 -0400 @@ -40,7 +40,7 @@ fi rm -f jrunscriptTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true > jrunscriptTest.out 2>&1 <<EOF +${JRUNSCRIPT} -J-Djava.awt.headless=true -l nashorn > jrunscriptTest.out 2>&1 <<EOF v = 2 + 5; v *= 5; v = v + " is the value"; @@ -52,25 +52,7 @@ $golden_diff jrunscriptTest.out ${TESTSRC}/repl.out if [ $? != 0 ] then - echo "Output of jrunscript session differ from expected output. Failed." - rm -f jrunscriptTest.out 2>/dev/null - exit 1 -fi - -rm -f jrunscriptTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -l js > jrunscriptTest.out 2>&1 <<EOF -v = 2 + 5; -v *= 5; -v = v + " is the value"; -if (v != 0) { println('yes v != 0'); } -java.lang.System.out.println('hello world from script'); -new java.lang.Runnable() { run: function() { println('I am runnable'); }}.run(); -EOF - -$golden_diff jrunscriptTest.out ${TESTSRC}/repl.out -if [ $? != 0 ] -then - echo "Output of jrunscript -l js differ from expected output. Failed." + echo "Output of jrunscript -l nashorn differ from expected output. Failed." rm -f jrunscriptTest.out 2>/dev/null exit 1 fi
--- a/test/sun/tools/jrunscript/repl.out Fri Feb 22 23:36:47 2013 -0400 +++ b/test/sun/tools/jrunscript/repl.out Sat Mar 02 11:06:58 2013 -0400 @@ -1,7 +1,7 @@ -js> 7.0 -js> 35.0 -js> 35 is the value -js> yes v != 0 -js> hello world from script -js> I am runnable -js> \ No newline at end of file +nashorn> 7 +nashorn> 35.0 +nashorn> 35 is the value +nashorn> yes v != 0 +nashorn> hello world from script +nashorn> I am runnable +nashorn> \ No newline at end of file
--- a/test/tools/launcher/I18NJarTest.java Fri Feb 22 23:36:47 2013 -0400 +++ b/test/tools/launcher/I18NJarTest.java Sat Mar 02 11:06:58 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -52,6 +52,8 @@ private static final File cwd = new File("."); private static final File dir = new File("\uFF66\uFF67\uFF68\uFF69"); private static final String encoding = System.getProperty("sun.jnu.encoding", ""); + private static final String LANG = System.getenv("LANG"); + private static final String LC_ALL = System.getenv("LC_ALL"); public static void main(String... args) throws Exception { boolean localeAvailable = false; @@ -63,7 +65,16 @@ } if (!localeAvailable) { System.out.println("Warning: locale: " + Locale.JAPAN - + " not found, test passes vacuosly"); + + " not found, test passes vacuously"); + return; + } + if ("C".equals(LC_ALL) || "C".equals(LANG)) { + System.out.println("Warning: The LANG and/or LC_ALL env vars are " + + "set to \"C\":\n" + + " LANG=" + LANG + "\n" + + " LC_ALL=" + LC_ALL + "\n" + + "This test requires support for multi-byte filenames.\n" + + "Test passes vacuously."); return; } if (encoding.equals("MS932") || encoding.equals("UTF-8")) { @@ -73,7 +84,7 @@ } else { System.out.println("Warning: current encoding is " + encoding + "this test requires MS932 <Ja> or UTF-8," + - " test passes vacuosly"); + " test passes vacuously"); return; } dir.mkdir();