Mercurial > hg > shenandoah-preopenjdk-archive > openjdk8 > jdk
changeset 10182:69055f4e04d5
Merge
author | asaha |
---|---|
date | Mon, 06 Oct 2014 15:51:21 -0700 |
parents | 5bea9ebf6f4f (current diff) 064adeb65ce8 (diff) |
children | d20e9d18bdc1 |
files | .hgtags make/lib/CoreLibraries.gmk src/share/classes/java/lang/invoke/MethodType.java src/share/classes/sun/awt/SunToolkit.java src/share/classes/sun/security/ssl/Handshaker.java src/solaris/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c |
diffstat | 54 files changed, 2571 insertions(+), 669 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed Sep 24 14:39:21 2014 -0700 +++ b/.hgtags Mon Oct 06 15:51:21 2014 -0700 @@ -341,3 +341,4 @@ d587834579dadd18cb8b096e61d92e2dbccc2782 jdk8u40-b05 25788892a6723c0742a24050cc25ab103d9804de jdk8u40-b06 07f0e22b5c238dd7b89fedbed35f02ac6b392c96 jdk8u40-b07 +0f0d70abca09b4ddb0981204ad5a427d4ce935e9 jdk8u40-b08
--- a/make/lib/CoreLibraries.gmk Wed Sep 24 14:39:21 2014 -0700 +++ b/make/lib/CoreLibraries.gmk Mon Oct 06 15:51:21 2014 -0700 @@ -129,9 +129,9 @@ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/common \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/java/util -ifneq ($(OPENJDK_TARGET_OS), macosx) +ifeq ($(OPENJDK_TARGET_OS), windows) LIBJAVA_SRC_DIRS += $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/util/locale/provider -else +else ifeq ($(OPENJDK_TARGET_OS), macosx) LIBJAVA_SRC_DIRS += $(JDK_TOPDIR)/src/macosx/native/sun/util/locale/provider endif
--- a/make/mapfiles/libjava/mapfile-vers Wed Sep 24 14:39:21 2014 -0700 +++ b/make/mapfiles/libjava/mapfile-vers Mon Oct 06 15:51:21 2014 -0700 @@ -287,8 +287,6 @@ # Java_sun_misc_VM_unsuspendSomeThreads; threads.c # Java_sun_misc_VM_unsuspendThreads; threads.c - Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPattern; - # Outcalls from libjvm done using dlsym(). VerifyClassCodes;
--- a/src/macosx/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Wed Sep 24 14:39:21 2014 -0700 +++ b/src/macosx/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Mon Oct 06 15:51:21 2014 -0700 @@ -24,6 +24,7 @@ */ #include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h" +#include "jni_util.h" #include <CoreFoundation/CoreFoundation.h> #include <stdio.h> @@ -63,6 +64,10 @@ localeString = getMacOSXLocale(posixCat); if (localeString == NULL) { localeString = getPosixLocale(posixCat); + if (localeString == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + return NULL; + } } ret = (*env)->NewStringUTF(env, localeString); free(localeString); @@ -127,6 +132,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { CFLocaleRef cflocale = CFLocaleCopyCurrent(); + jstring tmp_string; if (cflocale != NULL) { CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, cflocale, @@ -138,13 +144,21 @@ if (amStr != NULL) { CFStringGetCString(amStr, buf, BUFLEN, kCFStringEncodingUTF8); CFRelease(amStr); - (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewStringUTF(env, buf)); + tmp_string = (*env)->NewStringUTF(env, buf); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 0, tmp_string); + } } - CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol); - if (pmStr != NULL) { - CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8); - CFRelease(pmStr); - (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewStringUTF(env, buf)); + if (!(*env)->ExceptionCheck(env)){ + CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol); + if (pmStr != NULL) { + CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8); + CFRelease(pmStr); + tmp_string = (*env)->NewStringUTF(env, buf); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 1, tmp_string); + } + } } CFRelease(df); } @@ -647,10 +661,16 @@ static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count) { char buf[BUFLEN]; + jstring tmp_string; for (; count > 0; sindex++, dindex++, count--) { CFStringGetCString(CFArrayGetValueAtIndex(cfarray, sindex), buf, BUFLEN, kCFStringEncodingUTF8); - (*env)->SetObjectArrayElement(env, jarray, dindex, (*env)->NewStringUTF(env, buf)); + tmp_string = (*env)->NewStringUTF(env, buf); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, jarray, dindex, tmp_string); + } else { + break; + } } }
--- a/src/share/classes/java/io/ByteArrayOutputStream.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/java/io/ByteArrayOutputStream.java Mon Oct 06 15:51:21 2014 -0700 @@ -94,6 +94,14 @@ } /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * @@ -105,14 +113,19 @@ int newCapacity = oldCapacity << 1; if (newCapacity - minCapacity < 0) newCapacity = minCapacity; - if (newCapacity < 0) { - if (minCapacity < 0) // overflow - throw new OutOfMemoryError(); - newCapacity = Integer.MAX_VALUE; - } + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); buf = Arrays.copyOf(buf, newCapacity); } + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; + } + /** * Writes the specified byte to this byte array output stream. *
--- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java Mon Oct 06 15:51:21 2014 -0700 @@ -188,7 +188,6 @@ static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, boolean strict, boolean monobox) { MethodType dstType = target.type(); - assert(dstType.parameterCount() == target.type().parameterCount()); if (srcType == dstType) return target; if (USE_LAMBDA_FORM_EDITOR) { @@ -265,6 +264,7 @@ static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType, boolean strict, boolean monobox) { + assert(target.type().parameterCount() == srcType.parameterCount()); // Calculate extra arguments (temporaries) required in the names array. Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); final int INARG_COUNT = srcType.parameterCount();
--- a/src/share/classes/java/lang/invoke/MethodHandles.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Mon Oct 06 15:51:21 2014 -0700 @@ -2024,12 +2024,22 @@ */ public static MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { - if (!target.type().isCastableTo(newType)) { - throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType); + explicitCastArgumentsChecks(target, newType); + // use the asTypeCache when possible: + MethodType oldType = target.type(); + if (oldType == newType) return target; + if (oldType.explicitCastEquivalentToAsType(newType)) { + return target.asType(newType); } return MethodHandleImpl.makePairwiseConvert(target, newType, false); } + private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) { + if (target.type().parameterCount() != newType.parameterCount()) { + throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType); + } + } + /** * Produces a method handle which adapts the calling sequence of the * given method handle to a new type, by reordering the arguments. @@ -2162,7 +2172,7 @@ // dropIdx is missing from reorder; add it in at the end int oldArity = reorder.length; target = dropArguments(target, oldArity, newType.parameterType(dropIdx)); - reorder = Arrays.copyOf(reorder, oldArity+1); + reorder = Arrays.copyOf(reorder, oldArity + 1); reorder[oldArity] = dropIdx; } assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type())); @@ -2180,9 +2190,9 @@ long mask = 0; for (int arg : reorder) { assert(arg < newArity); - mask |= (1 << arg); + mask |= (1L << arg); } - if (mask == (1 << newArity) - 1) { + if (mask == (1L << newArity) - 1) { assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); return -1; } @@ -2191,16 +2201,18 @@ int zeroPos = Long.numberOfTrailingZeros(zeroBit); assert(zeroPos < newArity); return zeroPos; + } else { + BitSet mask = new BitSet(newArity); + for (int arg : reorder) { + assert (arg < newArity); + mask.set(arg); + } + int zeroPos = mask.nextClearBit(0); + assert(zeroPos <= newArity); + if (zeroPos == newArity) + return -1; + return zeroPos; } - BitSet mask = new BitSet(newArity); - for (int arg : reorder) { - assert(arg < newArity); - mask.set(arg); - } - int zeroPos = mask.nextClearBit(0); - if (zeroPos == newArity) - return -1; - return zeroPos; } /** @@ -2216,32 +2228,42 @@ long mask = 0; for (int i = 0; i < reorder.length; i++) { int arg = reorder[i]; - if (arg >= newArity) return reorder.length; - int bit = 1 << arg; - if ((mask & bit) != 0) + if (arg >= newArity) { + return reorder.length; + } + long bit = 1L << arg; + if ((mask & bit) != 0) { return i; // >0 indicates a dup + } mask |= bit; } - if (mask == (1 << newArity) - 1) { + if (mask == (1L << newArity) - 1) { assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); return 0; } // find first zero long zeroBit = Long.lowestOneBit(~mask); int zeroPos = Long.numberOfTrailingZeros(zeroBit); - assert(zeroPos < newArity); + assert(zeroPos <= newArity); + if (zeroPos == newArity) { + return 0; + } return ~zeroPos; } else { // same algorithm, different bit set BitSet mask = new BitSet(newArity); for (int i = 0; i < reorder.length; i++) { int arg = reorder[i]; - if (arg >= newArity) return reorder.length; - if (mask.get(arg)) + if (arg >= newArity) { + return reorder.length; + } + if (mask.get(arg)) { return i; // >0 indicates a dup + } mask.set(arg); } int zeroPos = mask.nextClearBit(0); + assert(zeroPos <= newArity); if (zeroPos == newArity) { return 0; } @@ -2477,6 +2499,7 @@ MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) { MethodType oldType = target.type(); // get NPE int dropped = dropArgumentChecks(oldType, pos, valueTypes); + MethodType newType = oldType.insertParameterTypes(pos, valueTypes); if (dropped == 0) return target; BoundMethodHandle result = target.rebind(); LambdaForm lform = result.form; @@ -2488,7 +2511,6 @@ } else { lform = lform.addArguments(pos, valueTypes); } - MethodType newType = oldType.insertParameterTypes(pos, valueTypes); result = result.copyWith(newType, lform); return result; }
--- a/src/share/classes/java/lang/invoke/MethodType.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodType.java Mon Oct 06 15:51:21 2014 -0700 @@ -827,26 +827,6 @@ return true; } /*non-public*/ - boolean isCastableTo(MethodType newType) { - MethodTypeForm oldForm = this.form(); - MethodTypeForm newForm = newType.form(); - if (oldForm == newForm) - // same parameter count, same primitive/object mix - return true; - int argc = parameterCount(); - if (argc != newType.parameterCount()) - return false; - // Corner case: boxing (primitive-to-reference) must have a plausible target type - // Therefore, we may have to return false for a boxing operation. - if (!canCast(returnType(), newType.returnType())) - return false; - if (newForm.primitiveParameterCount() == 0) - return true; // no primitive sources to mess things up - if (oldForm.erasedType == this) - return true; // no funny target references to mess things up - return canCastParameters(newType.ptypes, ptypes); - } - /*non-public*/ boolean isConvertibleTo(MethodType newType) { MethodTypeForm oldForm = this.form(); MethodTypeForm newForm = newType.form(); @@ -877,15 +857,66 @@ return canConvertParameters(srcTypes, dstTypes); } - private boolean canCastParameters(Class<?>[] srcTypes, Class<?>[] dstTypes) { - for (int i = 0; i < srcTypes.length; i++) { - if (!canCast(srcTypes[i], dstTypes[i])) { + /** Returns true if MHs.explicitCastArguments produces the same result as MH.asType. + * If the type conversion is impossible for either, the result should be false. + */ + /*non-public*/ + boolean explicitCastEquivalentToAsType(MethodType newType) { + if (this == newType) return true; + if (!explicitCastEquivalentToAsType(rtype, newType.rtype)) { + return false; + } + Class<?>[] srcTypes = newType.ptypes; + Class<?>[] dstTypes = ptypes; + if (dstTypes == srcTypes) { + return true; + } + assert(dstTypes.length == srcTypes.length); + for (int i = 0; i < dstTypes.length; i++) { + if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) { return false; } } return true; } + /** Reports true if the src can be converted to the dst, by both asType and MHs.eCE, + * and with the same effect. + * MHs.eCA has the following "upgrades" to MH.asType: + * 1. interfaces are unchecked (that is, treated as if aliased to Object) + * Therefore, {@code Object->CharSequence} is possible in both cases but has different semantics + * 2. the full matrix of primitive-to-primitive conversions is supported + * Narrowing like {@code long->byte} and basic-typing like {@code boolean->int} + * are not supported by asType, but anything supported by asType is equivalent + * with MHs.eCE. + * 3a. unboxing conversions can be followed by the full matrix of primitive conversions + * 3b. unboxing of null is permitted (creates a zero primitive value) + * Most unboxing conversions, like {@code Object->int}, has potentially + * different behaviors for asType vs. MHs.eCE, because the dynamic value + * might be a wrapper of a type that requires narrowing, like {@code (Object)1L->byte}. + * The equivalence is only certain if the static src type is a wrapper, + * and the conversion will be a widening one. + * Other than interfaces, reference-to-reference conversions are the same. + * Boxing primitives to references is the same for both operators. + */ + private static boolean explicitCastEquivalentToAsType(Class<?> src, Class<?> dst) { + if (src == dst || dst == Object.class || dst == void.class) return true; + if (src.isPrimitive()) { + // Could be a prim/prim conversion, where casting is a strict superset. + // Or a boxing conversion, which is always to an exact wrapper class. + return canConvert(src, dst); + } else if (dst.isPrimitive()) { + Wrapper dw = Wrapper.forPrimitiveType(dst); + // Watch out: If src is Number or Object, we could get dynamic narrowing conversion. + // The conversion is known to be widening only if the wrapper type is statically visible. + return (Wrapper.isWrapperType(src) && + dw.isConvertibleFrom(Wrapper.forWrapperType(src))); + } else { + // R->R always works, but we have to avoid a check-cast to an interface. + return !dst.isInterface() || dst.isAssignableFrom(src); + } + } + private boolean canConvertParameters(Class<?>[] srcTypes, Class<?>[] dstTypes) { for (int i = 0; i < srcTypes.length; i++) { if (!canConvert(srcTypes[i], dstTypes[i])) { @@ -895,16 +926,6 @@ return true; } - private static boolean canCast(Class<?> src, Class<?> dst) { - if (src.isPrimitive() && !dst.isPrimitive()) { - if (dst == Object.class || dst.isInterface()) return true; - // Here is the corner case that is not castable. Example: int -> String - Wrapper sw = Wrapper.forPrimitiveType(src); - return dst.isAssignableFrom(sw.wrapperType()); - } - return true; - } - /*non-public*/ static boolean canConvert(Class<?> src, Class<?> dst) { // short-circuit a few cases:
--- a/src/share/classes/java/lang/reflect/Constructor.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/java/lang/reflect/Constructor.java Mon Oct 06 15:51:21 2014 -0700 @@ -557,33 +557,15 @@ */ @Override public AnnotatedType getAnnotatedReceiverType() { - Class<?> thisDeclClass = getDeclaringClass(); - Class<?> enclosingClass = thisDeclClass.getEnclosingClass(); - - if (enclosingClass == null) { - // A Constructor for a top-level class - return null; - } + if (getDeclaringClass().getEnclosingClass() == null) + return super.getAnnotatedReceiverType(); - Class<?> outerDeclaringClass = thisDeclClass.getDeclaringClass(); - if (outerDeclaringClass == null) { - // A constructor for a local or anonymous class - return null; - } - - // Either static nested or inner class - if (Modifier.isStatic(thisDeclClass.getModifiers())) { - // static nested - return null; - } - - // A Constructor for an inner class return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(thisDeclClass), + getConstantPool(getDeclaringClass()), this, - thisDeclClass, - enclosingClass, + getDeclaringClass(), + getDeclaringClass().getEnclosingClass(), TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } }
--- a/src/share/classes/java/lang/reflect/Executable.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/java/lang/reflect/Executable.java Mon Oct 06 15:51:21 2014 -0700 @@ -602,24 +602,21 @@ /** * Returns an {@code AnnotatedType} object that represents the use of a * type to specify the receiver type of the method/constructor represented - * by this {@code Executable} object. + * by this Executable object. The receiver type of a method/constructor is + * available only if the method/constructor has a <em>receiver + * parameter</em> (JLS 8.4.1). * - * The receiver type of a method/constructor is available only if the - * method/constructor has a receiver parameter (JLS 8.4.1). If this {@code - * Executable} object <em>represents an instance method or represents a - * constructor of an inner member class</em>, and the - * method/constructor <em>either</em> has no receiver parameter or has a - * receiver parameter with no annotations on its type, then the return - * value is an {@code AnnotatedType} object representing an element with no + * If this {@code Executable} object represents a constructor or instance + * method that does not have a receiver parameter, or has a receiver + * parameter with no annotations on its type, then the return value is an + * {@code AnnotatedType} object representing an element with no * annotations. * - * If this {@code Executable} object represents a static method or - * represents a constructor of a top level, static member, local, or - * anoymous class, then the return value is null. + * If this {@code Executable} object represents a static method, then the + * return value is null. * * @return an object representing the receiver type of the method or - * constructor represented by this {@code Executable} or {@code null} if - * this {@code Executable} can not have a receiver parameter + * constructor represented by this {@code Executable} * * @since 1.8 */
--- a/src/share/classes/java/math/MutableBigInteger.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/java/math/MutableBigInteger.java Mon Oct 06 15:51:21 2014 -0700 @@ -1261,19 +1261,20 @@ int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n} MutableBigInteger bShifted = new MutableBigInteger(b); bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n - safeLeftShift(sigma); // step 4b: shift this by the same amount + MutableBigInteger aShifted = new MutableBigInteger (this); + aShifted.safeLeftShift(sigma); // step 4b: shift a by the same amount - // step 5: t is the number of blocks needed to accommodate this plus one additional bit - int t = (int) ((bitLength()+n32) / n32); + // step 5: t is the number of blocks needed to accommodate a plus one additional bit + int t = (int) ((aShifted.bitLength()+n32) / n32); if (t < 2) { t = 2; } - // step 6: conceptually split this into blocks a[t-1], ..., a[0] - MutableBigInteger a1 = getBlock(t-1, t, n); // the most significant block of this + // step 6: conceptually split a into blocks a[t-1], ..., a[0] + MutableBigInteger a1 = aShifted.getBlock(t-1, t, n); // the most significant block of a // step 7: z[t-2] = [a[t-1], a[t-2]] - MutableBigInteger z = getBlock(t-2, t, n); // the second to most significant block + MutableBigInteger z = aShifted.getBlock(t-2, t, n); // the second to most significant block z.addDisjoint(a1, n); // z[t-2] // do schoolbook division on blocks, dividing 2-block numbers by 1-block numbers @@ -1284,7 +1285,7 @@ ri = z.divide2n1n(bShifted, qi); // step 8b: z = [ri, a[i-1]] - z = getBlock(i-1, t, n); // a[i-1] + z = aShifted.getBlock(i-1, t, n); // a[i-1] z.addDisjoint(ri, n); quotient.addShifted(qi, i*n); // update q (part of step 9) } @@ -1292,7 +1293,7 @@ ri = z.divide2n1n(bShifted, qi); quotient.add(qi); - ri.rightShift(sigma); // step 9: this and b were shifted, so shift back + ri.rightShift(sigma); // step 9: a and b were shifted, so shift back return ri; } }
--- a/src/share/classes/javax/management/remote/rmi/RMIConnector.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/javax/management/remote/rmi/RMIConnector.java Mon Oct 06 15:51:21 2014 -0700 @@ -1335,66 +1335,94 @@ int maxNotifications, long timeout) throws IOException, ClassNotFoundException { - IOException org; + boolean retried = false; while (true) { // used for a successful re-connection + // or a transient network problem try { return connection.fetchNotifications(clientSequenceNumber, maxNotifications, - timeout); + timeout); // return normally } catch (IOException ioe) { - org = ioe; + // Examine the chain of exceptions to determine whether this + // is a deserialization issue. If so - we propagate the + // appropriate exception to the caller, who will then + // proceed with fetching notifications one by one + rethrowDeserializationException(ioe); - // inform of IOException try { communicatorAdmin.gotIOException(ioe); - - // The connection should be re-established. - continue; + // reconnection OK, back to "while" to do again } catch (IOException ee) { - // No more fetch, the Exception will be re-thrown. - break; - } // never reached - } // never reached - } + boolean toClose = false; - // specially treating for an UnmarshalException - if (org instanceof UnmarshalException) { - UnmarshalException ume = (UnmarshalException)org; - - if (ume.detail instanceof ClassNotFoundException) - throw (ClassNotFoundException) ume.detail; + synchronized (this) { + if (terminated) { + // the connection is closed. + throw ioe; + } else if (retried) { + toClose = true; + } + } - /* In Sun's RMI implementation, if a method return - contains an unserializable object, then we get - UnmarshalException wrapping WriteAbortedException - wrapping NotSerializableException. In that case we - extract the NotSerializableException so that our - caller can realize it should try to skip past the - notification that presumably caused it. It's not - certain that every other RMI implementation will - generate this exact exception sequence. If not, we - will not detect that the problem is due to an - unserializable object, and we will stop trying to - receive notifications from the server. It's not - clear we can do much better. */ - if (ume.detail instanceof WriteAbortedException) { - WriteAbortedException wae = - (WriteAbortedException) ume.detail; - if (wae.detail instanceof IOException) - throw (IOException) wae.detail; + if (toClose) { + // JDK-8049303 + // We received an IOException - but the communicatorAdmin + // did not close the connection - possibly because + // the original exception was raised by a transient network + // problem? + // We already know that this exception is not due to a deserialization + // issue as we already took care of that before involving the + // communicatorAdmin. Moreover - we already made one retry attempt + // at fetching the same batch of notifications - and the + // problem persisted. + // Since trying again doesn't seem to solve the issue, we will now + // close the connection. Doing otherwise might cause the + // NotifFetcher thread to die silently. + final Notification failedNotif = + new JMXConnectionNotification( + JMXConnectionNotification.FAILED, + this, + connectionId, + clientNotifSeqNo++, + "Failed to communicate with the server: " + ioe.toString(), + ioe); + + sendNotification(failedNotif); + + try { + close(true); + } catch (Exception e) { + // OK. + // We are closing + } + throw ioe; // the connection is closed here. + } else { + // JDK-8049303 possible transient network problem, + // let's try one more time + retried = true; + } + } } - } else if (org instanceof MarshalException) { + } + } + + private void rethrowDeserializationException(IOException ioe) + throws ClassNotFoundException, IOException { + // specially treating for an UnmarshalException + if (ioe instanceof UnmarshalException) { + throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs + // fetch one by one with UnmarshalException + } else if (ioe instanceof MarshalException) { // IIOP will throw MarshalException wrapping a NotSerializableException // when a server fails to serialize a response. - MarshalException me = (MarshalException)org; + MarshalException me = (MarshalException)ioe; if (me.detail instanceof NotSerializableException) { throw (NotSerializableException)me.detail; } } - // Not serialization problem, simply re-throw the orginal exception - throw org; + // Not serialization problem, return. } protected Integer addListenerForMBeanRemovedNotif()
--- a/src/share/classes/javax/swing/JComponent.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/javax/swing/JComponent.java Mon Oct 06 15:51:21 2014 -0700 @@ -56,6 +56,7 @@ import java.io.IOException; import java.io.ObjectInputValidation; import java.io.InvalidObjectException; +import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.border.*; import javax.swing.event.*; @@ -352,7 +353,8 @@ private static final int AUTOSCROLLS_SET = 25; private static final int FOCUS_TRAVERSAL_KEYS_FORWARD_SET = 26; private static final int FOCUS_TRAVERSAL_KEYS_BACKWARD_SET = 27; - private static final int REVALIDATE_RUNNABLE_SCHEDULED = 28; + + private transient AtomicBoolean revalidateRunnableScheduled = new AtomicBoolean(false); /** * Temporary rectangles. @@ -4859,16 +4861,11 @@ // To avoid a flood of Runnables when constructing GUIs off // the EDT, a flag is maintained as to whether or not // a Runnable has been scheduled. - synchronized(this) { - if (getFlag(REVALIDATE_RUNNABLE_SCHEDULED)) { - return; - } - setFlag(REVALIDATE_RUNNABLE_SCHEDULED, true); + if (revalidateRunnableScheduled.getAndSet(true)) { + return; } SunToolkit.executeOnEventHandlerThread(this, () -> { - synchronized(JComponent.this) { - setFlag(REVALIDATE_RUNNABLE_SCHEDULED, false); - } + revalidateRunnableScheduled.set(false); revalidate(); }); } @@ -5508,6 +5505,7 @@ ToolTipManager.sharedInstance().registerComponent(this); } setWriteObjCounter(this, (byte)0); + revalidateRunnableScheduled = new AtomicBoolean(false); }
--- a/src/share/classes/javax/swing/text/FlowView.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/javax/swing/text/FlowView.java Mon Oct 06 15:51:21 2014 -0700 @@ -800,14 +800,22 @@ @Override protected void forwardUpdate(DocumentEvent.ElementChange ec, DocumentEvent e, Shape a, ViewFactory f) { - calculateUpdateIndexes(e); - // Send update event to all views followed by the changed place. - lastUpdateIndex = Math.max((getViewCount() - 1), 0); - for (int i = firstUpdateIndex; i <= lastUpdateIndex; i++) { - View v = getView(i); - if (v != null) { - Shape childAlloc = getChildAllocation(i, a); - forwardUpdateToView(v, e, childAlloc, f); + // Update the view responsible for the changed element by invocation of + // super method. + super.forwardUpdate(ec, e, a, f); + // Re-calculate the update indexes and update the views followed by + // the changed place. Note: we update the views only when insertion or + // removal takes place. + DocumentEvent.EventType type = e.getType(); + if (type == DocumentEvent.EventType.INSERT || + type == DocumentEvent.EventType.REMOVE) { + firstUpdateIndex = Math.min((lastUpdateIndex + 1), (getViewCount() - 1)); + lastUpdateIndex = Math.max((getViewCount() - 1), 0); + for (int i = firstUpdateIndex; i <= lastUpdateIndex; i++) { + View v = getView(i); + if (v != null) { + v.updateAfterChange(); + } } } }
--- a/src/share/classes/javax/swing/text/GlyphView.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/javax/swing/text/GlyphView.java Mon Oct 06 15:51:21 2014 -0700 @@ -971,6 +971,14 @@ } } + /** {@inheritDoc} */ + @Override + void updateAfterChange() { + // Drop the break spots. They will be re-calculated during + // layout. It is necessary for proper line break calculation. + breakSpots = null; + } + /** * Class to hold data needed to justify this GlyphView in a PargraphView.Row */
--- a/src/share/classes/javax/swing/text/View.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/javax/swing/text/View.java Mon Oct 06 15:51:21 2014 -0700 @@ -1199,6 +1199,13 @@ } /** + * Updates the view to reflect the changes. + */ + void updateAfterChange() { + // Do nothing by default. Should be overridden in subclasses, if any. + } + + /** * Forwards the <code>DocumentEvent</code> to the give child view. This * simply messages the view with a call to <code>insertUpdate</code>, * <code>removeUpdate</code>, or <code>changedUpdate</code> depending
--- a/src/share/classes/sun/awt/SunToolkit.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/sun/awt/SunToolkit.java Mon Oct 06 15:51:21 2014 -0700 @@ -386,7 +386,7 @@ * null or the target can't be found, a null with be returned. */ public static AppContext targetToAppContext(Object target) { - if (target == null || GraphicsEnvironment.isHeadless()) { + if (target == null) { return null; } AppContext context = getAppContext(target); @@ -460,12 +460,10 @@ * via targetToAppContext() above. */ public static void insertTargetMapping(Object target, AppContext appContext) { - if (!GraphicsEnvironment.isHeadless()) { - if (!setAppContext(target, appContext)) { - // Target is not a Component/MenuComponent, use the private Map - // instead. - appContextMap.put(target, appContext); - } + if (!setAppContext(target, appContext)) { + // Target is not a Component/MenuComponent, use the private Map + // instead. + appContextMap.put(target, appContext); } }
--- a/src/share/classes/sun/security/ssl/Handshaker.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/classes/sun/security/ssl/Handshaker.java Mon Oct 06 15:51:21 2014 -0700 @@ -667,8 +667,15 @@ */ ProtocolList getActiveProtocols() { if (activeProtocols == null) { + boolean enabledSSL20Hello = false; ArrayList<ProtocolVersion> protocols = new ArrayList<>(4); for (ProtocolVersion protocol : enabledProtocols.collection()) { + // Need not to check the SSL20Hello protocol. + if (protocol.v == ProtocolVersion.SSL20Hello.v) { + enabledSSL20Hello = true; + continue; + } + boolean found = false; for (CipherSuite suite : enabledCipherSuites.collection()) { if (suite.isAvailable() && suite.obsoleted > protocol.v && @@ -695,6 +702,11 @@ "No available cipher suite for " + protocol); } } + + if (!protocols.isEmpty() && enabledSSL20Hello) { + protocols.add(ProtocolVersion.SSL20Hello); + } + activeProtocols = new ProtocolList(protocols); }
--- a/src/share/demo/README Wed Sep 24 14:39:21 2014 -0700 +++ b/src/share/demo/README Mon Oct 06 15:51:21 2014 -0700 @@ -4,3 +4,12 @@ production-quality application, such as security checks, input validation, and proper error handling, might not be present in the sample code. + +In some cases, the default security settings may block an execution +of demo applets in a browser. To adjust the security settings, please +refer to the following resource: + +http://java.com/en/download/help/java_blocked.xml + +Some demo applets need to be accessed through the HTTP or HTTPS +protocols to enable access to the required resources.
--- a/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/solaris/classes/sun/java2d/xr/XRSolidSrcPict.java Mon Oct 06 15:51:21 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,12 +31,14 @@ XRSurfaceData srcPict; XRColor xrCol; - int curPixVal = -1; + int curPixVal; public XRSolidSrcPict(XRBackend con, int parentXid) { this.con = con; xrCol = new XRColor(); + curPixVal = 0xFF000000; + int solidPixmap = con.createPixmap(parentXid, 32, 1, 1); int solidSrcPictXID = con.createPicture(solidPixmap, XRUtils.PictStandardARGB32); con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal);
--- a/src/solaris/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java Wed Sep 24 14:39:21 2014 -0700 +++ b/src/solaris/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java Mon Oct 06 15:51:21 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,100 +25,10 @@ package sun.util.locale.provider; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.text.spi.DateFormatProvider; -import java.util.Locale; - /** * LocaleProviderAdapter implementation for the Unix locale data * * @author Naoto Sato */ public class HostLocaleProviderAdapterImpl { - static Locale[] supported = {Locale.getDefault(Locale.Category.FORMAT)}; - - public static DateFormatProvider getDateFormatProvider() { - return new DateFormatProvider() { - String posixPattern; - - @Override - public Locale[] getAvailableLocales() { - // not implemented yet - return new Locale[0]; } - @Override - public DateFormat getDateInstance(int style, Locale locale) { - posixPattern = getPattern(style, -1, locale.toLanguageTag()); - return new SimpleDateFormat(convertPosixToJava(posixPattern), locale); - } - @Override - public DateFormat getTimeInstance(int style, Locale locale) { - posixPattern = getPattern(-1, style, locale.toLanguageTag()); - return new SimpleDateFormat(convertPosixToJava(posixPattern), locale); - } - @Override - public DateFormat getDateTimeInstance(int dateStyle, - int timeStyle, Locale locale) { - posixPattern = getPattern(dateStyle, timeStyle, locale.toLanguageTag()); - return new SimpleDateFormat(convertPosixToJava(posixPattern), locale); - } - }; - } - - private static String convertPosixToJava(String posixPattern) { - StringBuilder sb = new StringBuilder(); - boolean conversion = false; - - for (int index = 0; index < posixPattern.length(); index++) { - char c = posixPattern.charAt(index); - if (conversion) { - switch (c) { - case 'a': - sb.append("EEE"); - break; - case 'b': - sb.append("MMM"); - break; - case 'e': - sb.append("dd"); - break; - case 'H': - sb.append("kk"); - break; - case 'M': - sb.append("mm"); - break; - case 'S': - sb.append("ss"); - break; - case 'Y': - sb.append("yyyy"); - break; - case 'm': - sb.append("MM"); - break; - case 'd': - sb.append("dd"); - break; - case 'r': - sb.append("hh:mm:ss aa"); - break; - case 'Z': - sb.append("zzz"); - break; - } - conversion = false; - } else { - if (c == '%') { - conversion = true; - } else { - sb.append(c); - } - } - } - return sb.toString(); - } - - private static native String getPattern(int dateStyle, int timeStyle, String langtag); -}
--- a/src/solaris/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Wed Sep 24 14:39:21 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * 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. - */ - -#include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h" -#include <gdefs.h> -#include <string.h> -#include <langinfo.h> -#include <locale.h> - -#define BUFLEN 64 - -/* - * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl - * Method: getPattern - * Signature: (IILjava/lang/String;)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPattern - (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) { - - // TEMPORARY! - char locale[BUFLEN]; - char * pch; - char * old; - char * ret; - const char *langtag = (*env)->GetStringUTFChars(env, jlangtag, JNI_FALSE); - - strcpy(locale, langtag); - pch = strchr(locale, '-'); - if (pch != NULL) { - *pch = '_'; - } - pch = strchr(locale, '-'); - if (pch != NULL) { - *pch = '\0'; - } - strcat(locale, ".UTF-8"); - old = setlocale(LC_TIME, ""); - setlocale(LC_TIME, locale); - - if (dateStyle != (-1) && timeStyle != (-1)) { - ret = nl_langinfo(D_T_FMT); - } else if (dateStyle != (-1)) { - ret = nl_langinfo(D_FMT); - } else if (timeStyle != (-1)) { - ret = nl_langinfo(T_FMT); - } else { - ret = "yyyy/MM/dd"; - } - - setlocale(LC_TIME, old); - - (*env)->ReleaseStringUTFChars(env, jlangtag, langtag); - - return (*env)->NewStringUTF(env, ret); -}
--- a/src/windows/native/java/lang/java_props_md.c Wed Sep 24 14:39:21 2014 -0700 +++ b/src/windows/native/java/lang/java_props_md.c Mon Oct 06 15:51:21 2014 -0700 @@ -28,6 +28,9 @@ #define _WIN32_WINNT 0x0601 #endif +#include "jni.h" +#include "jni_util.h" + #include <windows.h> #include <shlobj.h> #include <objidl.h> @@ -51,7 +54,7 @@ #endif typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); -static void SetupI18nProps(LCID lcid, char** language, char** script, char** country, +static boolean SetupI18nProps(LCID lcid, char** language, char** script, char** country, char** variant, char** encoding); #define PROPSIZE 9 // eight-letter + null terminator @@ -60,8 +63,11 @@ static char * getEncodingInternal(LCID lcid) { + int codepage; char * ret = malloc(16); - int codepage; + if (ret == NULL) { + return NULL; + } if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, @@ -132,7 +138,11 @@ static char* getConsoleEncoding() { char* buf = malloc(16); - int cp = GetConsoleCP(); + int cp; + if (buf == NULL) { + return NULL; + } + cp = GetConsoleCP(); if (cp >= 874 && cp <= 950) sprintf(buf, "ms%d", cp); else @@ -152,11 +162,16 @@ getJavaIDFromLangID(LANGID langID) { char * elems[5]; // lang, script, ctry, variant, encoding - char * ret = malloc(SNAMESIZE); + char * ret; int index; - SetupI18nProps(MAKELCID(langID, SORT_DEFAULT), - &(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4])); + ret = malloc(SNAMESIZE); + if (ret == NULL) { + return NULL; + } + + if (SetupI18nProps(MAKELCID(langID, SORT_DEFAULT), + &(elems[0]), &(elems[1]), &(elems[2]), &(elems[3]), &(elems[4]))) { // there always is the "language" tag strcpy(ret, elems[0]); @@ -172,6 +187,9 @@ for (index = 0; index < 5; index++) { free(elems[index]); } + } else { + ret = NULL; + } return ret; } @@ -259,12 +277,15 @@ return NULL; } -static void +static boolean SetupI18nProps(LCID lcid, char** language, char** script, char** country, char** variant, char** encoding) { /* script */ char tmp[SNAMESIZE]; *script = malloc(PROPSIZE); + if (*script == NULL) { + return FALSE; + } if (GetLocaleInfo(lcid, LOCALE_SNAME, tmp, SNAMESIZE) == 0 || sscanf(tmp, "%*[a-z\\-]%1[A-Z]%[a-z]", *script, &((*script)[1])) == 0 || @@ -274,6 +295,9 @@ /* country */ *country = malloc(PROPSIZE); + if (*country == NULL) { + return FALSE; + } if (GetLocaleInfo(lcid, LOCALE_SISO3166CTRYNAME, *country, PROPSIZE) == 0 && GetLocaleInfo(lcid, @@ -283,6 +307,9 @@ /* language */ *language = malloc(PROPSIZE); + if (*language == NULL) { + return FALSE; + } if (GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME, *language, PROPSIZE) == 0 && GetLocaleInfo(lcid, @@ -294,6 +321,9 @@ /* variant */ *variant = malloc(PROPSIZE); + if (*variant == NULL) { + return FALSE; + } (*variant)[0] = '\0'; /* handling for Norwegian */ @@ -308,6 +338,10 @@ /* encoding */ *encoding = getEncodingInternal(lcid); + if (*encoding == NULL) { + return FALSE; + } + return TRUE; } java_props_t *
--- a/src/windows/native/java/net/NetworkInterface.c Wed Sep 24 14:39:21 2014 -0700 +++ b/src/windows/native/java/net/NetworkInterface.c Mon Oct 06 15:51:21 2014 -0700 @@ -1014,9 +1014,11 @@ case MIB_IF_TYPE_FDDI: case IF_TYPE_IEEE80211: len = ifRowP->dwPhysAddrLen; - ret = (*env)->NewByteArray(env, len); - if (!IS_NULL(ret)) { - (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr); + if (len > 0) { + ret = (*env)->NewByteArray(env, len); + if (!IS_NULL(ret)) { + (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr); + } } break; }
--- a/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c Wed Sep 24 14:39:21 2014 -0700 +++ b/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c Mon Oct 06 15:51:21 2014 -0700 @@ -23,6 +23,7 @@ * questions. */ #include <windows.h> +#include <Sddl.h> #include <string.h> #include "jni.h" @@ -258,6 +259,25 @@ HANDLE hPipe; char name[MAX_PIPE_NAME_LENGTH]; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + // Custom Security Descriptor is required here to "get" Medium Integrity Level. + // In order to allow Medium Integrity Level clients to open + // and use a NamedPipe created by an High Integrity Level process. + TCHAR *szSD = TEXT("D:") // Discretionary ACL + TEXT("(A;OICI;GRGW;;;WD)") // Allow read/write to Everybody + TEXT("(A;OICI;GA;;;SY)") // Allow full control to System + TEXT("(A;OICI;GA;;;BA)"); // Allow full control to Administrators + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = FALSE; + sa.lpSecurityDescriptor = NULL; + + if (ConvertStringSecurityDescriptorToSecurityDescriptor + (szSD, SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL)) { + lpSA = &sa; + } + jstring_to_cstring(env, pipename, name, MAX_PIPE_NAME_LENGTH); hPipe = CreateNamedPipe( @@ -270,7 +290,9 @@ 128, // output buffer size 8192, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out - NULL); // default security attribute + lpSA); // security attributes + + LocalFree(sa.lpSecurityDescriptor); if (hPipe == INVALID_HANDLE_VALUE) { JNU_ThrowIOExceptionWithLastError(env, "CreateNamedPipe failed");
--- a/src/windows/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Wed Sep 24 14:39:21 2014 -0700 +++ b/src/windows/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Mon Oct 06 15:51:21 2014 -0700 @@ -24,6 +24,7 @@ */ #include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h" +#include "jni_util.h" #include <windows.h> #include <gdefs.h> #include <stdlib.h> @@ -197,8 +198,13 @@ } localeString = (char *)getJavaIDFromLangID(langid); + if (localeString != NULL) { ret = (*env)->NewStringUTF(env, localeString); free(localeString); + } else { + JNU_ThrowOutOfMemoryError(env, "memory allocation error"); + ret = NULL; + } return ret; } @@ -211,6 +217,7 @@ (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) { WCHAR pattern[BUFLEN]; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + CHECK_NULL_RETURN(langtag, NULL); pattern[0] = L'\0'; @@ -228,7 +235,7 @@ (*env)->ReleaseStringChars(env, jlangtag, langtag); - return (*env)->NewString(env, pattern, wcslen(pattern)); + return (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); } /* @@ -238,8 +245,11 @@ */ JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarID (JNIEnv *env, jclass cls, jstring jlangtag) { - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - jint ret = getCalendarID(langtag); + const jchar *langtag; + jint ret; + langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + CHECK_NULL_RETURN(langtag, 0); + ret = getCalendarID(langtag); (*env)->ReleaseStringChars(env, jlangtag, langtag); return ret; } @@ -252,18 +262,30 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { WCHAR buf[BUFLEN]; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag; + jstring tmp_string; // AM - int got = getLocaleInfoWrapper(langtag, LOCALE_S1159, buf, BUFLEN); + int got; + langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + CHECK_NULL_RETURN(langtag, NULL); + got = getLocaleInfoWrapper(langtag, LOCALE_S1159, buf, BUFLEN); if (got) { - (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewString(env, buf, wcslen(buf))); + tmp_string = (*env)->NewString(env, buf, (jsize)wcslen(buf)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 0, tmp_string); + } } + if (!(*env)->ExceptionCheck(env)){ // PM got = getLocaleInfoWrapper(langtag, LOCALE_S2359, buf, BUFLEN); if (got) { - (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewString(env, buf, wcslen(buf))); + tmp_string = (*env)->NewString(env, buf, (jsize)wcslen(buf)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 1, tmp_string); + } + } } (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -280,12 +302,17 @@ (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) { WCHAR ad[BUFLEN]; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + jstring tmp_string; + CHECK_NULL_RETURN(langtag, eras); getCalendarInfoWrapper(langtag, getCalendarID(langtag), NULL, CAL_SERASTRING, ad, BUFLEN, NULL); // Windows does not provide B.C. era. - (*env)->SetObjectArrayElement(env, eras, 1, (*env)->NewString(env, ad, wcslen(ad))); + tmp_string = (*env)->NewString(env, ad, (jsize)wcslen(ad)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, eras, 1, tmp_string); + } (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -347,13 +374,17 @@ */ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPattern (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) { - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag; jstring ret; + WCHAR * pattern; - WCHAR * pattern = getNumberPattern(langtag, numberStyle); + langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + CHECK_NULL_RETURN(langtag, NULL); + pattern = getNumberPattern(langtag, numberStyle); + CHECK_NULL_RETURN(pattern, NULL); (*env)->ReleaseStringChars(env, jlangtag, langtag); - ret = (*env)->NewString(env, pattern, wcslen(pattern)); + ret = (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); free(pattern); return ret; @@ -367,8 +398,10 @@ JNIEXPORT jboolean JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_isNativeDigit (JNIEnv *env, jclass cls, jstring jlangtag) { DWORD num; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, + CHECK_NULL_RETURN(langtag, JNI_FALSE); + got = getLocaleInfoWrapper(langtag, LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER, (LPWSTR)&num, sizeof(num)); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -384,12 +417,14 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SCURRENCY, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, currencySymbol); + got = getLocaleInfoWrapper(langtag, LOCALE_SCURRENCY, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return currencySymbol; } @@ -403,8 +438,10 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SDECIMAL, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, decimalSeparator); + got = getLocaleInfoWrapper(langtag, LOCALE_SDECIMAL, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { @@ -422,8 +459,10 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_STHOUSAND, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, groupingSeparator); + got = getLocaleInfoWrapper(langtag, LOCALE_STHOUSAND, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { @@ -441,12 +480,14 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SPOSINFINITY, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, infinity); + got = getLocaleInfoWrapper(langtag, LOCALE_SPOSINFINITY, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return infinity; } @@ -460,12 +501,14 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SINTLSYMBOL, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, internationalCurrencySymbol); + got = getLocaleInfoWrapper(langtag, LOCALE_SINTLSYMBOL, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return internationalCurrencySymbol; } @@ -479,8 +522,10 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SNEGATIVESIGN, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, minusSign); + got = getLocaleInfoWrapper(langtag, LOCALE_SNEGATIVESIGN, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { @@ -498,8 +543,10 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SMONDECIMALSEP, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, monetaryDecimalSeparator); + got = getLocaleInfoWrapper(langtag, LOCALE_SMONDECIMALSEP, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { @@ -517,12 +564,14 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SNAN, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, nan); + got = getLocaleInfoWrapper(langtag, LOCALE_SNAN, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return nan; } @@ -536,8 +585,10 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) { WCHAR buf[BUFLEN]; + int got; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SPERCENT, buf, BUFLEN); + CHECK_NULL_RETURN(langtag, percent); + got = getLocaleInfoWrapper(langtag, LOCALE_SPERCENT, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { @@ -555,8 +606,12 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) { WCHAR buf[BUFLEN]; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SPERMILLE, buf, BUFLEN); + const jchar *langtag; + int got; + langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + CHECK_NULL_RETURN(langtag, perMill); + got = getLocaleInfoWrapper(langtag, LOCALE_SPERMILLE, buf, BUFLEN); + (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { @@ -574,8 +629,12 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) { WCHAR buf[BUFLEN]; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int got = getLocaleInfoWrapper(langtag, LOCALE_SNATIVEDIGITS, buf, BUFLEN); + const jchar *langtag; + int got; + langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + CHECK_NULL_RETURN(langtag, zeroDigit); + got = getLocaleInfoWrapper(langtag, LOCALE_SNATIVEDIGITS, buf, BUFLEN); + (*env)->ReleaseStringChars(env, jlangtag, langtag); if (got) { @@ -593,9 +652,11 @@ JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarDataValue (JNIEnv *env, jclass cls, jstring jlangtag, jint type) { DWORD num; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag; int got = 0; + langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + CHECK_NULL_RETURN(langtag, -1); switch (type) { case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK: got = getLocaleInfoWrapper(langtag, @@ -648,11 +709,12 @@ } pjChar = (*env)->GetStringChars(env, jStr, JNI_FALSE); + CHECK_NULL_RETURN(pjChar, NULL); got = getLocaleInfoWrapper(pjChar, lcType, buf, BUFLEN); (*env)->ReleaseStringChars(env, jStr, pjChar); if (got) { - return (*env)->NewString(env, buf, wcslen(buf)); + return (*env)->NewString(env, buf, (jsize)wcslen(buf)); } else { return NULL; } @@ -706,15 +768,21 @@ void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jobjectArray jarray, CALTYPE* pCalTypes, int offset, int length) { WCHAR name[BUFLEN]; const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); - int calid = getCalendarID(langtag); + int calid; + jstring tmp_string; + + CHECK_NULL(langtag); + calid = getCalendarID(langtag); if (calid != -1) { int i; for (i = 0; i < length; i++) { getCalendarInfoWrapper(langtag, calid, NULL, pCalTypes[i], name, BUFLEN, NULL); - (*env)->SetObjectArrayElement(env, jarray, i + offset, - (*env)->NewString(env, name, wcslen(name))); + tmp_string = (*env)->NewString(env, name, (jsize)wcslen(name)); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, jarray, i + offset, tmp_string); + } } }
--- a/test/TEST.groups Wed Sep 24 14:39:21 2014 -0700 +++ b/test/TEST.groups Mon Oct 06 15:51:21 2014 -0700 @@ -124,15 +124,27 @@ jdk_security3 = \ javax/security \ + -javax/security/auth/kerberos \ com/sun/security \ + -com/sun/security/jgss \ com/sun/org/apache/xml/internal/security \ sun/security \ + -sun/security/krb5 \ + -sun/security/jgss \ + javax/net \ lib/security +jdk_security4 = \ + com/sun/security/jgss \ + javax/security/auth/kerberos \ + sun/security/krb5 \ + sun/security/jgss + jdk_security = \ :jdk_security1 \ :jdk_security2 \ - :jdk_security3 + :jdk_security3 \ + :jdk_security4 jdk_text = \ java/text \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Graphics2D/WhiteTextColorTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import java.awt.image.*; +import javax.swing.*; + +/** + * @test + * @bug 8056009 + * @summary tests whether Graphics.setColor-calls with Color.white are ignored directly + * after pipeline initialization for a certain set of operations. + * @author ceisserer + */ +public class WhiteTextColorTest extends Frame { + public static volatile boolean success = false; + + public WhiteTextColorTest() { + Image dstImg = getGraphicsConfiguration() + .createCompatibleVolatileImage(30, 20); + Graphics g = dstImg.getGraphics(); + + g.setColor(Color.BLACK); + g.fillRect(0, 0, dstImg.getWidth(null), dstImg.getHeight(null)); + g.setColor(Color.WHITE); + g.drawString("Test", 0, 15); + + BufferedImage readBackImg = new BufferedImage(dstImg.getWidth(null), + dstImg.getHeight(null), BufferedImage.TYPE_INT_RGB); + readBackImg.getGraphics().drawImage(dstImg, 0, 0, null); + + for (int x = 0; x < readBackImg.getWidth(); x++) { + for (int y = 0; y < readBackImg.getHeight(); y++) { + int pixel = readBackImg.getRGB(x, y); + + // In case a single white pixel is found, the + // setColor(Color.WHITE) + // call before was not ignored and the bug is not present + if (pixel == 0xFFFFFFFF) { + return; + } + } + } + + throw new RuntimeException("Test Failed"); + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new WhiteTextColorTest(); + } + }); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/ByteArrayOutputStream/MaxCapacity.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Google Inc. 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 + * @ignore This test has huge memory requirements + * @run main/timeout=1800/othervm -Xmx8g MaxCapacity + * @bug 8055949 + * @summary Check that we can write (almost) Integer.MAX_VALUE bytes + * to a ByteArrayOutputStream. + * @author Martin Buchholz + */ +import java.io.ByteArrayOutputStream; + +public class MaxCapacity { + public static void main(String[] args) { + long maxHeap = Runtime.getRuntime().maxMemory(); + if (maxHeap < 3L * Integer.MAX_VALUE) { + System.out.printf("Skipping test; max memory %sM too small%n", + maxHeap/(1024*1024)); + return; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (long n = 0; ; n++) { + try { + baos.write((byte)'x'); + } catch (Throwable t) { + // check data integrity while we're here + byte[] bytes = baos.toByteArray(); + if (bytes.length != n) + throw new AssertionError("wrong length"); + if (bytes[0] != 'x' || + bytes[bytes.length - 1] != 'x') + throw new AssertionError("wrong contents"); + + long gap = Integer.MAX_VALUE - n; + System.out.printf("gap=%dM %d%n", gap/(1024*1024), gap); + if (gap > 1024) + throw t; + // t.printStackTrace(); + break; + } + } + } +}
--- a/test/java/lang/annotation/typeAnnotations/ConstructorReceiverTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/lang/annotation/typeAnnotations/ConstructorReceiverTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 8023651 8044629 + * @bug 8023651 * @summary Test that the receiver annotations and the return annotations of * constructors behave correctly. * @run testng ConstructorReceiverTest @@ -38,16 +38,11 @@ import static org.testng.Assert.*; public class ConstructorReceiverTest { - public static final Integer EMPTY_ANNOTATED_TYPE = Integer.valueOf(-1); - // Format is { // { Class to get ctor for, // ctor param class, // value of anno of return type, - // value of anno for receiver, - // or null if there should be no receiver, - // or EMPTY_ANNOTATED_TYPE of there should be a receiver but - // no annotation + // value of anno for receiver or null if there should be no receiver anno // }, // ... // } @@ -56,15 +51,13 @@ { ConstructorReceiverTest.Middle.class, ConstructorReceiverTest.class, Integer.valueOf(10), Integer.valueOf(15) }, { ConstructorReceiverTest.Middle.Inner.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(100), Integer.valueOf(150) }, { ConstructorReceiverTest.Middle.Inner.Innermost.class, ConstructorReceiverTest.Middle.Inner.class, Integer.valueOf(1000), Integer.valueOf(1500) }, - { ConstructorReceiverTest.Middle.InnerNoReceiver.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(300), EMPTY_ANNOTATED_TYPE }, + { ConstructorReceiverTest.Middle.InnerNoReceiver.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(300), null }, { ConstructorReceiverTest.Nested.class, null, Integer.valueOf(20), null }, { ConstructorReceiverTest.Nested.NestedMiddle.class, ConstructorReceiverTest.Nested.class, Integer.valueOf(200), Integer.valueOf(250)}, { ConstructorReceiverTest.Nested.NestedMiddle.NestedInner.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(2000), Integer.valueOf(2500)}, - { ConstructorReceiverTest.Nested.NestedMiddle.NestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(4000), EMPTY_ANNOTATED_TYPE}, - { ConstructorReceiverTest.Nested.NestedMiddle.SecondNestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(5000), EMPTY_ANNOTATED_TYPE}, + { ConstructorReceiverTest.Nested.NestedMiddle.NestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(4000), null}, }; - @DataProvider public Object[][] data() { return TESTS; } @@ -78,27 +71,14 @@ c = toTest.getDeclaredConstructor(ctorParamType); AnnotatedType annotatedReceiverType = c.getAnnotatedReceiverType(); + Annotation[] receiverAnnotations = annotatedReceiverType.getAnnotations(); - // Some Constructors doesn't conceptually have a receiver, they should return null if (receiverVal == null) { - assertNull(annotatedReceiverType, "getAnnotatedReciverType should return null for Constructor: " + c); + assertEquals(receiverAnnotations.length, 0, Arrays.asList(receiverAnnotations).toString() + + " should be empty. Looking at 'length': "); return; } - // check that getType() matches the receiver - assertEquals(annotatedReceiverType.getType(), - ctorParamType, - "getType() doesn't match receiver type: " + ctorParamType); - - Annotation[] receiverAnnotations = annotatedReceiverType.getAnnotations(); - - // Some Constructors have no annotations on but in theory can have a receiver - if (receiverVal.equals(EMPTY_ANNOTATED_TYPE)) { - assertEquals(receiverAnnotations.length, 0, "expecting an empty annotated type for: " + c); - return; - } - - // The rest should have annotations assertEquals(receiverAnnotations.length, 1, "expecting a 1 element array. Looking at 'length': "); assertEquals(((Annot)receiverAnnotations[0]).value(), receiverVal.intValue(), " wrong annotation found. Found " + receiverAnnotations[0] + @@ -156,10 +136,6 @@ class NestedInnerNoReceiver { @Annot(4000) public NestedInnerNoReceiver() {} } - - class SecondNestedInnerNoReceiver { - @Annot(5000) public SecondNestedInnerNoReceiver(NestedMiddle NestedMiddle.this) {} - } } }
--- a/test/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java Mon Oct 06 15:51:21 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,11 +23,10 @@ /* * @test - * @bug 8024915 8044629 + * @bug 8024915 */ import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Executable; import java.util.Arrays; public class GetAnnotatedReceiverType { @@ -43,115 +42,41 @@ public Inner1(GetAnnotatedReceiverType GetAnnotatedReceiverType.this) {} } - public static class Nested { - public Nested() {} - - public class NestedInner { - public NestedInner() { } - - public Class<?> getLocalClass () { - class NestedInnerLocal { public NestedInnerLocal() {} } - return NestedInnerLocal.class; - } - - public Class<?> getAnonymousClass() { - return new Object() {}.getClass(); - } - } - } - - public class Inner2 { - public Inner2() { } - - public class Inner3 { - public Inner3() { } - - public Class<?> getLocalClass () { - class InnerLocal { public InnerLocal() {} } - return InnerLocal.class; - } - - public Class<?> getAnonymousClass() { - return new Object() {}.getClass(); - } - } - - public Class<?> getLocalClass () { - class InnerLocal { public InnerLocal() {} } - return InnerLocal.class; - } - - public Class<?> getAnonymousClass() { - return new Object() {}.getClass(); - } - } - private static int failures = 0; private static int tests = 0; public static void main(String[] args) throws NoSuchMethodException { - checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method"), + checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method").getAnnotatedReceiverType(), "getAnnotatedReceiverType for \"method\" should return an empty AnnotatedType"); - checkEmptyAT(Inner0.class.getConstructor(GetAnnotatedReceiverType.class), + checkEmptyAT(Inner0.class.getConstructor(GetAnnotatedReceiverType.class).getAnnotatedReceiverType(), "getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType"); - checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method0"), + checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method0").getAnnotatedReceiverType(), "getAnnotatedReceiverType for \"method0\" should return an empty AnnotatedType"); - checkEmptyAT(Inner1.class.getConstructor(GetAnnotatedReceiverType.class), + checkEmptyAT(Inner1.class.getConstructor(GetAnnotatedReceiverType.class).getAnnotatedReceiverType(), "getAnnotatedReceiverType for a ctor with a \"this\" should return an empty AnnotatedType"); - checkNull(GetAnnotatedReceiverType.class.getMethod("method4"), + checkNull(GetAnnotatedReceiverType.class.getMethod("method4").getAnnotatedReceiverType(), "getAnnotatedReceiverType() on a static method should return null"); - // More nested, inner, local and anonymous classes - Nested nested = new Nested(); - Nested.NestedInner instance = nested.new NestedInner(); - checkNull(nested.getClass().getConstructors()[0], - "getAnnotatedReceiverType() on a constructor for a static class should return null"); - checkEmptyAT(instance.getClass().getConstructors()[0], - "getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType"); - checkNull(instance.getLocalClass().getConstructors()[0], - "getAnnotatedReceiverType() on a constructor for a local class should return null"); - checkNull(instance.getAnonymousClass().getDeclaredConstructors()[0], - "getAnnotatedReceiverType() on a constructor for an anonymous class should return null"); - - GetAnnotatedReceiverType outer = new GetAnnotatedReceiverType(); - Inner2 instance2 = outer.new Inner2(); - checkEmptyAT(instance2.getClass().getConstructors()[0], - "getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType"); - checkNull(instance2.getLocalClass().getConstructors()[0], - "getAnnotatedReceiverType() on a constructor for a local class should return null"); - checkNull(instance2.getAnonymousClass().getDeclaredConstructors()[0], - "getAnnotatedReceiverType() on a constructor for an anonymous class should return null"); - - Inner2.Inner3 instance3 = instance2.new Inner3(); - checkEmptyAT(instance3.getClass().getConstructors()[0], - "getAnnotatedReceiverType for a ctor without a \"this\" should return an empty AnnotatedType"); - checkNull(instance3.getLocalClass().getConstructors()[0], - "getAnnotatedReceiverType() on a constructor for a local class should return null"); - checkNull(instance3.getAnonymousClass().getDeclaredConstructors()[0], - "getAnnotatedReceiverType() on a constructor for an anonymous class should return null"); - if (failures != 0) throw new RuntimeException("Test failed, see log for details"); - else if (tests != 15) + else if (tests != 5) throw new RuntimeException("Not all cases ran, failing"); } - private static void checkNull(Executable e, String msg) { - AnnotatedType a = e.getAnnotatedReceiverType(); - if (a != null) { + private static void checkNull(Object o, String msg) { + if (o != null) { failures++; - System.err.println(msg + ": " + e); + System.err.println(msg); } tests++; } - private static void checkEmptyAT(Executable e, String msg) { - AnnotatedType a = e.getAnnotatedReceiverType(); + private static void checkEmptyAT(AnnotatedType a, String msg) { if (a.getAnnotations().length != 0) { failures++; - System.err.print(msg + ": " + e); + System.err.print(msg); } tests++; }
--- a/test/java/lang/annotation/typeAnnotations/TestExecutableGetAnnotatedType.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/lang/annotation/typeAnnotations/TestExecutableGetAnnotatedType.java Mon Oct 06 15:51:21 2014 -0700 @@ -73,11 +73,13 @@ testParameters(e.getParameters()); } + // should test constructors as well, see JDK-8044629 @Test(dataProvider = "genericMethodData") public void testGenericReceiverType(Executable e) throws Exception { testReceiverType0(e); } + // should test constructors as well, see JDK-8044629 @Test(dataProvider = "methodData") public void testReceiverType(Executable e) throws Exception { testReceiverType0(e);
--- a/test/java/lang/instrument/NMTHelper.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/lang/instrument/NMTHelper.java Mon Oct 06 15:51:21 2014 -0700 @@ -21,8 +21,12 @@ * questions. */ +import java.io.File; +import java.io.FileWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.Arrays; +import java.util.stream.Collectors; import sun.management.ManagementFactoryHelper; import com.sun.management.DiagnosticCommandMBean; @@ -32,8 +36,8 @@ executeDcmd("vmNativeMemory", "baseline"); } - // Total: reserved=3484685KB +293KB, committed=266629KB +293KB - private static Pattern totalLine = Pattern.compile("^Total: reserved=\\d+KB .*KB, committed=\\d+KB (.*)KB$"); + // Total: reserved=3484685KB +293KB, committed=266629KB +293KB + private static Pattern totalLine = Pattern.compile("^Total: reserved=\\d+KB .*KB, committed=\\d+KB (.*)KB$"); public static long committedDiff() throws Exception { String res = (String) executeDcmd("vmNativeMemory", "detail.diff"); @@ -53,14 +57,14 @@ Object[] dcmdArgs = {args}; String[] signature = {String[].class.getName()}; - try { - System.out.print("> " + cmd + " "); - for (String s : args) { - System.out.print(s + " "); - } - System.out.println(":"); + String cmdString = cmd + " " + + Arrays.stream(args).collect(Collectors.joining(" ")); + File f = new File("dcmdoutput-" + cmd + "-" + System.currentTimeMillis() + ".txt"); + System.out.println("Output from Dcmd '" + cmdString + "' is being written to file " + f); + try (FileWriter fw = new FileWriter(f)) { + fw.write("> " + cmdString + ":"); String result = (String) dcmd.invoke(cmd, dcmdArgs, signature); - System.out.println(result); + fw.write(result); return result; } catch(Exception ex) { ex.printStackTrace();
--- a/test/java/lang/instrument/RedefineBigClass.sh Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/lang/instrument/RedefineBigClass.sh Mon Oct 06 15:51:21 2014 -0700 @@ -27,7 +27,7 @@ # @author Daniel D. Daugherty # # @run shell MakeJAR3.sh RedefineBigClassAgent 'Can-Redefine-Classes: true' -# @run build BigClass RedefineBigClassApp +# @run build BigClass RedefineBigClassApp NMTHelper # @run shell/timeout=600 RedefineBigClass.sh #
--- a/test/java/lang/instrument/RetransformBigClass.sh Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/lang/instrument/RetransformBigClass.sh Mon Oct 06 15:51:21 2014 -0700 @@ -27,7 +27,7 @@ # @author Daniel D. Daugherty # # @run shell MakeJAR4.sh RetransformBigClassAgent SimpleIdentityTransformer 'Can-Retransform-Classes: true' -# @run build BigClass RetransformBigClassApp +# @run build BigClass RetransformBigClassApp NMTHelper # @run shell/timeout=600 RetransformBigClass.sh #
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFCachingTestCase.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.InvocationTargetException; + +/** + * Abstract class for lambda forms caching testing. + * + * @author kshefov + */ +public abstract class LFCachingTestCase extends LambdaFormTestCase { + + /** + * Constructor for lambda forms caching test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + protected LFCachingTestCase(TestMethods testMethod) { + super(testMethod); + } + + /** + * Checks that the lambda forms of the two adapter method handles adapter1 + * and adapter2 are the same. + * + * @param adapter1 First method handle. + * @param adapter2 Second method handle. + */ + public void checkLFCaching(MethodHandle adapter1, MethodHandle adapter2) { + try { + + if (!adapter1.type().equals(adapter2.type())) { + throw new Error("TESTBUG: Types of the two method handles are not the same"); + } + + Object lambdaForm0 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter1); + Object lambdaForm1 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter2); + + if (lambdaForm0 == null || lambdaForm1 == null) { + throw new Error("Unexpected error: One or both lambda forms of the method handles are null"); + } + + if (lambdaForm0 != lambdaForm1) { + System.err.println("Lambda form 0 toString is:"); + System.err.println(lambdaForm0); + System.err.println("Lambda form 1 toString is:"); + System.err.println(lambdaForm1); + throw new AssertionError("Error: Lambda forms of the two method handles" + + " are not the same. LF cahing does not work"); + } + } catch (IllegalAccessException | IllegalArgumentException | + SecurityException | InvocationTargetException ex) { + throw new Error("Unexpected exception: ", ex); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 LFGarbageCollectedTest + * @bug 8046703 + * @summary Test verifies that lambda forms are garbage collected + * @author kshefov + * @ignore 8057020 + * @library /lib/testlibrary/jsr292 /lib/testlibrary + * @build TestMethods + * @build LambdaFormTestCase + * @build LFGarbageCollectedTest + * @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 LFGarbageCollectedTest + */ + +import java.lang.invoke.MethodHandle; +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.lang.reflect.InvocationTargetException; +import java.util.EnumSet; +import java.util.Map; + +/** + * Lambda forms garbage collection test class. + */ +public final class LFGarbageCollectedTest extends LambdaFormTestCase { + + /** + * Constructor for a lambda forms garbage collection test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + public LFGarbageCollectedTest(TestMethods testMethod) { + super(testMethod); + } + + @Override + public void doTest() { + try { + Map<String, Object> data = getTestMethod().getTestCaseData(); + MethodHandle adapter; + try { + adapter = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE); + } catch (NoSuchMethodException ex) { + throw new Error("Unexpected exception: ", ex); + } + Object lambdaForm = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter); + if (lambdaForm == null) { + throw new Error("Unexpected error: Lambda form of the method handle is null"); + } + ReferenceQueue rq = new ReferenceQueue(); + PhantomReference ph = new PhantomReference(lambdaForm, rq); + lambdaForm = null; + data = null; + adapter = null; + for (int i = 0; i < 1000 && !ph.isEnqueued(); i++) { + System.gc(); + } + if (!ph.isEnqueued()) { + throw new AssertionError("Error: Lambda form is not garbage collected"); + } + } catch (IllegalAccessException | IllegalArgumentException | + InvocationTargetException ex) { + throw new Error("Unexpected exception: ", ex); + } + } + + /** + * Main routine for lambda forms garbage collection test. + * + * @param args Accepts no arguments. + */ + public static void main(String[] args) { + // The "identity", "constant", "arrayElementGetter" and "arrayElementSetter" + // methods should be removed from this test, + // because their lambda forms are stored in a static field and are not GC'ed. + // There can be only a finite number of such LFs for each method, + // so no memory leak happens. + EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of( + TestMethods.IDENTITY, + TestMethods.CONSTANT, + TestMethods.ARRAY_ELEMENT_GETTER, + TestMethods.ARRAY_ELEMENT_SETTER)); + LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 LFMultiThreadCachingTest + * @bug 8046703 + * @summary Test verifies that lambda forms are cached when run with multiple threads + * @author kshefov + * @library /lib/testlibrary/jsr292 /lib/testlibrary + * @build TestMethods + * @build LambdaFormTestCase + * @build LFCachingTestCase + * @build LFMultiThreadCachingTest + * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFMultiThreadCachingTest + */ + +import java.lang.invoke.MethodHandle; +import java.util.EnumSet; +import java.util.Map; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +/** + * Multiple threaded lambda forms caching test class. + */ +public final class LFMultiThreadCachingTest extends LFCachingTestCase { + private static final TestMethods.Kind[] KINDS; + static { + EnumSet<TestMethods.Kind> set = EnumSet.complementOf(EnumSet.of(TestMethods.Kind.EXCEPT)); + KINDS = set.toArray(new TestMethods.Kind[set.size()]); + if (KINDS.length < 2) { + throw new Error("TESTBUG: KINDS.length[" + KINDS.length + "] should be at least 2"); + } + } + private static final int CORES = Math.max(KINDS.length, Runtime.getRuntime().availableProcessors()); + + /** + * Constructor a for multiple threaded lambda forms caching test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + public LFMultiThreadCachingTest(TestMethods testMethod) { + super(testMethod); + } + + @Override + public void doTest() { + Map<String, Object> data = getTestMethod().getTestCaseData(); + ConcurrentLinkedQueue<MethodHandle> adapters = new ConcurrentLinkedQueue<>(); + CyclicBarrier begin = new CyclicBarrier(CORES); + CountDownLatch end = new CountDownLatch(CORES); + for (int i = 0; i < CORES; ++i) { + TestMethods.Kind kind = KINDS[i % KINDS.length]; + new Thread(() -> { + try { + begin.await(); + adapters.add(getTestMethod().getTestCaseMH(data, kind)); + } catch (InterruptedException | BrokenBarrierException | IllegalAccessException | NoSuchMethodException ex) { + throw new Error("Unexpected exception: ", ex); + } finally { + end.countDown(); + } + }).start(); + } + try { + end.await(); + } catch (InterruptedException ex) { + throw new Error("Unexpected exception: ", ex); + } + if (adapters.size() < CORES) { + throw new Error("adapters size[" + adapters.size() + "] is less than " + CORES); + } + MethodHandle prev = adapters.poll(); + for (MethodHandle current : adapters) { + checkLFCaching(prev, current); + prev = current; + } + } + + /** + * Main routine for multiple threaded lambda forms caching test. + * + * @param args Accepts no arguments. + */ + public static void main(String[] args) { + LambdaFormTestCase.runTests(LFMultiThreadCachingTest::new, EnumSet.allOf(TestMethods.class)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 LFSingleThreadCachingTest + * @bug 8046703 + * @summary Test verifies that lambda forms are cached when run with single thread + * @author kshefov + * @library /lib/testlibrary/jsr292 /lib/testlibrary + * @build TestMethods + * @build LambdaFormTestCase + * @build LFCachingTestCase + * @build LFSingleThreadCachingTest + * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFSingleThreadCachingTest + */ + +import java.lang.invoke.MethodHandle; +import java.util.EnumSet; +import java.util.Map; + +/** + * Single threaded lambda forms caching test class. + */ +public final class LFSingleThreadCachingTest extends LFCachingTestCase { + + /** + * Constructor for a single threaded lambda forms caching test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + public LFSingleThreadCachingTest(TestMethods testMethod) { + super(testMethod); + } + + @Override + public void doTest() { + MethodHandle adapter1; + MethodHandle adapter2; + Map<String, Object> data = getTestMethod().getTestCaseData(); + try { + adapter1 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE); + adapter2 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.TWO); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new Error("Unexpected exception: ", ex); + } + checkLFCaching(adapter1, adapter2); + } + + /** + * Main routine for single threaded lambda forms caching test. + * + * @param args Accepts no arguments. + */ + public static void main(String[] args) { + LambdaFormTestCase.runTests(LFSingleThreadCachingTest::new, EnumSet.allOf(TestMethods.class)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.testlibrary.jsr292.Helper; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.function.Function; + +/** + * Lambda forms caching test case class. Contains all necessary test routines to + * test lambda forms caching in method handles returned by methods of + * MethodHandles class. + * + * @author kshefov + */ +public abstract class LambdaFormTestCase { + + private final static String METHOD_HANDLE_CLASS_NAME = "java.lang.invoke.MethodHandle"; + private final static String INTERNAL_FORM_METHOD_NAME = "internalForm"; + + /** + * Reflection link to {@code j.l.i.MethodHandle.internalForm} method. It is + * used to get a lambda form from a method handle. + */ + protected final static Method INTERNAL_FORM; + + static { + try { + Class mhClass = Class.forName(METHOD_HANDLE_CLASS_NAME); + INTERNAL_FORM = mhClass.getDeclaredMethod(INTERNAL_FORM_METHOD_NAME); + INTERNAL_FORM.setAccessible(true); + } catch (Exception ex) { + throw new Error("Unexpected exception: ", ex); + } + } + + private final TestMethods testMethod; + + /** + * Test case constructor. Generates test cases with random method types for + * given methods form {@code j.l.i.MethodHandles} class. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class which + * returns a {@code j.l.i.MethodHandle}. + */ + protected LambdaFormTestCase(TestMethods testMethod) { + this.testMethod = testMethod; + } + + public TestMethods getTestMethod() { + return testMethod; + } + + /** + * Routine that executes a test case. + */ + public abstract void doTest(); + + /** + * Runs a number of test cases defined by the size of testCases list. + * + * @param ctor constructor of LambdaFormCachingTest or its child classes + * object. + * @param testMethods list of test methods + */ + public static void runTests(Function<TestMethods, LambdaFormTestCase> ctor, Collection<TestMethods> testMethods) { + boolean passed = true; + int testCounter = 0; + int failCounter = 0; + long iterations = Math.max(1, Helper.TEST_LIMIT / testMethods.size()); + for (long i = 0; i < iterations; i++) { + System.err.println(String.format("Iteration %d:", i)); + for (TestMethods testMethod : testMethods) { + LambdaFormTestCase testCase = ctor.apply(testMethod); + try { + System.err.printf("Tested LF caching feature with MethodHandles.%s method.%n", + testCase.getTestMethod().name); + testCase.doTest(); + System.err.println("PASSED"); + } catch (Throwable t) { + t.printStackTrace(); + System.err.println("FAILED"); + passed = false; + failCounter++; + } + testCounter++; + } + } + if (!passed) { + throw new Error(String.format("%d of %d test cases FAILED! %n" + + "Rerun the test with the same \"-Dseed=\" option as in the log file!", + failCounter, testCounter)); + } else { + System.err.println(String.format("All %d test cases PASSED!", testCounter)); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/TestMethods.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,698 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.testlibrary.jsr292.Helper; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Enumeration containing information about methods from + * {@code j.l.i.MethodHandles} class that are used for testing lambda forms + * caching. + * + * @author kshefov + */ +public enum TestMethods { + + FOLD_ARGUMENTS("foldArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + Class<?> combinerReturnType; + if (realArity == 0) { + combinerReturnType = void.class; + } else { + combinerReturnType = Helper.RNG.nextBoolean() ? void.class : mtTarget.parameterType(0); + } + data.put("combinerReturnType", combinerReturnType); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> combinerReturnType = (Class) data.get("combinerReturnType"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + Class<?> rType = mtTarget.returnType(); + int combListStart = (combinerReturnType == void.class) ? 0 : 1; + if (modifierMHArgNum < combListStart) { + modifierMHArgNum = combListStart; + } + MethodHandle combiner = TestMethods.methodHandleGenerator(combinerReturnType, + mtTarget.parameterList().subList(combListStart, + modifierMHArgNum), kind); + return MethodHandles.foldArguments(target, combiner); + } + }, + DROP_ARGUMENTS("dropArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int dropArgsPos = Helper.RNG.nextInt(realArity + 1); + data.put("dropArgsPos", dropArgsPos); + MethodType mtDropArgs = TestMethods.randomMethodTypeGenerator( + Helper.RNG.nextInt(Helper.MAX_ARITY - realArity)); + data.put("mtDropArgs", mtDropArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtDropArgs = (MethodType) data.get("mtDropArgs"); + int dropArgsPos = (int) data.get("dropArgsPos"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + int mtTgtSlotsCount = TestMethods.argSlotsCount(mtTarget); + int mtDASlotsCount = TestMethods.argSlotsCount(mtDropArgs); + List<Class<?>> fakeParList; + if (mtTgtSlotsCount + mtDASlotsCount > Helper.MAX_ARITY - 1) { + fakeParList = TestMethods.reduceArgListToSlotsCount(mtDropArgs.parameterList(), + Helper.MAX_ARITY - mtTgtSlotsCount - 1); + } else { + fakeParList = mtDropArgs.parameterList(); + } + return MethodHandles.dropArguments(target, dropArgsPos, fakeParList); + } + }, + EXPLICIT_CAST_ARGUMENTS("explicitCastArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + MethodType mtExcplCastArgs = TestMethods.randomMethodTypeGenerator(realArity); + if (mtTarget.returnType() == void.class) { + mtExcplCastArgs = MethodType.methodType(void.class, + mtExcplCastArgs.parameterArray()); + } + if (mtExcplCastArgs.returnType() == void.class) { + mtExcplCastArgs = MethodType.methodType(mtTarget.returnType(), + mtExcplCastArgs.parameterArray()); + } + data.put("mtExcplCastArgs", mtExcplCastArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtExcplCastArgs = (MethodType) data.get("mtExcplCastArgs"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + return MethodHandles.explicitCastArguments(target, mtExcplCastArgs); + } + }, + FILTER_ARGUMENTS("filterArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int filterArgsPos = Helper.RNG.nextInt(realArity + 1); + data.put("filterArgsPos", filterArgsPos); + int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos); + data.put("filtersArgsArrayLength", filtersArgsArrayLength); + MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength); + data.put("mtFilter", mtFilter); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtFilter = (MethodType) data.get("mtFilter"); + int filterArgsPos = (int) data.get("filterArgsPos"); + int filtersArgsArrayLength = (int) data.get("filtersArgsArrayLength"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + MethodHandle[] filters = new MethodHandle[filtersArgsArrayLength]; + for (int i = 0; i < filtersArgsArrayLength; i++) { + filters[i] = TestMethods.filterGenerator(mtFilter.parameterType(i), + mtTarget.parameterType(filterArgsPos + i), kind); + } + return MethodHandles.filterArguments(target, filterArgsPos, filters); + } + }, + FILTER_RETURN_VALUE("filterReturnValue") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int filterArgsPos = Helper.RNG.nextInt(realArity + 1); + int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos); + MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength); + data.put("mtFilter", mtFilter); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtFilter = (MethodType) data.get("mtFilter"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + MethodHandle filter = TestMethods.filterGenerator(mtTarget.returnType(), + mtFilter.returnType(), kind); + return MethodHandles.filterReturnValue(target, filter); + } + }, + INSERT_ARGUMENTS("insertArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int insertArgsPos = Helper.RNG.nextInt(realArity + 1); + data.put("insertArgsPos", insertArgsPos); + int insertArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - insertArgsPos); + MethodType mtInsertArgs = MethodType.methodType(void.class, mtTarget.parameterList() + .subList(insertArgsPos, insertArgsPos + insertArgsArrayLength)); + data.put("mtInsertArgs", mtInsertArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtInsertArgs = (MethodType) data.get("mtInsertArgs"); + int insertArgsPos = (int) data.get("insertArgsPos"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + Object[] insertList = Helper.randomArgs(mtInsertArgs.parameterList()); + return MethodHandles.insertArguments(target, insertArgsPos, insertList); + } + }, + PERMUTE_ARGUMENTS("permuteArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int[] permuteArgsReorderArray = new int[realArity]; + int mtParmuteArgsNum = Helper.RNG.nextInt(Helper.MAX_ARITY); + mtParmuteArgsNum = mtParmuteArgsNum == 0 ? 1 : mtParmuteArgsNum; + MethodType mtPermuteArgs = TestMethods.randomMethodTypeGenerator(mtParmuteArgsNum); + mtTarget = mtTarget.changeReturnType(mtPermuteArgs.returnType()); + for (int i = 0; i < realArity; i++) { + int mtPermuteArgsParNum = Helper.RNG.nextInt(mtPermuteArgs.parameterCount()); + permuteArgsReorderArray[i] = mtPermuteArgsParNum; + mtTarget = mtTarget.changeParameterType( + i, mtPermuteArgs.parameterType(mtPermuteArgsParNum)); + } + data.put("mtTarget", mtTarget); + data.put("permuteArgsReorderArray", permuteArgsReorderArray); + data.put("mtPermuteArgs", mtPermuteArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtPermuteArgs = (MethodType) data.get("mtPermuteArgs"); + int[] permuteArgsReorderArray = (int[]) data.get("permuteArgsReorderArray"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + return MethodHandles.permuteArguments(target, mtPermuteArgs, permuteArgsReorderArray); + } + }, + THROW_EXCEPTION("throwException") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + return MethodHandles.throwException(rType, Exception.class + ); + } + }, + GUARD_WITH_TEST("guardWithTest") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + TestMethods.Kind targetKind; + TestMethods.Kind fallbackKind; + if (kind.equals(TestMethods.Kind.ONE)) { + targetKind = TestMethods.Kind.ONE; + fallbackKind = TestMethods.Kind.TWO; + } else { + targetKind = TestMethods.Kind.TWO; + fallbackKind = TestMethods.Kind.ONE; + } + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), targetKind); + MethodHandle fallback = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), fallbackKind); + MethodHandle test = TestMethods.methodHandleGenerator(boolean.class, + mtTarget.parameterList().subList(0, modifierMHArgNum), kind); + return MethodHandles.guardWithTest(test, target, fallback); + } + }, + CATCH_EXCEPTION("catchException") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + MethodHandle target; + if (kind.equals(TestMethods.Kind.ONE)) { + target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), TestMethods.Kind.ONE); + } else { + target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), TestMethods.Kind.EXCEPT); + } + List<Class<?>> handlerParamList = new ArrayList<>(mtTarget.parameterCount() + 1); + handlerParamList.add(Exception.class); + handlerParamList.addAll(mtTarget.parameterList().subList(0, modifierMHArgNum)); + MethodHandle handler = TestMethods.methodHandleGenerator( + mtTarget.returnType(), handlerParamList, TestMethods.Kind.TWO); + return MethodHandles.catchException(target, Exception.class, handler); + } + }, + INVOKER("invoker") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + return MethodHandles.invoker(mtTarget); + } + }, + EXACT_INVOKER("exactInvoker") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + return MethodHandles.exactInvoker(mtTarget); + } + }, + SPREAD_INVOKER("spreadInvoker") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + return MethodHandles.spreadInvoker(mtTarget, modifierMHArgNum); + } + }, + ARRAY_ELEMENT_GETTER("arrayElementGetter") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + return MethodHandles.arrayElementGetter(Array.newInstance(rType, 2).getClass()); + } + }, + ARRAY_ELEMENT_SETTER("arrayElementSetter") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + return MethodHandles.arrayElementSetter(Array.newInstance(rType, 2).getClass()); + } + }, + CONSTANT("constant") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + if (rType.equals(boolean.class)) { + // There should be the same return values because for default values there are special "zero" forms + return MethodHandles.constant(rType, true); + } else { + return MethodHandles.constant(rType, kind.getValue(rType)); + } + } + }, + IDENTITY("identity") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + return MethodHandles.identity(rType); + } + }; + + /** + * Test method's name. + */ + public final String name; + + private TestMethods(String name) { + this.name = name; + } + + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + throw new UnsupportedOperationException("TESTBUG: getMH method is not implemented for test method " + this); + } + + /** + * Creates an adapter method handle depending on a test method from + * MethodHandles class. Adapter is what is returned by the test method. This + * method is able to create two kinds of adapters, their type will be the + * same, but return values are different. + * + * @param data a Map containing data to create a method handle, can be + * obtained by {@link #getTestCaseData} method + * @param kind defines whether adapter ONE or adapter TWO will be + * initialized. Should be equal to TestMethods.Kind.ONE or + * TestMethods.Kind.TWO + * @return Method handle adapter that behaves according to + * TestMethods.Kind.ONE or TestMethods.Kind.TWO + * @throws java.lang.NoSuchMethodException + * @throws java.lang.IllegalAccessException + */ + public MethodHandle getTestCaseMH(Map<String, Object> data, TestMethods.Kind kind) + throws NoSuchMethodException, IllegalAccessException { + if (data == null) { + throw new Error(String.format("TESTBUG: Data for test method %s is not prepared", + this.name)); + } + if (!kind.equals(TestMethods.Kind.ONE) && !kind.equals(TestMethods.Kind.TWO)) { + throw new IllegalArgumentException("TESTBUG: Wrong \"kind\" (" + kind + + ") arg to getTestCaseMH function." + + " Should be Kind.ONE or Kind.TWO"); + } + return getMH(data, kind); + } + + /** + * Returns a data Map needed for {@link #getTestCaseMH} method. + * + * @return data Map needed for {@link #getTestCaseMH} method + */ + public Map<String, Object> getTestCaseData() { + throw new UnsupportedOperationException( + "TESTBUG: getTestCaseData method is not implemented for test method " + this); + } + + /** + * Enumeration used in methodHandleGenerator to define whether a MH returned + * by this method returns "2" in different type representations, "4", or + * throw an Exception. + */ + public static enum Kind { + + ONE(2), + TWO(4), + EXCEPT(0); + + private final int value; + + private Object getValue(Class<?> cl) { + return Helper.castToWrapper(value, cl); + } + + private MethodHandle getBasicMH(Class<?> rType) throws NoSuchMethodException, IllegalAccessException { + MethodHandle result = null; + switch (this) { + case ONE: + case TWO: + if (rType.equals(void.class)) { + result = MethodHandles.lookup().findVirtual(Kind.class, "returnVoid", MethodType.methodType(void.class)); + result = MethodHandles.insertArguments(result, 0, this); + } else { + result = MethodHandles.constant(rType, getValue(rType)); + } + break; + case EXCEPT: + result = MethodHandles.throwException(rType, Exception.class); + result = MethodHandles.insertArguments(result, 0, new Exception()); + break; + } + return result; + } + + private void returnVoid() { + } + + private Kind(int value) { + this.value = value; + } + } + + /** + * Routine used to obtain a randomly generated method type. + * + * @param arity Arity of returned method type. + * @return MethodType generated randomly. + */ + private static MethodType randomMethodTypeGenerator(int arity) { + final Class<?>[] CLASSES = { + Object.class, + int.class, + boolean.class, + byte.class, + short.class, + char.class, + long.class, + float.class, + double.class + }; + if (arity > Helper.MAX_ARITY) { + throw new IllegalArgumentException( + String.format("Arity should not exceed %d!", Helper.MAX_ARITY)); + } + List<Class<?>> list = Helper.randomClasses(CLASSES, arity); + list = Helper.getParams(list, false, arity); + int i = Helper.RNG.nextInt(CLASSES.length + 1); + Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i]; + return MethodType.methodType(rtype, list); + } + + /** + * Routine used to obtain a method handles of a given type an kind (return + * value). + * + * @param returnType Type of MH return value. + * @param argTypes Types of MH args. + * @param kind Defines whether the obtained MH returns "1" or "2". + * @return Method handle of the given type. + * @throws NoSuchMethodException + * @throws IllegalAccessException + */ + private static MethodHandle methodHandleGenerator(Class<?> returnType, + List<Class<?>> argTypes, TestMethods.Kind kind) + throws NoSuchMethodException, IllegalAccessException { + MethodHandle result; + result = kind.getBasicMH(returnType); + return Helper.addTrailingArgs(result, argTypes.size(), argTypes); + } + + /** + * Routine that generates filter method handles to test + * MethodHandles.filterArguments method. + * + * @param inputType Filter's argument type. + * @param returnType Filter's return type. + * @param kind Filter's return value definer. + * @return A filter method handle, that takes one argument. + * @throws NoSuchMethodException + * @throws IllegalAccessException + */ + private static MethodHandle filterGenerator(Class<?> inputType, Class<?> returnType, + TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodHandle tmpMH = kind.getBasicMH(returnType); + if (inputType.equals(void.class)) { + return tmpMH; + } + ArrayList<Class<?>> inputTypeList = new ArrayList<>(1); + inputTypeList.add(inputType); + return Helper.addTrailingArgs(tmpMH, 1, inputTypeList); + } + + private static int argSlotsCount(MethodType mt) { + int result = 0; + for (Class cl : mt.parameterArray()) { + if (cl.equals(long.class) || cl.equals(double.class)) { + result += 2; + } else { + result++; + } + } + return result; + } + + private static List<Class<?>> reduceArgListToSlotsCount(List<Class<?>> list, + int desiredSlotCount) { + List<Class<?>> result = new ArrayList<>(desiredSlotCount); + int count = 0; + for (Class<?> cl : list) { + if (count >= desiredSlotCount) { + break; + } + if (cl.equals(long.class) || cl.equals(double.class)) { + count += 2; + } else { + count++; + } + result.add(cl); + } + return result; + } +}
--- a/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -43,6 +43,7 @@ public class CatchExceptionTest { private static final List<Class<?>> ARGS_CLASSES; protected static final int MAX_ARITY = Helper.MAX_ARITY - 1; + static { Class<?> classes[] = { Object.class, @@ -53,11 +54,8 @@ double[].class, String.class, }; - List<Class<?>> list = new ArrayList<>(MAX_ARITY); - for (int i = 0; i < MAX_ARITY; ++i) { - list.add(classes[Helper.RNG.nextInt(classes.length)]); - } - ARGS_CLASSES = Collections.unmodifiableList(list); + ARGS_CLASSES = Collections.unmodifiableList( + Helper.randomClasses(classes, MAX_ARITY)); } private final TestCase testCase; @@ -67,7 +65,6 @@ private int dropped; private MethodHandle thrower; - public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount, final int catchDrops) { this.testCase = testCase; @@ -108,37 +105,7 @@ } private List<Class<?>> getThrowerParams(boolean isVararg, int argsCount) { - boolean unmodifiable = true; - List<Class<?>> classes; - classes = ARGS_CLASSES.subList(0, - Math.min(argsCount, (MAX_ARITY / 2) - 1)); - int extra = 0; - if (argsCount >= MAX_ARITY / 2) { - classes = new ArrayList<>(classes); - unmodifiable = false; - extra = (int) classes.stream().filter(Helper::isDoubleCost).count(); - int i = classes.size(); - while (classes.size() + extra < argsCount) { - Class<?> aClass = ARGS_CLASSES.get(i); - if (Helper.isDoubleCost(aClass)) { - ++extra; - if (classes.size() + extra >= argsCount) { - break; - } - } - classes.add(aClass); - } - } - if (isVararg && classes.size() > 0) { - if (unmodifiable) { - classes = new ArrayList<>(classes); - } - int last = classes.size() - 1; - Class<?> aClass = classes.get(classes.size() - 1); - aClass = Array.newInstance(aClass, 2).getClass(); - classes.set(last, aClass); - } - return classes; + return Helper.getParams(ARGS_CLASSES, isVararg, argsCount); }
--- a/test/java/math/BigDecimal/ZeroScalingTests.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/math/BigDecimal/ZeroScalingTests.java Mon Oct 06 15:51:21 2014 -0700 @@ -23,8 +23,10 @@ /* * @test - * @bug 4902952 4905407 4916149 - * @summary Tests that the scale of zero is propagated properly and has the proper effect. + * @bug 4902952 4905407 4916149 8057793 + * @summary Tests that the scale of zero is propagated properly and has the + * proper effect and that setting the scale to zero does not mutate the + * BigDecimal. * @author Joseph D. Darcy */ @@ -445,6 +447,16 @@ return failures; } + static int setScaleDoesNotMutateTest() { + BigDecimal total = new BigDecimal("258815507198903607775511093103396443816569106750031264155319238473795838680758514810110764742309284477206138527975952150289602995045050194333030191178778772026538699925775139201970526695485362661420908248887297829319881475178467494779683293036572059595504702727301324759997409522995072582369210284334718757260859794972695026582432867589093687280300148141501712013226636373167978223780290547640482160818746599330924736802844173226042389174403401903999447463440670236056324929325189403433689" + + ".426167432065785331444814035799717606745777287606858873045971898862329763544687891847664736523584843544347118836628373041412918374550458884706686730726101338872517021688769782894793734049819222924171842793485919753186993388451909096042127903835765393729547730953942175461146061715108701615615142134282261293656760570061554783195726716403304101469782303957325142638493327692352838806741611887655695029948975509680496573999174402058593454203190963443179532640446352828089016874853634851387762579319853267317320515941105912189838719919259277721994880193541634872882180184303434360412344059435559680494807415573269199203376126242271766939666939316648575065702750502798973418978204972336924254702551350654650573582614211506856383897692911422458286912085339575875324832979140870119455620532272318122103640233069115700020760625493816902806241630788230268031695140687964931377988962507263990468276009750998066442971308866347136022907166625330623130307555914930120150437900510530537258665172619821272937026713977709974434967165159545592482710663639966781678268622620229577009317698254134914742098420792313931843709810905414336383757407675429663714210967924767434203021205270369316797752411974617662200898086335322218191674846795163102021505555508444216708745911194321674887527227200297039471799580744303346354057273540730643842091810899490590914195225087593013834388801018488174855060306804024894292757613618190472234110859436472645203753139820658279559340251226992556744343475086923568365637919479462424794554522865559888240039662899509652221329892034706445253487898044421278283079233226845124525434586324657471286953226255430662125870993375281512713207125720748163498642795960457639954616530163959004770092547297392499137383176609646505351001304840762905826237024982330597805063521162285806541220110524989649256399233792799406995068469271941269511818994954109392839548141262324660472253632382325038836831429045617036015122388070240133760858500132713255407855625837956886349324981003917084922808187223285051144454915441134217743066575863563572152133978905444998209075763950909784148142018992367290485890072303179512881131769414783097454103103347826517701720263541869335631166977965013552647906729408522950996105479525445916501155305220090853891226367184989434453290788068397817927893708837722255115237672194162924260945492012622891770365546831236789867922136747819364833843397165107825773447549885351449899330007200651144003961228091210630807333236718793283427788965479074476288255387824982443633190938302785760754436525586544523339170400053128503337395428393881357669568532722167493096151221381017320147344991331421789379785964440840684363041795410525097564979585773948558651896834067324427900848255265001498890329859444233861478388742393060996236783742654761350763876989363052609107226398858310051497856931093693697981165801539060516895227818925342535261227134364063673285588256280386915163875872231395348293505967057794409379709079685798908660258077792158532257603211711587587586356431658240229896344639704"); + if (total.setScale(0, RoundingMode.DOWN).equals(total.setScale(0, RoundingMode.DOWN))) { + return 0; + } else { + return 1; + } + } + public static void main(String argv[]) { int failures = 0; @@ -455,6 +467,7 @@ failures += setScaleTests(); failures += toEngineeringStringTests(); failures += ulpTests(); + failures += setScaleDoesNotMutateTest(); if (failures > 0 ) { throw new RuntimeException("Incurred " + failures + " failures" +
--- a/test/java/math/BigInteger/BigIntegerTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/math/BigInteger/BigIntegerTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -71,6 +71,7 @@ static final int BITS_TOOM_COOK_SQUARE = 6912; static final int BITS_SCHOENHAGE_BASE = 640; static final int BITS_BURNIKEL_ZIEGLER = 2560; + static final int BITS_BURNIKEL_ZIEGLER_OFFSET = 1280; static final int ORDER_SMALL = 60; static final int ORDER_MEDIUM = 100; @@ -288,19 +289,19 @@ * where {@code abs(u) > abs(v)} and {@code a > b && b > 0}, then if * {@code w/z = q1*z + r1} and {@code u/v = q2*v + r2}, then * {@code q1 = q2*pow(2,a-b)} and {@code r1 = r2*pow(2,b)}. The test - * ensures that {@code v} is just under the B-Z threshold and that {@code w} - * and {@code z} are both over the threshold. This implies that {@code u/v} - * uses the standard division algorithm and {@code w/z} uses the B-Z - * algorithm. The results of the two algorithms are then compared using the - * observation described in the foregoing and if they are not equal a - * failure is logged. + * ensures that {@code v} is just under the B-Z threshold, that {@code z} is + * over the threshold and {@code w} is much larger than {@code z}. This + * implies that {@code u/v} uses the standard division algorithm and + * {@code w/z} uses the B-Z algorithm. The results of the two algorithms + * are then compared using the observation described in the foregoing and + * if they are not equal a failure is logged. */ public static void divideLarge() { int failCount = 0; - BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER - 33); + BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 33); for (int i=0; i<SIZE; i++) { - BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER - 34, rnd); + BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 34, rnd); BigInteger v = base.add(addend); BigInteger u = v.multiply(BigInteger.valueOf(2 + rnd.nextInt(Short.MAX_VALUE - 1))); @@ -312,14 +313,14 @@ v = v.negate(); } - int a = 17 + rnd.nextInt(16); + int a = BITS_BURNIKEL_ZIEGLER_OFFSET + rnd.nextInt(16); int b = 1 + rnd.nextInt(16); - BigInteger w = u.multiply(BigInteger.valueOf(1L << a)); - BigInteger z = v.multiply(BigInteger.valueOf(1L << b)); + BigInteger w = u.multiply(BigInteger.ONE.shiftLeft(a)); + BigInteger z = v.multiply(BigInteger.ONE.shiftLeft(b)); BigInteger[] divideResult = u.divideAndRemainder(v); - divideResult[0] = divideResult[0].multiply(BigInteger.valueOf(1L << (a - b))); - divideResult[1] = divideResult[1].multiply(BigInteger.valueOf(1L << b)); + divideResult[0] = divideResult[0].multiply(BigInteger.ONE.shiftLeft(a - b)); + divideResult[1] = divideResult[1].multiply(BigInteger.ONE.shiftLeft(b)); BigInteger[] bzResult = w.divideAndRemainder(z); if (divideResult[0].compareTo(bzResult[0]) != 0 ||
--- a/test/java/net/NetworkInterface/Test.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/java/net/NetworkInterface/Test.java Mon Oct 06 15:51:21 2014 -0700 @@ -22,7 +22,9 @@ */ /* @test - * @bug 4405354 6594296 + * @bug 4405354 6594296 8058216 + * @run main Test + * @run main/othervm -Djava.net.preferIPv4Stack=true Test * @summary Basic tests for NetworkInterface */ import java.net.NetworkInterface;
--- a/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -58,9 +58,9 @@ public class AttributeArbitraryDataTypeTest implements NotificationListener { // Flag to notify that a message has been received - private boolean counterMessageReceived = false; - private boolean gaugeMessageReceived = false; - private boolean stringMessageReceived = false; + private volatile boolean counterMessageReceived = false; + private volatile boolean gaugeMessageReceived = false; + private volatile boolean stringMessageReceived = false; // Match enum public enum Match { do_not_match_0, @@ -195,21 +195,33 @@ " has reached or exceeded the threshold"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - counterMessageReceived = true; + + synchronized (this) { + counterMessageReceived = true; + notifyAll(); + } } else if (type.equals(MonitorNotification. THRESHOLD_HIGH_VALUE_EXCEEDED)) { echo("\t\t" + n.getObservedAttribute() + " has reached or exceeded the high threshold"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - gaugeMessageReceived = true; + + synchronized (this) { + gaugeMessageReceived = true; + notifyAll(); + } } else if (type.equals(MonitorNotification. STRING_TO_COMPARE_VALUE_MATCHED)) { echo("\t\t" + n.getObservedAttribute() + " matches the string-to-compare value"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - stringMessageReceived = true; + + synchronized (this) { + stringMessageReceived = true; + notifyAll(); + } } else { echo("\t\tSkipping notification of type: " + type); } @@ -358,6 +370,17 @@ // Check if notification was received // + synchronized (this) { + while (!counterMessageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } if (counterMessageReceived) { echo("\tOK: CounterMonitor notification received"); } else { @@ -525,6 +548,17 @@ // Check if notification was received // + synchronized (this) { + while (!gaugeMessageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } if (gaugeMessageReceived) { echo("\tOK: GaugeMonitor notification received"); } else { @@ -680,6 +714,17 @@ // Check if notification was received // + synchronized (this) { + while (!stringMessageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } if (stringMessageReceived) { echo("\tOK: StringMonitor notification received"); } else {
--- a/test/javax/management/monitor/CounterMonitorTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/javax/management/monitor/CounterMonitorTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -43,9 +43,6 @@ // modulus number private Number modulus = new Integer(7); - // offset number - private int offset = 0; - // difference mode flag private boolean differenceModeFlag = true; @@ -58,9 +55,6 @@ // counter values private int[] values = new int[] {4, 6, 9, 11}; - // time to wait for notification (in seconds) - private int timeout = 5; - // flag to notify that a message has been received private volatile boolean messageReceived = false; @@ -92,8 +86,9 @@ echo("\t\t" + n.getObservedAttribute() + " has reached or exceeded the threshold"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); - messageReceived = true; + synchronized (this) { + messageReceived = true; notifyAll(); } } else { @@ -205,22 +200,17 @@ } /* - * Wait until timeout reached + * Wait messageReceived to be true */ - void doWait() { - for (int i = 0; i < timeout; i++) { - echo("\tdoWait: Waiting for " + timeout + " seconds. " + - "i = " + i + ", messageReceived = " + messageReceived); - if (messageReceived) { + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); break; } - try { - synchronized (this) { - wait(1000); - } - } catch (InterruptedException e) { - // OK: Ignore... - } } }
--- a/test/javax/management/monitor/GaugeMonitorDeadlockTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/javax/management/monitor/GaugeMonitorDeadlockTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -36,8 +36,9 @@ */ import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; import java.util.concurrent.atomic.AtomicInteger; -import javax.management.Attribute; import javax.management.JMX; import javax.management.MBeanServer; import javax.management.Notification; @@ -47,10 +48,16 @@ import javax.management.monitor.GaugeMonitorMBean; public class GaugeMonitorDeadlockTest { + private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY}; + private static long checkingTime; public static void main(String[] args) throws Exception { if (args.length != 1) throw new Exception("Arg should be test number"); + double factor = Double.parseDouble(System.getProperty("test.timeout.factor", "1.0")); + checkingTime = (long)factor*1000; + System.out.println("=== checkingTime = " + checkingTime + "ms"); + int testNo = Integer.parseInt(args[0]) - 1; TestCase test = testCases[testNo]; System.out.println("Test: " + test.getDescription()); @@ -58,8 +65,6 @@ System.out.println("Test passed"); } - private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY}; - private static abstract class TestCase { TestCase(String description, When when) { this.description = description; @@ -98,16 +103,29 @@ monitorProxy.setNotifyLow(true); monitorProxy.start(); + System.out.println("=== Waiting observedProxy.getGetCount() to be " + + "changed, presumable deadlock if timeout?"); final int initGetCount = observedProxy.getGetCount(); - int getCount = initGetCount; - for (int i = 0; i < 2000; i++) { // 2000 * 10 = 20 seconds - getCount = observedProxy.getGetCount(); - if (getCount != initGetCount) - break; - Thread.sleep(10); + long checkedTime = System.currentTimeMillis(); + long nowTime; + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + while (observedProxy.getGetCount() == initGetCount) { + Thread.sleep(100); + + nowTime = System.currentTimeMillis(); + if (nowTime - checkedTime >= checkingTime) { + System.out.println("=== Checking deadlocked ..."); + if (threadMXBean.findDeadlockedThreads() != null) { + for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) { + System.out.println(info); + } + throw new Error("Found deadlocked threads: " + + threadMXBean.findDeadlockedThreads().length); + } + checkedTime = System.currentTimeMillis(); + } } - if (getCount <= initGetCount) - throw new Exception("Test failed: presumable deadlock"); + // This won't show up as a deadlock in CTRL-\ or in // ThreadMXBean.findDeadlockedThreads(), because they don't // see that thread A is waiting for thread B (B.join()), and @@ -117,13 +135,13 @@ // so if we want to test notify behaviour we can trigger by // exceeding the threshold. if (when == When.IN_NOTIFY) { + final Thread testedThread = new Thread(sensitiveThing); final AtomicInteger notifCount = new AtomicInteger(); final NotificationListener listener = new NotificationListener() { public void handleNotification(Notification n, Object h) { - Thread t = new Thread(sensitiveThing); - t.start(); + testedThread.start(); try { - t.join(); + testedThread.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } @@ -132,12 +150,36 @@ }; mbs.addNotificationListener(monitorName, listener, null, null); observedProxy.setThing(1000); - for (int i = 0; i < 2000 && notifCount.get() == 0; i++) - Thread.sleep(10); - if (notifCount.get() == 0) - throw new Exception("Test failed: presumable deadlock"); + System.out.println("=== Waiting notifications, presumable " + + "deadlock if timeout?"); + long startTime = System.currentTimeMillis(); + checkedTime = startTime; + while (notifCount.get() == 0) { + Thread.sleep(100); + + nowTime = System.currentTimeMillis(); + if (nowTime - checkedTime >= checkingTime) { + System.out.println("=== Checking the thread state ..."); + if (testedThread.isAlive()) { + System.out.println("=== Waiting testedThread to die " + + "after " + (nowTime - startTime) + "ms"); + + ThreadInfo tinfo = threadMXBean.getThreadInfo(testedThread.getId()); + if (Thread.State.BLOCKED.equals(tinfo.getThreadState())) { + for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) { + System.out.println(info); + } + } else { + System.out.println(tinfo); + } + } else { + System.out.println("=== The testedThread is dead as wished, " + + "the test must be passed soon."); + } + checkedTime = System.currentTimeMillis(); + } + } } - } abstract void doSensitiveThing(GaugeMonitorMBean monitorProxy,
--- a/test/javax/management/monitor/NonComparableAttributeValueTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/javax/management/monitor/NonComparableAttributeValueTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -39,7 +39,7 @@ public class NonComparableAttributeValueTest implements NotificationListener { // Flag to notify that a message has been received - private boolean messageReceived = false; + private volatile boolean messageReceived = false; // MBean class public class ObservedObject implements ObservedObjectMBean { @@ -69,7 +69,11 @@ echo("\t\t" + n.getObservedAttribute() + " is null"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - messageReceived = true; + + synchronized (this) { + messageReceived = true; + notifyAll(); + } } else { echo("\t\tSkipping notification of type: " + type); } @@ -134,12 +138,9 @@ echo(">>> START the CounterMonitor"); counterMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: CounterMonitor notification received"); } else { @@ -212,12 +213,9 @@ echo(">>> START the GaugeMonitor"); gaugeMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: GaugeMonitor notification received"); } else { @@ -289,12 +287,9 @@ echo(">>> START the StringMonitor"); stringMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: StringMonitor notification received"); } else { @@ -334,6 +329,21 @@ } /* + * Wait messageReceived to be true + */ + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } + + /* * Standalone entry point. * * Run the test and report to stdout.
--- a/test/javax/management/monitor/ReflectionExceptionTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/javax/management/monitor/ReflectionExceptionTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -87,7 +87,11 @@ echo("\tObservedAttribute: " + mn.getObservedAttribute()); echo("\tDerivedGauge: " + mn.getDerivedGauge()); echo("\tTrigger: " + mn.getTrigger()); - messageReceived = true; + + synchronized (this) { + messageReceived = true; + notifyAll(); + } } } } @@ -135,12 +139,9 @@ echo(">>> START the CounterMonitor"); counterMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!"); } else { @@ -203,12 +204,9 @@ echo(">>> START the GaugeMonitor"); gaugeMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!"); } else { @@ -270,12 +268,9 @@ echo(">>> START the StringMonitor"); stringMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: StringMonitor got RUNTIME_ERROR notification!"); } else { @@ -349,8 +344,23 @@ } } + /* + * Wait messageReceived to be true + */ + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } + // Flag to notify that a message has been received - private boolean messageReceived = false; + private volatile boolean messageReceived = false; private MBeanServer server; private ObjectName obsObjName;
--- a/test/javax/management/monitor/RuntimeExceptionTest.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/javax/management/monitor/RuntimeExceptionTest.java Mon Oct 06 15:51:21 2014 -0700 @@ -86,7 +86,11 @@ echo("\tObservedAttribute: " + mn.getObservedAttribute()); echo("\tDerivedGauge: " + mn.getDerivedGauge()); echo("\tTrigger: " + mn.getTrigger()); - messageReceived = true; + + synchronized (this) { + messageReceived = true; + notifyAll(); + } } } } @@ -134,12 +138,9 @@ echo(">>> START the CounterMonitor"); counterMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!"); } else { @@ -202,12 +203,9 @@ echo(">>> START the GaugeMonitor"); gaugeMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!"); } else { @@ -269,12 +267,9 @@ echo(">>> START the StringMonitor"); stringMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: StringMonitor got RUNTIME_ERROR notification!"); } else { @@ -347,8 +342,23 @@ } } + /* + * Wait messageReceived to be true + */ + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } + // Flag to notify that a message has been received - private boolean messageReceived = false; + private volatile boolean messageReceived = false; private MBeanServer server; private ObjectName obsObjName;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/net/ssl/TLSv12/ProtocolFilter.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 8052406 + * @summary SSLv2Hello protocol may be filter out unexpectedly + * @run main/othervm ProtocolFilter + */ + +import java.io.*; +import java.net.*; +import javax.net.ssl.*; + +public class ProtocolFilter { + + /* + * ============================================================= + * 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 = false; + + /* + * Where do we find the keystores? + */ + static String pathToStores = "../../../../sun/security/ssl/etc"; + static String keyStoreFile = "keystore"; + static String trustStoreFile = "truststore"; + static String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * 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 { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket(serverPort); + + // Only enable cipher suites for TLS v1.2. + sslServerSocket.setEnabledCipherSuites( + new String[]{"TLS_RSA_WITH_AES_128_CBC_SHA256"}); + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + 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); + } + + SSLSocketFactory sslsf = + (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) + sslsf.createSocket("localhost", serverPort); + + // Enable all supported protocols, including SSLv2Hello. + sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols()); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + sslSocket.close(); + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // 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 { + String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) + System.setProperty("javax.net.debug", "all"); + + /* + * Start the tests. + */ + new ProtocolFilter(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ProtocolFilter() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + 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..."); + 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..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/text/View/8048110/bug8048110.java Mon Oct 06 15:51:21 2014 -0700 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 8048110 + * @summary Using tables in JTextPane leads to infinite loop in FlowLayout.layoutRow + * @author Dmitry Markov + * @run main bug8048110 + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.text.Element; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.HTMLEditorKit; +import java.awt.*; + +public class bug8048110 { + private static SunToolkit toolkit = (SunToolkit)Toolkit.getDefaultToolkit(); + private static Object lock = new Object(); + private static boolean isRealSyncPerformed = false; + private static final String htmlText = "<table width=\"100%\" cellpadding=\"10\" cellspacing=\"5\" align=\"center\">" + + "<tr><th align=\"left\" bgcolor=\"#bec3c6\">Devices</th><th align=\"left\" bgcolor=\"#bec3c6\">State</th></tr>" + + "<tr><td align=\"left\" bgcolor=\"#bec3c6\">PC</td><td align=\"left\" bgcolor=\"#46a055\">Ok</td></tr></table>"; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createAndShowGUI(); + } + }); + + Thread thread = new Thread() { + @Override + public void run() { + toolkit.realSync(); + synchronized (lock) { + isRealSyncPerformed = true; + lock.notifyAll(); + } + } + }; + thread.start(); + + synchronized (lock) { + if (!isRealSyncPerformed) { + lock.wait(5000); + } + } + + if (!isRealSyncPerformed) { + throw new RuntimeException("Test Failed!"); + } + } + + private static void createAndShowGUI() { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + HTMLEditorKit editorKit = new HTMLEditorKit(); + JTextPane textPane = new JTextPane(); + textPane.setContentType("text/html"); + textPane.setEditorKit(editorKit); + textPane.setText("Initial text without table"); + + JFrame frame = new JFrame("bug8048110"); + frame.getContentPane().add(textPane, BorderLayout.CENTER); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.setSize(500, 200); + frame.setVisible(true); + + textPane.setDocument(textPane.getEditorKit().createDefaultDocument()); + HTMLDocument htmlDocument = (HTMLDocument) textPane.getDocument(); + Element firstParagraph = findFirstElement(textPane.getDocument().getDefaultRootElement(), "p"); + + try { + htmlDocument.setInnerHTML(firstParagraph, htmlText); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + private static Element findFirstElement(Element e, String name) { + String elementName = e.getName(); + if (elementName != null && elementName.equalsIgnoreCase(name)) { + return e; + } + for (int i = 0; i < e.getElementCount(); i++) { + Element result = findFirstElement(e.getElement(i), name); + if (result != null) { + return result; + } + } + return null; + } +} +
--- a/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Wed Sep 24 14:39:21 2014 -0700 +++ b/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Mon Oct 06 15:51:21 2014 -0700 @@ -52,7 +52,7 @@ public static final long TEST_LIMIT; static { String str = System.getProperty("testLimit"); - TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2_000L; + TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2000L; System.out.printf("-DtestLimit=%d%n", TEST_LIMIT); } @@ -116,6 +116,48 @@ return size <= lag ? null : calledLog.get(size - lag - 1); } + public static List<Class<?>> randomClasses(Class<?>[] classes, int size) { + List<Class<?>> result = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + result.add(classes[RNG.nextInt(classes.length)]); + } + return result; + } + + public static List<Class<?>> getParams(List<Class<?>> classes, + boolean isVararg, int argsCount) { + boolean unmodifiable = true; + List<Class<?>> result = classes.subList(0, + Math.min(argsCount, (MAX_ARITY / 2) - 1)); + int extra = 0; + if (argsCount >= MAX_ARITY / 2) { + result = new ArrayList<>(result); + unmodifiable = false; + extra = (int) result.stream().filter(Helper::isDoubleCost).count(); + int i = result.size(); + while (result.size() + extra < argsCount) { + Class<?> aClass = classes.get(i); + if (Helper.isDoubleCost(aClass)) { + ++extra; + if (result.size() + extra >= argsCount) { + break; + } + } + result.add(aClass); + } + } + if (isVararg && result.size() > 0) { + if (unmodifiable) { + result = new ArrayList<>(result); + } + int last = result.size() - 1; + Class<?> aClass = result.get(last); + aClass = Array.newInstance(aClass, 2).getClass(); + result.set(last, aClass); + } + return result; + } + public static MethodHandle addTrailingArgs(MethodHandle target, int nargs, List<Class<?>> classes) { int targetLen = target.type().parameterCount(); @@ -230,7 +272,7 @@ return randomArgs(params.toArray(new Class<?>[params.size()])); } - private static Object castToWrapper(Object value, Class<?> dst) { + public static Object castToWrapper(Object value, Class<?> dst) { Object wrap = null; if (value instanceof Number) { wrap = castToWrapperOrNull(((Number) value).longValue(), dst); @@ -268,7 +310,7 @@ if (dst == byte.class || dst == Byte.class) { return (byte) (value); } - if (dst == boolean.class || dst == boolean.class) { + if (dst == boolean.class || dst == Boolean.class) { return ((value % 29) & 1) == 0; } return null;