# HG changeset patch # User chegar # Date 1382441613 -3600 # Node ID 1c85f50e262233e484c1f613d3b743dab9223c2c # Parent d7ef65d3ee57c9d3244996d431cac0e26a0081ce# Parent f15ad52cffeda150e2ff5622847192d67394e975 Merge diff -r d7ef65d3ee57 -r 1c85f50e2622 make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java --- a/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java Mon Oct 21 15:00:56 2013 +0100 +++ b/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java Tue Oct 22 12:33:33 2013 +0100 @@ -618,6 +618,11 @@ // remove ROC, which is not supported in j.u.tz builtZones.remove("ROC"); links.remove("ROC"); + // remove EST, HST and MST. They are supported via + // the short-id mapping + builtZones.remove("EST"); + builtZones.remove("HST"); + builtZones.remove("MST"); } /** diff -r d7ef65d3ee57 -r 1c85f50e2622 makefiles/Setup.gmk --- a/makefiles/Setup.gmk Mon Oct 21 15:00:56 2013 +0100 +++ b/makefiles/Setup.gmk Tue Oct 22 12:33:33 2013 +0100 @@ -27,7 +27,7 @@ # To build with all warnings enabled, do the following: # make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000" -JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,classfile,dep-ann,divzero,varargs -Werror +JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,auxiliaryclass,classfile,dep-ann,divzero,empty,try,varargs -Werror # Any java code executed during a JDK build to build other parts of the JDK must be # executed by the bootstrap JDK (probably with -Xbootclasspath/p: ) and for this diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/io/Closeable.java --- a/src/share/classes/java/io/Closeable.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/io/Closeable.java Tue Oct 22 12:33:33 2013 +0100 @@ -34,7 +34,6 @@ * * @since 1.5 */ -@FunctionalInterface public interface Closeable extends AutoCloseable { /** diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/io/Flushable.java --- a/src/share/classes/java/io/Flushable.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/io/Flushable.java Tue Oct 22 12:33:33 2013 +0100 @@ -34,7 +34,6 @@ * * @since 1.5 */ -@FunctionalInterface public interface Flushable { /** diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/AutoCloseable.java --- a/src/share/classes/java/lang/AutoCloseable.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/AutoCloseable.java Tue Oct 22 12:33:33 2013 +0100 @@ -48,7 +48,6 @@ * @author Josh Bloch * @since 1.7 */ -@FunctionalInterface public interface AutoCloseable { /** * Closes this resource, relinquishing any underlying resources. diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/Class.java --- a/src/share/classes/java/lang/Class.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/Class.java Tue Oct 22 12:33:33 2013 +0100 @@ -1571,6 +1571,10 @@ *

If this {@code Class} object represents a primitive type or void, * then the returned array has length 0. * + *

Static methods declared in superinterfaces of the class or interface + * represented by this {@code Class} object are not considered members of + * the class or interface. + * *

The elements in the returned array are not sorted and are not in any * particular order. * @@ -1729,6 +1733,10 @@ *

If this {@code Class} object represents an array type, then this * method does not find the {@code clone()} method. * + *

Static methods declared in superinterfaces of the class or interface + * represented by this {@code Class} object are not considered members of + * the class or interface. + * * @param name the name of the method * @param parameterTypes the list of parameters * @return the {@code Method} object that matches the specified @@ -1752,7 +1760,7 @@ public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); - Method method = getMethod0(name, parameterTypes); + Method method = getMethod0(name, parameterTypes, true); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } @@ -2727,6 +2735,14 @@ } } + void addAllNonStatic(Method[] methods) { + for (Method candidate : methods) { + if (!Modifier.isStatic(candidate.getModifiers())) { + add(candidate); + } + } + } + int length() { return length; } @@ -2797,7 +2813,7 @@ MethodArray inheritedMethods = new MethodArray(); Class[] interfaces = getInterfaces(); for (int i = 0; i < interfaces.length; i++) { - inheritedMethods.addAll(interfaces[i].privateGetPublicMethods()); + inheritedMethods.addAllNonStatic(interfaces[i].privateGetPublicMethods()); } if (!isInterface()) { Class c = getSuperclass(); @@ -2900,7 +2916,7 @@ } - private Method getMethod0(String name, Class[] parameterTypes) { + private Method getMethod0(String name, Class[] parameterTypes, boolean includeStaticMethods) { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicMethods(). It fetches only the declared @@ -2913,25 +2929,23 @@ if ((res = searchMethods(privateGetDeclaredMethods(true), name, parameterTypes)) != null) { - return res; + if (includeStaticMethods || !Modifier.isStatic(res.getModifiers())) + return res; } // Search superclass's methods if (!isInterface()) { Class c = getSuperclass(); if (c != null) { - if ((res = c.getMethod0(name, parameterTypes)) != null) { + if ((res = c.getMethod0(name, parameterTypes, true)) != null) { return res; } } } // Search superinterfaces' methods Class[] interfaces = getInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - Class c = interfaces[i]; - if ((res = c.getMethod0(name, parameterTypes)) != null) { + for (Class c : interfaces) + if ((res = c.getMethod0(name, parameterTypes, false)) != null) return res; - } - } // Not found return null; } @@ -3300,7 +3314,10 @@ public A[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return AnnotationSupport.getMultipleAnnotations(annotationData().annotations, annotationClass); + AnnotationData annotationData = annotationData(); + return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations, + annotationData.annotations, + annotationClass); } /** @@ -3330,7 +3347,8 @@ public A[] getDeclaredAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return AnnotationSupport.getMultipleAnnotations(annotationData().declaredAnnotations, annotationClass); + return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations, + annotationClass); } /** diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/Comparable.java --- a/src/share/classes/java/lang/Comparable.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/Comparable.java Tue Oct 22 12:33:33 2013 +0100 @@ -93,7 +93,6 @@ * @see java.util.Comparator * @since 1.2 */ -@FunctionalInterface public interface Comparable { /** * Compares this object with the specified object for order. Returns a diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/ConditionalSpecialCasing.java --- a/src/share/classes/java/lang/ConditionalSpecialCasing.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/ConditionalSpecialCasing.java Tue Oct 22 12:33:33 2013 +0100 @@ -74,7 +74,6 @@ new Entry(0x00CC, new char[]{0x0069, 0x0307, 0x0300}, new char[]{0x00CC}, "lt", 0), // # LATIN CAPITAL LETTER I WITH GRAVE new Entry(0x00CD, new char[]{0x0069, 0x0307, 0x0301}, new char[]{0x00CD}, "lt", 0), // # LATIN CAPITAL LETTER I WITH ACUTE new Entry(0x0128, new char[]{0x0069, 0x0307, 0x0303}, new char[]{0x0128}, "lt", 0), // # LATIN CAPITAL LETTER I WITH TILDE - new Entry(0x0130, new char[]{0x0069, 0x0307}, new char[]{0x0130}, "lt", 0), // # LATIN CAPITAL LETTER I WITH DOT ABOVE //# ================================================================================ //# Turkish and Azeri @@ -85,10 +84,7 @@ new Entry(0x0049, new char[]{0x0131}, new char[]{0x0049}, "tr", NOT_BEFORE_DOT), // # LATIN CAPITAL LETTER I new Entry(0x0049, new char[]{0x0131}, new char[]{0x0049}, "az", NOT_BEFORE_DOT), // # LATIN CAPITAL LETTER I new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "tr", 0), // # LATIN SMALL LETTER I - new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "az", 0), // # LATIN SMALL LETTER I - //# ================================================================================ - //# Other - new Entry(0x0130, new char[]{0x0069, 0x0307}, new char[]{0x0130}, "en", 0), // # LATIN CAPITALLETTER I WITH DOT ABOVE + new Entry(0x0069, new char[]{0x0069}, new char[]{0x0130}, "az", 0) // # LATIN SMALL LETTER I }; // A hash table that contains the above entries diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/Iterable.java --- a/src/share/classes/java/lang/Iterable.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/Iterable.java Tue Oct 22 12:33:33 2013 +0100 @@ -42,7 +42,6 @@ * @since 1.5 * @jls 14.14.2 The enhanced for statement */ -@FunctionalInterface public interface Iterable { /** * Returns an iterator over elements of type {@code T}. diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/Readable.java --- a/src/share/classes/java/lang/Readable.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/Readable.java Tue Oct 22 12:33:33 2013 +0100 @@ -34,7 +34,6 @@ * * @since 1.5 */ -@FunctionalInterface public interface Readable { /** diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/String.java --- a/src/share/classes/java/lang/String.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/String.java Tue Oct 22 12:33:33 2013 +0100 @@ -2598,21 +2598,14 @@ } if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale); - } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT - lowerChar = Character.ERROR; } else { lowerChar = Character.toLowerCase(srcChar); } if ((lowerChar == Character.ERROR) || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { if (lowerChar == Character.ERROR) { - if (!localeDependent && srcChar == '\u0130') { - lowerCharArray = - ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH); - } else { - lowerCharArray = - ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale); - } + lowerCharArray = + ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale); } else if (srcCount == 2) { resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount; continue; diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/reflect/Executable.java --- a/src/share/classes/java/lang/reflect/Executable.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/reflect/Executable.java Tue Oct 22 12:33:33 2013 +0100 @@ -527,7 +527,7 @@ public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); + return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass); } /** diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/reflect/Field.java --- a/src/share/classes/java/lang/reflect/Field.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/reflect/Field.java Tue Oct 22 12:33:33 2013 +0100 @@ -1123,7 +1123,7 @@ public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); + return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass); } /** diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/java/lang/reflect/Parameter.java --- a/src/share/classes/java/lang/reflect/Parameter.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/java/lang/reflect/Parameter.java Tue Oct 22 12:33:33 2013 +0100 @@ -295,7 +295,7 @@ public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); + return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass); } /** diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/sun/nio/ch/FileChannelImpl.java --- a/src/share/classes/sun/nio/ch/FileChannelImpl.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java Tue Oct 22 12:33:33 2013 +0100 @@ -840,7 +840,15 @@ ti = threads.add(); if (!isOpen()) return null; - if (size() < position + size) { // Extend file size + + long filesize; + do { + filesize = nd.size(fd); + } while ((filesize == IOStatus.INTERRUPTED) && isOpen()); + if (!isOpen()) + return null; + + if (filesize < position + size) { // Extend file size if (!writable) { throw new IOException("Channel not open for writing " + "- cannot extend file to required size"); @@ -849,6 +857,8 @@ do { rv = nd.truncate(fd, position + size); } while ((rv == IOStatus.INTERRUPTED) && isOpen()); + if (!isOpen()) + return null; } if (size == 0) { addr = 0; diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/sun/nio/cs/ext/DoubleByte.java --- a/src/share/classes/sun/nio/cs/ext/DoubleByte.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/sun/nio/cs/ext/DoubleByte.java Tue Oct 22 12:33:33 2013 +0100 @@ -111,7 +111,6 @@ public static class Decoder extends CharsetDecoder implements DelegatableDecoder, ArrayDecoder { - final char[][] b2c; final char[] b2cSB; final int b2Min; @@ -122,7 +121,12 @@ return CoderResult.UNDERFLOW; } - protected CoderResult crMalformedOrUnmappable(int b) { + protected CoderResult crMalformedOrUnmappable(int b1, int b2) { + if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte(b1) + b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte(b2) + decodeSingle(b2) != UNMAPPABLE_DECODING) { // isSingle(b2) + return CoderResult.malformedForLength(1); + } return CoderResult.unmappableForLength(2); } @@ -161,7 +165,7 @@ int b2 = sa[sp + 1] & 0xff; if (b2 < b2Min || b2 > b2Max || (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) { - return crMalformedOrUnmappable(b1); + return crMalformedOrUnmappable(b1, b2); } inSize++; } @@ -190,7 +194,7 @@ int b2 = src.get() & 0xff; if (b2 < b2Min || b2 > b2Max || (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) - return crMalformedOrUnmappable(b1); + return crMalformedOrUnmappable(b1, b2); inSize++; } dst.put(c); @@ -221,8 +225,13 @@ if (c == UNMAPPABLE_DECODING) { if (sp < sl) { int b2 = src[sp++] & 0xff; - if (b2 >= b2Min && b2 <= b2Max) { - c = b2c[b1][b2 - b2Min]; + if (b2 < b2Min || b2 > b2Max || + (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) { + if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte + b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte + decodeSingle(b2) != UNMAPPABLE_DECODING) { + sp--; + } } } if (c == UNMAPPABLE_DECODING) { @@ -466,8 +475,8 @@ return CoderResult.UNDERFLOW; } - protected CoderResult crMalformedOrUnmappable(int b) { - if (b == SS2 || b == SS3 ) + protected CoderResult crMalformedOrUnmappable(int b1, int b2) { + if (b1 == SS2 || b1 == SS3 ) return CoderResult.malformedForLength(1); return CoderResult.unmappableForLength(2); } diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java --- a/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Tue Oct 22 12:33:33 2013 +0100 @@ -166,7 +166,7 @@ @Override public T[] getDeclaredAnnotationsByType(Class annotation) { - return AnnotationSupport.getMultipleAnnotations(annotations, annotation); + return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotations, annotation); } // AnnotatedType diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/sun/reflect/annotation/AnnotationSupport.java --- a/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Tue Oct 22 12:33:33 2013 +0100 @@ -28,109 +28,224 @@ import java.lang.annotation.*; import java.lang.reflect.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; public final class AnnotationSupport { + /** - * Finds and returns all annotation of the type indicated by - * {@code annotationClass} from the {@code Map} {@code - * annotationMap}. Looks into containers of the {@code - * annotationClass} (as specified by an the {@code - * annotationClass} type being meta-annotated with an {@code - * Repeatable} annotation). + * Finds and returns all annotations in {@code annotations} matching + * the given {@code annoClass}. + * + * Apart from annotations directly present in {@code annotations} this + * method searches for annotations inside containers i.e. indirectly + * present annotations. + * + * The order of the elements in the array returned depends on the iteration + * order of the provided map. Specifically, the directly present annotations + * come before the indirectly present annotations if and only if the + * directly present annotations come before the indirectly present + * annotations in the map. * - * @param annotationMap the {@code Map} used to store annotations indexed by their type - * @param annotationClass the type of annotation to search for + * @param annotations the {@code Map} in which to search for annotations + * @param annoClass the type of annotation to search for + * @param includeNonInheritedContainees if false, the annoClass must be + * inheritable for the containers to be searched * - * @return an array of instances of {@code annotationClass} or an empty array if none were found + * @return an array of instances of {@code annoClass} or an empty + * array if none were found */ - public static A[] getMultipleAnnotations( - final Map, Annotation> annotationMap, - final Class annotationClass) { - final List res = new ArrayList(); + private static A[] getDirectlyAndIndirectlyPresent( + Map, Annotation> annotations, + Class annoClass, + boolean includeNonInheritedContainees) { + + List result = new ArrayList(); @SuppressWarnings("unchecked") - final A candidate = (A)annotationMap.get(annotationClass); - if (candidate != null) { - res.add(candidate); + A direct = (A) annotations.get(annoClass); + if (direct != null) + result.add(direct); + + if (includeNonInheritedContainees || + AnnotationType.getInstance(annoClass).isInherited()) { + A[] indirect = getIndirectlyPresent(annotations, annoClass); + + if (indirect != null) { + + boolean indirectFirst = direct == null || + containerBeforeContainee(annotations, annoClass); + + result.addAll((indirectFirst ? 0 : 1), Arrays.asList(indirect)); + } } - final Class containerClass = getContainer(annotationClass); - if (containerClass != null) { - res.addAll(unpackAll(annotationMap.get(containerClass), annotationClass)); - } + @SuppressWarnings("unchecked") + A[] arr = (A[]) Array.newInstance(annoClass, result.size()); + return result.toArray(arr); + } + + + /** + * Equivalent to calling {@code getDirectlyAndIndirectlyPresentAnnotations( + * annotations, annoClass, true)}. + */ + public static A[] getDirectlyAndIndirectlyPresent( + Map, Annotation> annotations, + Class annoClass) { + + return getDirectlyAndIndirectlyPresent(annotations, annoClass, true); + } + - @SuppressWarnings("unchecked") // should be safe annotationClass is a token for A - final A[] emptyTemplateArray = (A[])Array.newInstance(annotationClass, 0); - return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray); + /** + * Finds and returns all annotations matching the given {@code annoClass} + * indirectly present in {@code annotations}. + * + * @param annotations annotations to search indexed by their types + * @param annoClass the type of annotation to search for + * + * @return an array of instances of {@code annoClass} or an empty array if no + * indirectly present annotations were found + */ + private static A[] getIndirectlyPresent( + Map, Annotation> annotations, + Class annoClass) { + + Repeatable repeatable = annoClass.getDeclaredAnnotation(Repeatable.class); + if (repeatable == null) + return null; // Not repeatable -> no indirectly present annotations + + Class containerClass = repeatable.value(); + + Annotation container = annotations.get(containerClass); + if (container == null) + return null; + + // Unpack container + A[] valueArray = getValueArray(container); + checkTypes(valueArray, container, annoClass); + + return valueArray; } - /** Helper to get the container, or null if none, of an annotation. */ - private static Class getContainer(Class annotationClass) { - Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class); - return (containingAnnotation == null) ? null : containingAnnotation.value(); + + /** + * Figures out if conatiner class comes before containee class among the + * keys of the given map. + * + * @return true if container class is found before containee class when + * iterating over annotations.keySet(). + */ + private static boolean containerBeforeContainee( + Map, Annotation> annotations, + Class annoClass) { + + Class containerClass = + annoClass.getDeclaredAnnotation(Repeatable.class).value(); + + for (Class c : annotations.keySet()) { + if (c == containerClass) return true; + if (c == annoClass) return false; + } + + // Neither containee nor container present + return false; } - /** Reflectively look up and get the returned array from the the - * invocation of the value() element on an instance of an - * Annotation. + + /** + * Finds and returns all associated annotations matching the given class. + * + * The order of the elements in the array returned depends on the iteration + * order of the provided maps. Specifically, the directly present annotations + * come before the indirectly present annotations if and only if the + * directly present annotations come before the indirectly present + * annotations in the relevant map. + * + * @param declaredAnnotations the declared annotations indexed by their types + * @param allAnnotations declared and inherited annotations indexed by their types + * @param annoClass the type of annotation to search for + * + * @return an array of instances of {@code annoClass} or an empty array if none were found. */ - private static A[] getValueArray(Annotation containerInstance) { + public static A[] getAssociatedAnnotations( + Map, Annotation> declaredAnnotations, + Map, Annotation> allAnnotations, + Class annoClass) { + + // Search declared + A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass); + + // Search inherited + if (result.length == 0) + result = getDirectlyAndIndirectlyPresent(allAnnotations, annoClass, false); + + return result; + } + + + /* Reflectively invoke the values-method of the given annotation + * (container), cast it to an array of annotations and return the result. + */ + private static A[] getValueArray(Annotation container) { try { - // the spec tells us the container must have an array-valued - // value element. Get the AnnotationType, get the "value" element - // and invoke it to get the contents. + // According to JLS the container must have an array-valued value + // method. Get the AnnotationType, get the "value" method and invoke + // it to get the content. - Class containerClass = containerInstance.annotationType(); + Class containerClass = container.annotationType(); AnnotationType annoType = AnnotationType.getInstance(containerClass); if (annoType == null) - throw new AnnotationFormatError(containerInstance + " is an invalid container for repeating annotations"); + throw invalidContainerException(container, null); Method m = annoType.members().get("value"); if (m == null) - throw new AnnotationFormatError(containerInstance + - " is an invalid container for repeating annotations"); + throw invalidContainerException(container, null); + m.setAccessible(true); - @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException - A[] a = (A[])m.invoke(containerInstance); // this will erase to (Annotation[]) but we - // do a runtime cast on the return-value - // in the methods that call this method - return a; - } catch (IllegalAccessException | // couldnt loosen security - IllegalArgumentException | // parameters doesn't match + // This will erase to (Annotation[]) but we do a runtime cast on the + // return-value in the method that call this method. + @SuppressWarnings("unchecked") + A[] values = (A[]) m.invoke(container); + + return values; + + } catch (IllegalAccessException | // couldn't loosen security + IllegalArgumentException | // parameters doesn't match InvocationTargetException | // the value method threw an exception - ClassCastException e) { // well, a cast failed ... - throw new AnnotationFormatError( - containerInstance + " is an invalid container for repeating annotations", - e); + ClassCastException e) { + + throw invalidContainerException(container, e); + } } - /* Sanity check type of and return a list of all the annotation - * instances of type {@code annotationClass} from {@code - * containerInstance}. - */ - private static List unpackAll(Annotation containerInstance, - Class annotationClass) { - if (containerInstance == null) { - return Collections.emptyList(); // container not present - } + + private static AnnotationFormatError invalidContainerException(Annotation anno, + Throwable cause) { + return new AnnotationFormatError( + anno + " is an invalid container for repeating annotations", + cause); + } + - try { - A[] a = getValueArray(containerInstance); - List l = new ArrayList<>(a.length); - for (int i = 0; i < a.length; i++) - l.add(annotationClass.cast(a[i])); - return l; - } catch (ClassCastException | - NullPointerException e) { - throw new AnnotationFormatError( - String.format("%s is an invalid container for repeating annotations of type: %s", - containerInstance, annotationClass), - e); + /* Sanity check type of all the annotation instances of type {@code annoClass} + * from {@code container}. + */ + private static void checkTypes(A[] annotations, + Annotation container, + Class annoClass) { + for (A a : annotations) { + if (!annoClass.isInstance(a)) { + throw new AnnotationFormatError( + String.format("%s is an invalid container for " + + "repeating annotations of type: %s", + container, annoClass)); + } } } } diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java --- a/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Tue Oct 22 12:33:33 2013 +0100 @@ -217,7 +217,7 @@ @Override public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass); + return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass); } @Override diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/classes/sun/util/calendar/ZoneInfoFile.java --- a/src/share/classes/sun/util/calendar/ZoneInfoFile.java Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/classes/sun/util/calendar/ZoneInfoFile.java Tue Oct 22 12:33:33 2013 +0100 @@ -66,8 +66,17 @@ * @return a set of time zone IDs. */ public static String[] getZoneIds() { - String[] ids = Arrays.copyOf(regions, regions.length + oldMappings.length); + int len = regions.length + oldMappings.length; + if (!USE_OLDMAPPING) { + len += 3; // EST/HST/MST not in tzdb.dat + } + String[] ids = Arrays.copyOf(regions, len); int i = regions.length; + if (!USE_OLDMAPPING) { + ids[i++] = "EST"; + ids[i++] = "HST"; + ids[i++] = "MST"; + } for (int j = 0; j < oldMappings.length; j++) { ids[i++] = oldMappings[j][0]; } @@ -264,6 +273,10 @@ aliases.put("EST", "America/New_York"); aliases.put("MST", "America/Denver"); aliases.put("HST", "Pacific/Honolulu"); + } else { + zones.put("EST", new ZoneInfo("EST", -18000000)); + zones.put("MST", new ZoneInfo("MST", -25200000)); + zones.put("HST", new ZoneInfo("HST", -36000000)); } } diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/lib/security/java.security-linux --- a/src/share/lib/security/java.security-linux Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/lib/security/java.security-linux Tue Oct 22 12:33:33 2013 +0100 @@ -184,6 +184,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ @@ -230,6 +231,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/lib/security/java.security-macosx --- a/src/share/lib/security/java.security-macosx Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/lib/security/java.security-macosx Tue Oct 22 12:33:33 2013 +0100 @@ -185,6 +185,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ @@ -231,6 +232,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/lib/security/java.security-solaris --- a/src/share/lib/security/java.security-solaris Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/lib/security/java.security-solaris Tue Oct 22 12:33:33 2013 +0100 @@ -186,6 +186,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ @@ -231,6 +232,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ diff -r d7ef65d3ee57 -r 1c85f50e2622 src/share/lib/security/java.security-windows --- a/src/share/lib/security/java.security-windows Mon Oct 21 15:00:56 2013 +0100 +++ b/src/share/lib/security/java.security-windows Tue Oct 22 12:33:33 2013 +0100 @@ -185,6 +185,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ @@ -231,6 +232,7 @@ com.sun.media.sound.,\ com.sun.naming.internal.,\ com.sun.proxy.,\ + com.sun.corba.se.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ com.sun.org.apache.xerces.internal.,\ diff -r d7ef65d3ee57 -r 1c85f50e2622 test/ProblemList.txt --- a/test/ProblemList.txt Mon Oct 21 15:00:56 2013 +0100 +++ b/test/ProblemList.txt Tue Oct 22 12:33:33 2013 +0100 @@ -325,6 +325,9 @@ # 8007410 tools/launcher/FXLauncherTest.java linux-all +# 7144200 +java/lang/management/ClassLoadingMXBean/LoadCounts.java generic-all + ############################################################################ # jdk_jdi diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/SecurityManager/CheckPackageAccess.java --- a/test/java/lang/SecurityManager/CheckPackageAccess.java Mon Oct 21 15:00:56 2013 +0100 +++ b/test/java/lang/SecurityManager/CheckPackageAccess.java Tue Oct 22 12:33:33 2013 +0100 @@ -58,6 +58,7 @@ "com.sun.media.sound.", "com.sun.naming.internal.", "com.sun.proxy.", + "com.sun.corba.se.", "com.sun.org.apache.bcel.internal.", "com.sun.org.apache.regexp.internal.", "com.sun.org.apache.xerces.internal.", diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/String/ToLowerCase.java --- a/test/java/lang/String/ToLowerCase.java Mon Oct 21 15:00:56 2013 +0100 +++ b/test/java/lang/String/ToLowerCase.java Tue Oct 22 12:33:33 2013 +0100 @@ -23,7 +23,7 @@ /* @test - @bug 4217441 4533872 4900935 + @bug 4217441 4533872 4900935 8020037 @summary toLowerCase should lower-case Greek Sigma correctly depending on the context (final/non-final). Also it should handle Locale specific (lt, tr, and az) lowercasings and supplementary @@ -69,10 +69,11 @@ test("\u00CD", Locale.US, "\u00ED"); test("\u0128", Locale.US, "\u0129"); - // I-dot tests (Turkish and Azeri) + // I-dot tests test("\u0130", turkish, "i"); test("\u0130", az, "i"); - test("\u0130", Locale.US, "i\u0307"); + test("\u0130", lt, "i"); + test("\u0130", Locale.US, "i"); // Remove dot_above in the sequence I + dot_above (Turkish and Azeri) test("I\u0307", turkish, "i"); diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/annotation/repeatingAnnotations/NonInheritableContainee.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/annotation/repeatingAnnotations/NonInheritableContainee.java Tue Oct 22 12:33:33 2013 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8019420 + * @summary Repeatable non-inheritable annotation types are mishandled by Core Reflection + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; + +public class NonInheritableContainee { + + @Retention(RetentionPolicy.RUNTIME) + @Repeatable(InheritedAnnotationContainer.class) + @interface NonInheritedAnnotationRepeated { + String name(); + } + + @Inherited + @Retention(RetentionPolicy.RUNTIME) + @interface InheritedAnnotationContainer { + NonInheritedAnnotationRepeated[] value(); + } + + @NonInheritedAnnotationRepeated(name="A") + @NonInheritedAnnotationRepeated(name="B") + class Parent {} + class Sample extends Parent {} + + + public static void main(String[] args) { + + Annotation[] anns = Sample.class.getAnnotationsByType( + NonInheritedAnnotationRepeated.class); + + if (anns.length != 0) + throw new RuntimeException("Non-@Inherited containees should not " + + "be inherited even though its container is @Inherited."); + } +} diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/annotation/repeatingAnnotations/OrderUnitTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/annotation/repeatingAnnotations/OrderUnitTest.java Tue Oct 22 12:33:33 2013 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8004912 + * @summary Unit test for order of annotations returned by get[Declared]AnnotationsByType. + * + * @run main OrderUnitTest + */ + +import java.lang.annotation.*; +import java.lang.reflect.*; + +public class OrderUnitTest { + + public static void main(String[] args) { + testOrder(Case1.class); + testOrder(Case2.class); + } + + private static void testOrder(AnnotatedElement e) { + Annotation[] decl = e.getDeclaredAnnotations(); + Foo[] declByType = e.getDeclaredAnnotationsByType(Foo.class); + + if (decl[0] instanceof Foo != declByType[0].isDirect() || + decl[1] instanceof Foo != declByType[1].isDirect()) { + throw new RuntimeException("Order of directly / indirectly present " + + "annotations from getDeclaredAnnotationsByType does not " + + "match order from getDeclaredAnnotations."); + } + } +} + +@Retention(RetentionPolicy.RUNTIME) +@interface FooContainer { + Foo[] value(); +} + +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(FooContainer.class) +@interface Foo { + boolean isDirect(); +} + + +@Foo(isDirect = true) @FooContainer({@Foo(isDirect = false)}) +class Case1 { +} + + +@FooContainer({@Foo(isDirect = false)}) @Foo(isDirect = true) +class Case2 { +} diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java --- a/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java Mon Oct 21 15:00:56 2013 +0100 +++ b/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java Tue Oct 22 12:33:33 2013 +0100 @@ -23,7 +23,7 @@ /* * @test - * @bug 7154390 8005712 8007278 + * @bug 7154390 8005712 8007278 8004912 * @summary Unit test for repeated annotation reflection * * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java @@ -51,6 +51,12 @@ inheritedMe3(); inheritedMe4(); + inheritedMe5(); // ContainerOnSuperSingleOnSub + inheritedMe6(); // RepeatableOnSuperSingleOnSub + inheritedMe7(); // SingleAnnoOnSuperContainerOnSub + inheritedMe8(); // SingleOnSuperRepeatableOnSub + + // CONSTRUCTOR checkMultiplier(Me1.class.getConstructor(new Class[0]), 10); @@ -159,6 +165,30 @@ check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 1000); } + static void inheritedMe5() { + AnnotatedElement e = Me5.class; + check(2 == e.getAnnotations().length); + check(1 == countAnnotation(e, InheritedContainee.class)); + } + + static void inheritedMe6() { + AnnotatedElement e = Me6.class; + check(2 == e.getAnnotations().length); + check(1 == countAnnotation(e, InheritedContainee.class)); + } + + static void inheritedMe7() { + AnnotatedElement e = Me7.class; + check(2 == e.getAnnotations().length); + check(2 == countAnnotation(e, InheritedContainee.class)); + } + + static void inheritedMe8() { + AnnotatedElement e = Me8.class; + check(2 == e.getAnnotations().length); + check(2 == countAnnotation(e, InheritedContainee.class)); + } + static void checkMultiplier(AnnotatedElement e, int m) { // Basic sanity of non-repeating getAnnotation(Class) check(e.getAnnotation(NonRepeated.class).value() == 5 * m); @@ -252,3 +282,31 @@ @InheritedContainee(1000) @InheritedContainee(2000) @InheritedContainee(3000) @InheritedContainee(4000) @Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000) class Me4 extends Father {} + + +@InheritedContainer({@InheritedContainee(1), @InheritedContainee(2)}) +class SuperOf5 {} + +@InheritedContainee(3) +class Me5 extends SuperOf5{} + + +@InheritedContainee(1) @InheritedContainee(2) +class SuperOf6 {} + +@InheritedContainee(3) +class Me6 extends SuperOf6 {} + + +@InheritedContainee(1) +class SuperOf7 {} + +@InheritedContainer({@InheritedContainee(2), @InheritedContainee(3)}) +class Me7 extends SuperOf7 {} + + +@InheritedContainee(1) +class SuperOf8 {} + +@InheritedContainee(2) @InheritedContainee(3) +class Me8 extends SuperOf8 {} diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/instrument/RedefineMethodInBacktrace.sh --- a/test/java/lang/instrument/RedefineMethodInBacktrace.sh Mon Oct 21 15:00:56 2013 +0100 +++ b/test/java/lang/instrument/RedefineMethodInBacktrace.sh Tue Oct 22 12:33:33 2013 +0100 @@ -62,6 +62,10 @@ RedefineMethodInBacktraceTarget.java "${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . RedefineMethodInBacktraceTarget.java +cp "${TESTSRC}"/RedefineMethodInBacktraceTargetB_2.java \ + RedefineMethodInBacktraceTargetB.java +"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . RedefineMethodInBacktraceTargetB.java + "${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodInBacktraceAgent.jar \ -classpath "${TESTCLASSES}" RedefineMethodInBacktraceApp > output.log 2>&1 RUN_RESULT=$? diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/instrument/RedefineMethodInBacktraceApp.java --- a/test/java/lang/instrument/RedefineMethodInBacktraceApp.java Mon Oct 21 15:00:56 2013 +0100 +++ b/test/java/lang/instrument/RedefineMethodInBacktraceApp.java Tue Oct 22 12:33:33 2013 +0100 @@ -21,12 +21,17 @@ * questions. */ +import com.sun.management.DiagnosticCommandMBean; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.lang.instrument.ClassDefinition; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.concurrent.CountDownLatch; +import sun.management.ManagementFactoryHelper; /** * When an exception is thrown, the JVM collects just enough information @@ -49,8 +54,12 @@ System.exit(0); } + public static CountDownLatch stop = new CountDownLatch(1); + public static CountDownLatch called = new CountDownLatch(1); + private void doTest() throws Exception { doMethodInBacktraceTest(); + doMethodInBacktraceTestB(); } private void doMethodInBacktraceTest() throws Exception { @@ -63,6 +72,36 @@ touchRedefinedMethodInBacktrace(t); } + private void doMethodInBacktraceTestB() throws Exception { + // Start a thread which blocks in method + Thread t = new Thread(RedefineMethodInBacktraceTargetB::methodToRedefine); + t.setDaemon(true); + t.start(); + + // Wait here until the new thread is in the method we want to redefine + called.await(); + + // Now redefine the class while the method is still on the stack of the new thread + doRedefine(RedefineMethodInBacktraceTargetB.class); + + // Do thread dumps in two different ways (to exercise different code paths) + // while the old class is still on the stack + + ThreadInfo[] tis = ManagementFactory.getThreadMXBean().dumpAllThreads(false, false); + for(ThreadInfo ti : tis) { + System.out.println(ti); + } + + String[] threadPrintArgs = {}; + Object[] dcmdArgs = {threadPrintArgs}; + String[] signature = {String[].class.getName()}; + DiagnosticCommandMBean dcmd = ManagementFactoryHelper.getDiagnosticCommandMBean(); + System.out.println(dcmd.invoke("threadPrint", dcmdArgs, signature)); + + // release the thread + stop.countDown(); + } + private static Throwable getThrowableFromMethodToRedefine() throws Exception { Class c = RedefineMethodInBacktraceTarget.class; diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/instrument/RedefineMethodInBacktraceTargetB.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/instrument/RedefineMethodInBacktraceTargetB.java Tue Oct 22 12:33:33 2013 +0100 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The first version of this class. The second version is in + * RedefineMethodInBacktraceTargetB_2.java. + */ +public class RedefineMethodInBacktraceTargetB { + public static void methodToRedefine() { + try { + // signal that we are here + RedefineMethodInBacktraceApp.called.countDown(); + + // wait until test is done + RedefineMethodInBacktraceApp.stop.await(); + } catch (InterruptedException ex) { + // ignore, test will fail + } + } +} diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/instrument/RedefineMethodInBacktraceTargetB_2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/instrument/RedefineMethodInBacktraceTargetB_2.java Tue Oct 22 12:33:33 2013 +0100 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This is the second version of this class. The first version is in + * RedefineMethodInBacktraceTargetB.java. + */ +public class RedefineMethodInBacktraceTargetB { + public static void methodToRedefine() { + } +} diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java --- a/test/java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java Mon Oct 21 15:00:56 2013 +0100 +++ b/test/java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java Tue Oct 22 12:33:33 2013 +0100 @@ -44,30 +44,86 @@ import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; import org.testng.annotations.Test; import static helper.Mod.*; import static helper.Declared.*; import helper.Mod; + public class DefaultStaticInvokeTest { + // getMethods(): Make sure getMethods returns the expected methods. @Test(dataProvider = "testCasesAll", dataProviderClass = DefaultStaticTestData.class) public void testGetMethods(String testTarget, Object param) throws Exception { - // test the methods retrieved by getMethods() testMethods(ALL_METHODS, testTarget, param); } + + // getDeclaredMethods(): Make sure getDeclaredMethods returns the expected methods. @Test(dataProvider = "testCasesAll", dataProviderClass = DefaultStaticTestData.class) public void testGetDeclaredMethods(String testTarget, Object param) throws Exception { - // test the methods retrieved by getDeclaredMethods() testMethods(DECLARED_ONLY, testTarget, param); } + + // getMethod(): Make sure that getMethod finds all methods it should find. + @Test(dataProvider = "testCasesAll", + dataProviderClass = DefaultStaticTestData.class) + public void testGetMethod(String testTarget, Object param) + throws Exception { + + Class typeUnderTest = Class.forName(testTarget); + + MethodDesc[] descs = typeUnderTest.getAnnotationsByType(MethodDesc.class); + + for (MethodDesc desc : descs) { + assertTrue(isFoundByGetMethod(typeUnderTest, + desc.name(), + argTypes(param))); + } + } + + + // getMethod(): Make sure that getMethod does *not* find certain methods. + @Test(dataProvider = "testCasesAll", + dataProviderClass = DefaultStaticTestData.class) + public void testGetMethodSuperInterfaces(String testTarget, Object param) + throws Exception { + + // Make sure static methods in superinterfaces are not found (unless the type under + // test declares a static method with the same signature). + + Class typeUnderTest = Class.forName(testTarget); + + for (Class interfaze : typeUnderTest.getInterfaces()) { + + for (MethodDesc desc : interfaze.getAnnotationsByType(MethodDesc.class)) { + + boolean isStatic = desc.mod() == STATIC; + + boolean declaredInThisType = isMethodDeclared(typeUnderTest, + desc.name()); + + boolean expectedToBeFound = !isStatic || declaredInThisType; + + if (expectedToBeFound) + continue; // already tested in testGetMethod() + + assertFalse(isFoundByGetMethod(typeUnderTest, + desc.name(), + argTypes(param))); + } + } + } + + + // Method.invoke(): Make sure Method.invoke returns the expected value. @Test(dataProvider = "testCasesAll", dataProviderClass = DefaultStaticTestData.class) public void testMethodInvoke(String testTarget, Object param) @@ -78,11 +134,13 @@ // test the method retrieved by Class.getMethod(String, Object[]) for (MethodDesc toTest : expectedMethods) { String name = toTest.name(); - Method m = getTestMethod(typeUnderTest, name, param); + Method m = typeUnderTest.getMethod(name, argTypes(param)); testThisMethod(toTest, m, typeUnderTest, param); } } + + // MethodHandle.invoke(): Make sure MethodHandle.invoke returns the expected value. @Test(dataProvider = "testCasesAll", dataProviderClass = DefaultStaticTestData.class) public void testMethodHandleInvoke(String testTarget, Object param) @@ -116,6 +174,7 @@ } + // Lookup.findStatic / .findVirtual: Make sure IllegalAccessException is thrown as expected. @Test(dataProvider = "testClasses", dataProviderClass = DefaultStaticTestData.class) public void testIAE(String testTarget, Object param) @@ -128,7 +187,7 @@ String mName = toTest.name(); Mod mod = toTest.mod(); if (mod != STATIC && typeUnderTest.isInterface()) { - return; + continue; } Exception caught = null; try { @@ -136,10 +195,12 @@ } catch (Exception e) { caught = e; } - assertTrue(caught != null); + assertNotNull(caught); assertEquals(caught.getClass(), IllegalAccessException.class); } } + + private static final String[] OBJECT_METHOD_NAMES = { "equals", "hashCode", @@ -192,15 +253,15 @@ myMethods.put(mName, m); } } - assertEquals(expectedMethods.length, myMethods.size()); + + assertEquals(myMethods.size(), expectedMethods.length); for (MethodDesc toTest : expectedMethods) { String name = toTest.name(); - Method candidate = myMethods.get(name); + Method candidate = myMethods.remove(name); assertNotNull(candidate); - myMethods.remove(name); testThisMethod(toTest, candidate, typeUnderTest, param); @@ -210,6 +271,7 @@ assertTrue(myMethods.isEmpty()); } + private void testThisMethod(MethodDesc toTest, Method method, Class typeUnderTest, Object param) throws Exception { // Test modifiers, and invoke @@ -256,37 +318,52 @@ assertFalse(method.isDefault()); break; default: - assertFalse(true); //this should never happen + fail(); //this should never happen break; } } + + private boolean isMethodDeclared(Class type, String name) { + MethodDesc[] methDescs = type.getAnnotationsByType(MethodDesc.class); + for (MethodDesc desc : methDescs) { + if (desc.declared() == YES && desc.name().equals(name)) + return true; + } + return false; + } + + + private boolean isFoundByGetMethod(Class c, String method, Class... argTypes) { + try { + c.getMethod(method, argTypes); + return true; + } catch (NoSuchMethodException notFound) { + return false; + } + } + + + private Class[] argTypes(Object param) { + return param == null ? new Class[0] : new Class[] { Object.class }; + } + + private Object tryInvoke(Method m, Class receiverType, Object param) throws Exception { Object receiver = receiverType == null ? null : receiverType.newInstance(); - Object result = null; - if (param == null) { - result = m.invoke(receiver); - } else { - result = m.invoke(receiver, param); - } - return result; + Object[] args = param == null ? new Object[0] : new Object[] { param }; + return m.invoke(receiver, args); } - private Method getTestMethod(Class clazz, String methodName, Object param) - throws NoSuchMethodException { - Class[] paramsType = (param != null) - ? new Class[]{Object.class} - : new Class[]{}; - return clazz.getMethod(methodName, paramsType); - } private MethodHandle getTestMH(Class clazz, String methodName, Object param) throws Exception { return getTestMH(clazz, methodName, param, false); } + private MethodHandle getTestMH(Class clazz, String methodName, Object param, boolean isNegativeTest) throws Exception { diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/reflect/DefaultStaticTest/DefaultStaticTestData.java --- a/test/java/lang/reflect/DefaultStaticTest/DefaultStaticTestData.java Mon Oct 21 15:00:56 2013 +0100 +++ b/test/java/lang/reflect/DefaultStaticTest/DefaultStaticTestData.java Tue Oct 22 12:33:33 2013 +0100 @@ -172,7 +172,7 @@ @MethodDesc(name = "defaultMethod", retval = "TestIF8.TestClass8", mod = DEFAULT, declared = NO) class TestClass8 implements TestIF8 { -}; +} @MethodDesc(name = "defaultMethod", retval = "TestIF9.defaultMethod", mod = DEFAULT, declared = YES) interface TestIF9 extends TestIF1 { @@ -218,7 +218,6 @@ } @MethodDesc(name = "defaultMethod", retval = "TestIF12.defaultMethod", mod = DEFAULT, declared = YES) -@MethodDesc(name = "staticMethod", retval = "TestIF2.staticMethod", mod = STATIC, declared = NO) interface TestIF12 extends TestIF2 { default String defaultMethod() { @@ -299,7 +298,7 @@ @MethodDesc(name = "defaultMethod", retval = "TestIF16.defaultMethod", mod = DEFAULT, declared = NO) class TestClass16 implements TestIF16 { -}; +} @MethodDesc(name = "defaultMethod", retval = "TestIF17.defaultMethod", mod = DEFAULT, declared = YES) @MethodDesc(name = "staticMethod", retval = "TestIF17.staticMethod", mod = STATIC, declared = YES) @@ -318,6 +317,12 @@ class TestClass17 implements TestIF17 { } + +@MethodDesc(name = "defaultMethod", retval = "TestIF17.defaultMethod", mod = DEFAULT, declared = NO) +class TestClass18 extends TestClass17 { +} + + @Retention(RetentionPolicy.RUNTIME) @Repeatable(MethodDescs.class) @interface MethodDesc { @@ -332,6 +337,41 @@ MethodDesc[] value(); } +//Diamond Case for static method +@MethodDesc(name = "staticMethod", retval = "TestIF2A.staticMethod", mod = STATIC, declared = YES) +interface TestIF2A extends TestIF2 { + static String staticMethod() { + return "TestIF2A.staticMethod"; + } +} + +@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = YES) +interface TestIF2B extends TestIF2 { + String method(); +} + +@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = YES) +interface TestIF18 extends TestIF10, TestIF2A { + String method(); +} + +@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = NO) +@MethodDesc(name = "defaultMethod", retval = "TestIF12.defaultMethod", mod = DEFAULT, declared = NO) +interface TestIF19 extends TestIF12, TestIF2B { +} + +@MethodDesc(name = "staticMethod", retval = "TestIF20.staticMethod", mod = STATIC, declared = YES) +@MethodDesc(name = "defaultMethod", retval = "TestIF12.defaultMethod", mod = DEFAULT, declared = NO) +interface TestIF20 extends TestIF12, TestIF2A { + static String staticMethod() { + return "TestIF20.staticMethod"; + } +} + +@MethodDesc(name = "method", retval = "", mod = ABSTRACT, declared = NO) +interface TestIF21 extends TestIF2A, TestIF2B { +} + public class DefaultStaticTestData { /** @@ -343,22 +383,23 @@ static Object[][] testClasses() { return new Object[][]{ {"TestClass1", null}, - //{"TestClass2", null}, @ignore due to JDK-8009411 + {"TestClass2", null}, {"TestClass3", null}, - //{"TestClass4", null}, @ignore due to JDK-8009411 - //{"TestClass5", null}, @ignore due to JDK-8009411 - //{"TestClass6", null}, @ignore due to JDK-8009411 + {"TestClass4", null}, + {"TestClass5", null}, + {"TestClass6", null}, {"TestClass7", "TestIF7.TestClass7"}, {"TestClass8", "TestIF8.TestClass8"}, {"TestClass9", null}, {"TestClass91", null}, - //{"TestClass11", null}, @ignore due to JDK-8009411 - //{"TestClass12", null}, @ignore due to JDK-8009411 + {"TestClass11", null}, + {"TestClass12", null}, {"TestClass13", null}, {"TestClass14", null}, {"TestClass15", null}, - {"TestClass16", null} - //{"TestClass17", null} @ignore due to JDK-8009411 + {"TestClass16", null}, + {"TestClass17", null}, + {"TestClass18", null}, }; } @@ -372,6 +413,8 @@ return new Object[][]{ {"TestIF1", null}, {"TestIF2", null}, + {"TestIF2A", null}, + {"TestIF2B", null}, {"TestIF3", null}, {"TestIF4", null}, {"TestIF5", null}, @@ -388,7 +431,12 @@ {"TestIF1D", null}, {"TestIF15", null}, {"TestIF16", null}, - {"TestIF17", null},}; + {"TestIF17", null}, + {"TestIF18", null}, + {"TestIF19", null}, + {"TestIF20", null}, + {"TestIF21", null}, + }; } @DataProvider diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/lang/reflect/Method/InterfaceStatic/StaticInterfaceMethodInWayOfDefault.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/reflect/Method/InterfaceStatic/StaticInterfaceMethodInWayOfDefault.java Tue Oct 22 12:33:33 2013 +0100 @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8009411 + * @summary Test that a static method on an interface doesn't hide a default + * method with the same name and signature in a separate compilation + * scenario. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + +import sun.misc.IOUtils; + +public class StaticInterfaceMethodInWayOfDefault { + public interface A_v1 { + } + + public interface A_v2 { + default void m() { + System.err.println("A.m() called"); + } + } + + public interface B extends A_v1 { + static void m() { + System.err.println("B.m() called"); + } + } + + public interface C_v1 extends B { + default void m() { + System.err.println("C.m() called"); + } + } + + public interface C_v2 extends B { + } + + public static class TestTask implements Callable { + @Override + public String call() { + try { + Method m = C_v1.class.getMethod("m", (Class[])null); + return m.getDeclaringClass().getSimpleName(); + } catch (NoSuchMethodException e) { + System.err.println("Couldn't find method"); + return "ERROR"; + } + } + } + + public static void main(String[] args) throws Exception { + int errors = 0; + Callable v1Task = new TestTask(); + + ClassLoader v2Loader = new V2ClassLoader( + StaticInterfaceMethodInWayOfDefault.class.getClassLoader()); + Callable v2Task = (Callable) Class.forName( + TestTask.class.getName(), + true, + v2Loader).newInstance(); + + System.err.println("Running using _v1 classes:"); + String res = v1Task.call(); + if(!res.equals("C_v1")) { + System.err.println("Got wrong method, expecting C_v1, got: " + res); + errors++; + } + + System.err.println("Running using _v2 classes:"); + res = v2Task.call(); + if(!res.equals("A_v1")) { + System.err.println("Got wrong method, expecting A_v1, got: " + res); + errors++; + } + + if (errors != 0) + throw new RuntimeException("Errors found, check log for details"); + } + + /** + * A ClassLoader implementation that loads alternative implementations of + * classes. If class name ends with "_v1" it locates instead a class with + * name ending with "_v2" and loads that class instead. + */ + static class V2ClassLoader extends ClassLoader { + V2ClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + if (name.indexOf('.') < 0) { // root package is our class + synchronized (getClassLoadingLock(name)) { + // First, check if the class has already been loaded + Class c = findLoadedClass(name); + if (c == null) { + c = findClass(name); + } + if (resolve) { + resolveClass(c); + } + return c; + } + } + else { // not our class + return super.loadClass(name, resolve); + } + } + + @Override + protected Class findClass(String name) + throws ClassNotFoundException { + // special class name -> replace it with alternative name + if (name.endsWith("_v1")) { + String altName = name.substring(0, name.length() - 3) + "_v2"; + String altPath = altName.replace('.', '/').concat(".class"); + try (InputStream is = getResourceAsStream(altPath)) { + if (is != null) { + byte[] bytes = IOUtils.readFully(is, -1, true); + // patch class bytes to contain original name + for (int i = 0; i < bytes.length - 2; i++) { + if (bytes[i] == '_' && + bytes[i + 1] == 'v' && + bytes[i + 2] == '2') { + bytes[i + 2] = '1'; + } + } + return defineClass(name, bytes, 0, bytes.length); + } + else { + throw new ClassNotFoundException(name); + } + } + catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + else { // not special class name -> just load the class + String path = name.replace('.', '/').concat(".class"); + try (InputStream is = getResourceAsStream(path)) { + if (is != null) { + byte[] bytes = IOUtils.readFully(is, -1, true); + return defineClass(name, bytes, 0, bytes.length); + } + else { + throw new ClassNotFoundException(name); + } + } + catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + } + } +} diff -r d7ef65d3ee57 -r 1c85f50e2622 test/java/nio/channels/FileChannel/InterruptMapDeadlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/nio/channels/FileChannel/InterruptMapDeadlock.java Tue Oct 22 12:33:33 2013 +0100 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8024833 + * @summary Tests interruption of threads mapping sections of a file channel in + * an attempt to deadlock due to nesting of begin calls. + */ +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.nio.channels.FileChannel.MapMode; +import java.nio.file.*; +import java.util.concurrent.Semaphore; +import static java.nio.file.StandardOpenOption.*; + +public class InterruptMapDeadlock { + + static class Mapper extends Thread { + final FileChannel fc; + final Semaphore gate; + volatile Exception exception; + + Mapper(FileChannel fc, Semaphore gate) { + this.fc = fc; + this.gate = gate; + } + + @Override + public void run() { + try { + gate.acquireUninterruptibly(); + fc.map(MapMode.READ_ONLY, 0, 1); + throw new Exception("Map succeeded"); + } catch (IOException x) { + System.out.println(x.getClass() + " (expected)"); + } catch (Exception unexpected) { + this.exception = unexpected; + } + } + + Exception exception() { + return exception; + } + + static Mapper startMapper(FileChannel fc, Semaphore gate) { + Mapper r = new Mapper(fc, gate); + r.setDaemon(true); + r.start(); + return r; + } + } + + static class Interruptor extends Thread { + + final Mapper[] mappers; + final Semaphore gate; + + Interruptor(Mapper[] mappers, Semaphore gate) { + this.mappers = mappers; + this.gate = gate; + } + + public void run() { + gate.release(mappers.length); + for (Mapper m : mappers) { + m.interrupt(); + } + } + } + // the number of mapper threads to start + private static final int MAPPER_COUNT = 4; + + public static void main(String[] args) throws Exception { + Path file = Paths.get("data.txt"); + FileChannel.open(file, CREATE, TRUNCATE_EXISTING, WRITE).close(); + + Mapper[] mappers = new Mapper[MAPPER_COUNT]; + + for (int i=1; i<=20; i++) { + System.out.format("Iteration: %s%n", i); + + FileChannel fc = FileChannel.open(file); + boolean failed = false; + + Semaphore gate = new Semaphore(0); + // start mapper threads + for (int j=0; j preferred = new HashSet<>(Arrays.asList(new ZoneId[] { - ZoneId.of("EST"), + ZoneId.of("EST", ZoneId.SHORT_IDS), ZoneId.of("Asia/Taipei"), ZoneId.of("CET"), })); private static Set preferred_s = new HashSet<>(Arrays.asList(new ZoneId[] { - ZoneId.of("EST"), + ZoneId.of("EST", ZoneId.SHORT_IDS), ZoneId.of("CET"), ZoneId.of("Australia/South"), ZoneId.of("Australia/West"), @@ -131,7 +131,7 @@ Object[][] data_preferredZones() { return new Object[][] { {"America/New_York", "Eastern Standard Time", none, Locale.ENGLISH, TextStyle.FULL}, - {"EST", "Eastern Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL}, +// {"EST", "Eastern Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL}, {"Europe/Paris", "Central European Time", none, Locale.ENGLISH, TextStyle.FULL}, {"CET", "Central European Time", preferred, Locale.ENGLISH, TextStyle.FULL}, {"Asia/Shanghai", "China Standard Time", none, Locale.ENGLISH, TextStyle.FULL}, diff -r d7ef65d3ee57 -r 1c85f50e2622 test/sun/nio/cs/TestIBMBugs.java --- a/test/sun/nio/cs/TestIBMBugs.java Mon Oct 21 15:00:56 2013 +0100 +++ b/test/sun/nio/cs/TestIBMBugs.java Tue Oct 22 12:33:33 2013 +0100 @@ -147,16 +147,17 @@ } private static void bug6569191 () throws Exception { - byte[] bs = new byte[] { (byte)0x81, (byte)0xad, - (byte)0x81, (byte)0xae, - (byte)0x81, (byte)0xaf, - (byte)0x81, (byte)0xb0, - (byte)0x85, (byte)0x81, - (byte)0x85, (byte)0x87, - (byte)0x85, (byte)0xe0, - (byte)0x85, (byte)0xf0 }; + byte[] bs = new byte[] { (byte)0x81, (byte)0xad, // fffd ff6d + (byte)0x81, (byte)0xae, // fffd ff6e + (byte)0x81, (byte)0xaf, // fffd ff6f + (byte)0x81, (byte)0xb0, // fffd ff70 + (byte)0x85, (byte)0x81, // fffd -> + (byte)0x85, (byte)0x87, // 2266 -> + (byte)0x85, (byte)0xe0, // 32a4 -> + (byte)0x85, (byte)0xf0 };// 7165 fffd String s = new String(bs, "Cp943"); - if (!"\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd" + // see DoubleByte for how the unmappables are handled + if (!"\ufffd\uff6d\ufffd\uff6e\ufffd\uff6f\ufffd\uff70\ufffd\u2266\u32a4\u7165\ufffd" .equals(s)) throw new Exception("Cp943 failed"); } diff -r d7ef65d3ee57 -r 1c85f50e2622 test/sun/nio/cs/TestUnmappable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/nio/cs/TestUnmappable.java Tue Oct 22 12:33:33 2013 +0100 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/* + * @test + * @bug 8008386 + * @summary (cs) Unmappable leading should be decoded to replacement. + * Tests for Shift_JIS and MS932 decoding + * @run main TestUnmappable + */ + +import java.nio.*; +import java.nio.charset.*; + +public class TestUnmappable { + public static void main(String args[]) throws Exception { + + // illegal leading character test + byte[][] inputBytes = { + // Shift_JIS + {(byte)0xce, (byte)0xa0, (byte)0xce, (byte)0x7a}, + // MS932 + {(byte)0x3c, (byte)0x21, (byte)0x2d, (byte)0x2d, + (byte)0xe5, (byte)0xaf, (byte)0xbe, (byte)0xe5, + (byte)0xbf, (byte)0x9c, (byte)0x2d, (byte)0x2d, + (byte)0x3e, (byte)0xd, (byte)0xa }, + {(byte)0x81, (byte)0xad}, + // PCK + {(byte)0xef, (byte)0x90}, + {(byte)0x91, (byte)0xfd} + }; + + String[] charsets = { "Shift_JIS", "MS932", "PCK" }; + String[] expectedStrings = { + // Shift_JIS + "0xce 0x3f 0xce 0x7a ", + // MS932 + "0x3c 0x21 0x2d 0x2d 0xe5 0xaf 0xbe 0xe5 0xbf " + + "0x3f 0x2d 0x2d 0x3e 0xd 0xa ", + "0x3f 0xad ", + // PCK + "0x3f 0x3f ", + "0x3f "}; + + for (int i = 0; i < charsets.length; i++) { + String ret = new String(inputBytes[i], charsets[i]); + String bString = getByteString(ret.getBytes(Charset.forName(charsets[i]))); + if (expectedStrings[i].length() != bString.length() + || ! expectedStrings[i].equals(bString)){ + throw new Exception("ByteToChar for " + charsets[i] + + " does not work correctly.\n" + + "Expected: " + expectedStrings[i] + "\n" + + "Received: " + bString); + } + } + } + + private static String getByteString(byte[] bytes) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + sb.append("0x" + Integer.toHexString((int)(bytes[i] & 0xFF)) + " "); + } + return sb.toString(); + } +}