--- a/jdk/make/tools/src/build/tools/deps/refs.allowed Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/makefiles/CreateJars.gmk Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/makefiles/Images.gmk Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/makefiles/profile-rtjar-includes.txt Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/Deprecated.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/Override.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/SafeVarargs.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/SecurityManager.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/SuppressWarnings.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/annotation/Inherited.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/src/share/classes/java/lang/annotation/Retention.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/annotation/Target.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/nio/file/Files.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/util/IdentityHashMap.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/util/function/BinaryOperator.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/provider/PolicyFile.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/src/share/classes/sun/security/ssl/CipherBox.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/EngineWriter.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/Handshaker.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/InputRecord.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/JsseJce.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/MAC.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/OutputRecord.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/Record.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/classes/sun/security/util/SecurityConstants.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/native/java/lang/System.c Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/share/native/java/lang/java_props.h Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/src/solaris/native/java/lang/java_props_md.c Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/ProblemList.txt Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/java/lang/SecurityManager/NoAWT.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/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/jdk/test/java/lang/invoke/lambda/LambdaSerialization.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/java/nio/file/Files/CopyAndMove.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/test/javax/script/CauseExceptionTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/test/javax/script/GetInterfaceTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/Helper.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/test/javax/script/StringWriterPrintTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/Test3.js Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/Test5.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/Test5.js Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/Test6.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/Test7.js Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/UnescapedBracketRegExTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/javax/script/VersionTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/security/ec/TestEC.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/security/pkcs11/fips/CipherTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/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/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/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/jdk/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/security/ssl/sanity/interop/CipherTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/CheckEngine.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/sun/tools/jrunscript/repl.out Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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/jdk/test/tools/launcher/I18NJarTest.java Fri Feb 22 23:36:47 2013 -0400
+++ b/jdk/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();