Mercurial > hg > openjdk > bsd-port > jdk
changeset 7822:598ef39fd47a
Merge
author | lana |
---|---|
date | Tue, 11 Mar 2014 23:31:58 -0700 |
parents | eeb571eea68d (current diff) 472f8d774ecd (diff) |
children | 1a4618c1f1bb |
files | src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java |
diffstat | 22 files changed, 968 insertions(+), 305 deletions(-) [+] |
line wrap: on
line diff
--- a/make/common/Defs-embedded.gmk Thu Feb 27 10:36:18 2014 -0800 +++ b/make/common/Defs-embedded.gmk Tue Mar 11 23:31:58 2014 -0700 @@ -71,7 +71,9 @@ # and it must be linked after fdlibm - this places it at the end after libc # -z muldefs avoids linker errors for duplicate symbols. ifeq ($(CROSS_COMPILE_ARCH), arm) - EXTRA_LIBS += $(EXT_LIBS_PATH)/sflt_glibc_jdk.a -Xlinker -z -Xlinker muldefs + ifneq ($(EXT_LIBS_PATH),) + EXTRA_LIBS += $(EXT_LIBS_PATH)/sflt_glibc_jdk.a -Xlinker -z -Xlinker muldefs + endif endif endif
--- a/make/sun/lwawt/FILES_export_macosx.gmk Thu Feb 27 10:36:18 2014 -0800 +++ b/make/sun/lwawt/FILES_export_macosx.gmk Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -141,7 +141,6 @@ sun/lwawt/macosx/CMenuBar.java \ sun/lwawt/macosx/CMenuComponent.java \ sun/lwawt/macosx/CMenuItem.java \ - sun/lwawt/macosx/CMouseInfoPeer.java \ sun/lwawt/macosx/CPlatformView.java \ sun/lwawt/macosx/CPlatformWindow.java \ sun/lwawt/macosx/CPlatformComponent.java \
--- a/src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java Thu Feb 27 10:36:18 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.lwawt.macosx; - -import java.awt.Window; -import sun.lwawt.LWMouseInfoPeer; -import sun.lwawt.LWWindowPeer; - -public class CMouseInfoPeer extends LWMouseInfoPeer -{ - //If a new window is to appear under the cursor, - //we get wrong window. - //This is a workaround for macosx. - @Override - public boolean isWindowUnderMouse(Window w) { - if (w == null) { - return false; - } - - return ((LWWindowPeer)w.getPeer()).getPlatformWindow().isUnderMouse(); - } -}
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Feb 27 10:36:18 2014 -0800 +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, 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 @@ -300,11 +300,6 @@ } @Override - protected MouseInfoPeer createMouseInfoPeerImpl() { - return new CMouseInfoPeer(); - } - - @Override protected int getScreenHeight() { return GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration().getBounds().height;
--- a/src/macosx/native/sun/awt/AWTView.m Thu Feb 27 10:36:18 2014 -0800 +++ b/src/macosx/native/sun/awt/AWTView.m Tue Mar 11 23:31:58 2014 -0700 @@ -387,7 +387,7 @@ [rolloverTrackingArea release]; } - int options = (NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | + int options = (NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag); rolloverTrackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect]
--- a/src/share/classes/java/lang/Class.java Thu Feb 27 10:36:18 2014 -0800 +++ b/src/share/classes/java/lang/Class.java Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -2338,44 +2338,110 @@ } /** + * Atomic operations support. + */ + private static class Atomic { + // initialize Unsafe machinery here, since we need to call Class.class instance method + // and have to avoid calling it in the static initializer of the Class class... + private static final Unsafe unsafe = Unsafe.getUnsafe(); + // offset of Class.reflectionData instance field + private static final long reflectionDataOffset; + // offset of Class.annotationType instance field + private static final long annotationTypeOffset; + + static { + Field[] fields = Class.class.getDeclaredFields0(false); // bypass caches + reflectionDataOffset = objectFieldOffset(fields, "reflectionData"); + annotationTypeOffset = objectFieldOffset(fields, "annotationType"); + } + + private static long objectFieldOffset(Field[] fields, String fieldName) { + Field field = searchFields(fields, fieldName); + if (field == null) { + throw new Error("No " + fieldName + " field found in java.lang.Class"); + } + return unsafe.objectFieldOffset(field); + } + + static <T> boolean casReflectionData(Class<?> clazz, + SoftReference<ReflectionData<T>> oldData, + SoftReference<ReflectionData<T>> newData) { + return unsafe.compareAndSwapObject(clazz, reflectionDataOffset, oldData, newData); + } + + static <T> boolean casAnnotationType(Class<?> clazz, + AnnotationType oldType, + AnnotationType newType) { + return unsafe.compareAndSwapObject(clazz, annotationTypeOffset, oldType, newType); + } + } + + /** * Reflection support. */ // Caches for certain reflective results private static boolean useCaches = true; - private volatile transient SoftReference<Field[]> declaredFields; - private volatile transient SoftReference<Field[]> publicFields; - private volatile transient SoftReference<Method[]> declaredMethods; - private volatile transient SoftReference<Method[]> publicMethods; - private volatile transient SoftReference<Constructor<T>[]> declaredConstructors; - private volatile transient SoftReference<Constructor<T>[]> publicConstructors; - // Intermediate results for getFields and getMethods - private volatile transient SoftReference<Field[]> declaredPublicFields; - private volatile transient SoftReference<Method[]> declaredPublicMethods; + + // reflection data that might get invalidated when JVM TI RedefineClasses() is called + static class ReflectionData<T> { + volatile Field[] declaredFields; + volatile Field[] publicFields; + volatile Method[] declaredMethods; + volatile Method[] publicMethods; + volatile Constructor<T>[] declaredConstructors; + volatile Constructor<T>[] publicConstructors; + // Intermediate results for getFields and getMethods + volatile Field[] declaredPublicFields; + volatile Method[] declaredPublicMethods; + // Value of classRedefinedCount when we created this ReflectionData instance + final int redefinedCount; + + ReflectionData(int redefinedCount) { + this.redefinedCount = redefinedCount; + } + } + + private volatile transient SoftReference<ReflectionData<T>> reflectionData; // Incremented by the VM on each call to JVM TI RedefineClasses() // that redefines this class or a superclass. private volatile transient int classRedefinedCount = 0; - // Value of classRedefinedCount when we last cleared the cached values - // that are sensitive to class redefinition. - private volatile transient int lastRedefinedCount = 0; + // Lazily create and cache ReflectionData + private ReflectionData<T> reflectionData() { + SoftReference<ReflectionData<T>> reflectionData = this.reflectionData; + int classRedefinedCount = this.classRedefinedCount; + ReflectionData<T> rd; + if (useCaches && + reflectionData != null && + (rd = reflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } + // else no SoftReference or cleared SoftReference or stale ReflectionData + // -> create and replace new instance + return newReflectionData(reflectionData, classRedefinedCount); + } - // Clears cached values that might possibly have been obsoleted by - // a class redefinition. - private void clearCachesOnClassRedefinition() { - if (lastRedefinedCount != classRedefinedCount) { - declaredFields = publicFields = declaredPublicFields = null; - declaredMethods = publicMethods = declaredPublicMethods = null; - declaredConstructors = publicConstructors = null; - annotations = declaredAnnotations = null; + private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData, + int classRedefinedCount) { + if (!useCaches) return null; - // Use of "volatile" (and synchronization by caller in the case - // of annotations) ensures that no thread sees the update to - // lastRedefinedCount before seeing the caches cleared. - // We do not guard against brief windows during which multiple - // threads might redundantly work to fill an empty cache. - lastRedefinedCount = classRedefinedCount; + while (true) { + ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount); + // try to CAS it... + if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) { + return rd; + } + // else retry + oldReflectionData = this.reflectionData; + classRedefinedCount = this.classRedefinedCount; + if (oldReflectionData != null && + (rd = oldReflectionData.get()) != null && + rd.redefinedCount == classRedefinedCount) { + return rd; + } } } @@ -2403,7 +2469,7 @@ } // Annotations handling - private native byte[] getRawAnnotations(); + native byte[] getRawAnnotations(); native ConstantPool getConstantPool(); @@ -2418,27 +2484,19 @@ // via ReflectionFactory.copyField. private Field[] privateGetDeclaredFields(boolean publicOnly) { checkInitted(); - Field[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (declaredPublicFields != null) { - res = declaredPublicFields.get(); - } - } else { - if (declaredFields != null) { - res = declaredFields.get(); - } - } + Field[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicFields : rd.declaredFields; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); - if (useCaches) { + if (rd != null) { if (publicOnly) { - declaredPublicFields = new SoftReference<>(res); + rd.declaredPublicFields = res; } else { - declaredFields = new SoftReference<>(res); + rd.declaredFields = res; } } return res; @@ -2449,12 +2507,10 @@ // via ReflectionFactory.copyField. private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) { checkInitted(); - Field[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicFields != null) { - res = publicFields.get(); - } + Field[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = rd.publicFields; if (res != null) return res; } @@ -2487,8 +2543,8 @@ res = new Field[fields.size()]; fields.toArray(res); - if (useCaches) { - publicFields = new SoftReference<>(res); + if (rd != null) { + rd.publicFields = res; } return res; } @@ -2511,18 +2567,10 @@ // instead be copied via ReflectionFactory.copyConstructor. private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) { checkInitted(); - Constructor<T>[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (publicConstructors != null) { - res = publicConstructors.get(); - } - } else { - if (declaredConstructors != null) { - res = declaredConstructors.get(); - } - } + Constructor<T>[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.publicConstructors : rd.declaredConstructors; if (res != null) return res; } // No cached value available; request value from VM @@ -2531,11 +2579,11 @@ } else { res = getDeclaredConstructors0(publicOnly); } - if (useCaches) { + if (rd != null) { if (publicOnly) { - publicConstructors = new SoftReference<>(res); + rd.publicConstructors = res; } else { - declaredConstructors = new SoftReference<>(res); + rd.declaredConstructors = res; } } return res; @@ -2552,27 +2600,19 @@ // via ReflectionFactory.copyMethod. private Method[] privateGetDeclaredMethods(boolean publicOnly) { checkInitted(); - Method[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicOnly) { - if (declaredPublicMethods != null) { - res = declaredPublicMethods.get(); - } - } else { - if (declaredMethods != null) { - res = declaredMethods.get(); - } - } + Method[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods; if (res != null) return res; } // No cached value available; request value from VM res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); - if (useCaches) { + if (rd != null) { if (publicOnly) { - declaredPublicMethods = new SoftReference<>(res); + rd.declaredPublicMethods = res; } else { - declaredMethods = new SoftReference<>(res); + rd.declaredMethods = res; } } return res; @@ -2674,12 +2714,10 @@ // via ReflectionFactory.copyMethod. private Method[] privateGetPublicMethods() { checkInitted(); - Method[] res = null; - if (useCaches) { - clearCachesOnClassRedefinition(); - if (publicMethods != null) { - res = publicMethods.get(); - } + Method[] res; + ReflectionData<T> rd = reflectionData(); + if (rd != null) { + res = rd.publicMethods; if (res != null) return res; } @@ -2727,8 +2765,8 @@ methods.addAllIfNotPresent(inheritedMethods); methods.compactAndTrim(); res = methods.getArray(); - if (useCaches) { - publicMethods = new SoftReference<>(res); + if (rd != null) { + rd.publicMethods = res; } return res; } @@ -2738,7 +2776,7 @@ // Helpers for fetchers of one field, method, or constructor // - private Field searchFields(Field[] fields, String name) { + private static Field searchFields(Field[] fields, String name) { String internedName = name.intern(); for (int i = 0; i < fields.length; i++) { if (fields[i].getName() == internedName) { @@ -2756,7 +2794,7 @@ // of Field objects which have to be created for the common // case where the field being requested is declared in the // class which is being queried. - Field res = null; + Field res; // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; @@ -2808,7 +2846,7 @@ // number of Method objects which have to be created for the // common case where the method being requested is declared in // the class which is being queried. - Method res = null; + Method res; // Search declared public methods if ((res = searchMethods(privateGetDeclaredMethods(true), name, @@ -3209,9 +3247,20 @@ // Annotations cache private transient Map<Class<? extends Annotation>, Annotation> annotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; + // Value of classRedefinedCount when we last cleared the cached annotations and declaredAnnotations fields + private transient int lastAnnotationsRedefinedCount = 0; + + // Clears cached values that might possibly have been obsoleted by + // a class redefinition. + private void clearAnnotationCachesOnClassRedefinition() { + if (lastAnnotationsRedefinedCount != classRedefinedCount) { + annotations = declaredAnnotations = null; + lastAnnotationsRedefinedCount = classRedefinedCount; + } + } private synchronized void initAnnotationsIfNecessary() { - clearCachesOnClassRedefinition(); + clearAnnotationCachesOnClassRedefinition(); if (annotations != null) return; declaredAnnotations = AnnotationParser.parseAnnotations( @@ -3233,10 +3282,11 @@ // Annotation types cache their internal (AnnotationType) form - private AnnotationType annotationType; + @SuppressWarnings("UnusedDeclaration") + private volatile transient AnnotationType annotationType; - void setAnnotationType(AnnotationType type) { - annotationType = type; + boolean casAnnotationType(AnnotationType oldType, AnnotationType newType) { + return Atomic.casAnnotationType(this, oldType, newType); } AnnotationType getAnnotationType() {
--- a/src/share/classes/java/lang/System.java Thu Feb 27 10:36:18 2014 -0800 +++ b/src/share/classes/java/lang/System.java Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -1178,12 +1178,15 @@ public sun.reflect.ConstantPool getConstantPool(Class klass) { return klass.getConstantPool(); } - public void setAnnotationType(Class klass, AnnotationType type) { - klass.setAnnotationType(type); + public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) { + return klass.casAnnotationType(oldType, newType); } public AnnotationType getAnnotationType(Class klass) { return klass.getAnnotationType(); } + public byte[] getRawClassAnnotations(Class<?> klass) { + return klass.getRawAnnotations(); + } public <E extends Enum<E>> E[] getEnumConstantsShared(Class<E> klass) { return klass.getEnumConstantsShared();
--- a/src/share/classes/sun/misc/JavaLangAccess.java Thu Feb 27 10:36:18 2014 -0800 +++ b/src/share/classes/sun/misc/JavaLangAccess.java Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -35,10 +35,10 @@ ConstantPool getConstantPool(Class klass); /** - * Set the AnnotationType instance corresponding to this class. + * Compare-And-Swap the AnnotationType instance corresponding to this class. * (This method only applies to annotation types.) */ - void setAnnotationType(Class klass, AnnotationType annotationType); + boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType); /** * Get the AnnotationType instance corresponding to this class. @@ -47,6 +47,12 @@ AnnotationType getAnnotationType(Class klass); /** + * Get the array of bytes that is the class-file representation + * of this Class' annotations. + */ + byte[] getRawClassAnnotations(Class<?> klass); + + /** * Returns the elements of an enum class or null if the * Class object does not represent an enum type; * the result is uncloned, cached, and shared by all callers.
--- a/src/share/classes/sun/reflect/annotation/AnnotationParser.java Thu Feb 27 10:36:18 2014 -0800 +++ b/src/share/classes/sun/reflect/annotation/AnnotationParser.java Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -67,7 +67,35 @@ return Collections.emptyMap(); try { - return parseAnnotations2(rawAnnotations, constPool, container); + return parseAnnotations2(rawAnnotations, constPool, container, null); + } catch(BufferUnderflowException e) { + throw new AnnotationFormatError("Unexpected end of annotations."); + } catch(IllegalArgumentException e) { + // Type mismatch in constant pool + throw new AnnotationFormatError(e); + } + } + + /** + * Like {@link #parseAnnotations(byte[], sun.reflect.ConstantPool, Class)} + * with an additional parameter {@code selectAnnotationClasses} which selects the + * annotation types to parse (other than selected are quickly skipped).<p> + * This method is only used to parse select meta annotations in the construction + * phase of {@link AnnotationType} instances to prevent infinite recursion. + * + * @param selectAnnotationClasses an array of annotation types to select when parsing + */ + @SafeVarargs + static Map<Class<? extends Annotation>, Annotation> parseSelectAnnotations( + byte[] rawAnnotations, + ConstantPool constPool, + Class<?> container, + Class<? extends Annotation> ... selectAnnotationClasses) { + if (rawAnnotations == null) + return Collections.emptyMap(); + + try { + return parseAnnotations2(rawAnnotations, constPool, container, selectAnnotationClasses); } catch(BufferUnderflowException e) { throw new AnnotationFormatError("Unexpected end of annotations."); } catch(IllegalArgumentException e) { @@ -79,22 +107,23 @@ private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2( byte[] rawAnnotations, ConstantPool constPool, - Class<?> container) { + Class<?> container, + Class<? extends Annotation>[] selectAnnotationClasses) { Map<Class<? extends Annotation>, Annotation> result = new LinkedHashMap<Class<? extends Annotation>, Annotation>(); ByteBuffer buf = ByteBuffer.wrap(rawAnnotations); int numAnnotations = buf.getShort() & 0xFFFF; for (int i = 0; i < numAnnotations; i++) { - Annotation a = parseAnnotation(buf, constPool, container, false); + Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses); if (a != null) { Class<? extends Annotation> klass = a.annotationType(); - AnnotationType type = AnnotationType.getInstance(klass); - if (type.retention() == RetentionPolicy.RUNTIME) - if (result.put(klass, a) != null) + if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME && + result.put(klass, a) != null) { throw new AnnotationFormatError( "Duplicate annotation for class: "+klass+": " + a); } } + } return result; } @@ -191,6 +220,15 @@ ConstantPool constPool, Class<?> container, boolean exceptionOnMissingAnnotationClass) { + return parseAnnotation2(buf, constPool, container, exceptionOnMissingAnnotationClass, null); + } + + @SuppressWarnings("unchecked") + private static Annotation parseAnnotation2(ByteBuffer buf, + ConstantPool constPool, + Class<?> container, + boolean exceptionOnMissingAnnotationClass, + Class<? extends Annotation>[] selectAnnotationClasses) { int typeIndex = buf.getShort() & 0xFFFF; Class<? extends Annotation> annotationClass = null; String sig = "[unknown]"; @@ -216,6 +254,10 @@ skipAnnotation(buf, false); return null; } + if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) { + skipAnnotation(buf, false); + return null; + } AnnotationType type = null; try { type = AnnotationType.getInstance(annotationClass); @@ -791,6 +833,17 @@ skipMemberValue(buf); } + /** + * Searches for given {@code element} in given {@code array} by identity. + * Returns {@code true} if found {@code false} if not. + */ + private static boolean contains(Object[] array, Object element) { + for (Object e : array) + if (e == element) + return true; + return false; + } + /* * This method converts the annotation map returned by the parseAnnotations() * method to an array. It is called by Field.getDeclaredAnnotations(),
--- a/src/share/classes/sun/reflect/annotation/AnnotationType.java Thu Feb 27 10:36:18 2014 -0800 +++ b/src/share/classes/sun/reflect/annotation/AnnotationType.java Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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,6 +25,8 @@ package sun.reflect.annotation; +import sun.misc.JavaLangAccess; + import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; @@ -45,29 +47,28 @@ * types. This matches the return value that must be used for a * dynamic proxy, allowing for a simple isInstance test. */ - private final Map<String, Class<?>> memberTypes = new HashMap<String,Class<?>>(); + private final Map<String, Class<?>> memberTypes; /** * Member name -> default value mapping. */ - private final Map<String, Object> memberDefaults = - new HashMap<String, Object>(); + private final Map<String, Object> memberDefaults; /** - * Member name -> Method object mapping. This (and its assoicated + * Member name -> Method object mapping. This (and its associated * accessor) are used only to generate AnnotationTypeMismatchExceptions. */ - private final Map<String, Method> members = new HashMap<String, Method>(); + private final Map<String, Method> members; /** * The retention policy for this annotation type. */ - private RetentionPolicy retention = RetentionPolicy.RUNTIME;; + private final RetentionPolicy retention; /** * Whether this annotation type is inherited. */ - private boolean inherited = false; + private final boolean inherited; /** * Returns an AnnotationType instance for the specified annotation type. @@ -75,13 +76,20 @@ * @throw IllegalArgumentException if the specified class object for * does not represent a valid annotation type */ - public static synchronized AnnotationType getInstance( + public static AnnotationType getInstance( Class<? extends Annotation> annotationClass) { - AnnotationType result = sun.misc.SharedSecrets.getJavaLangAccess(). - getAnnotationType(annotationClass); - if (result == null) - result = new AnnotationType((Class<? extends Annotation>) annotationClass); + JavaLangAccess jla = sun.misc.SharedSecrets.getJavaLangAccess(); + AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read + if (result == null) { + result = new AnnotationType(annotationClass); + // try to CAS the AnnotationType: null -> result + if (!jla.casAnnotationType(annotationClass, null, result)) { + // somebody was quicker -> read it's result + result = jla.getAnnotationType(annotationClass); + assert result != null; + } + } return result; } @@ -105,6 +113,9 @@ } }); + memberTypes = new HashMap<String,Class<?>>(methods.length+1, 1.0f); + memberDefaults = new HashMap<String, Object>(0); + members = new HashMap<String, Method>(methods.length+1, 1.0f); for (Method method : methods) { if (method.getParameterTypes().length != 0) @@ -117,20 +128,27 @@ Object defaultValue = method.getDefaultValue(); if (defaultValue != null) memberDefaults.put(name, defaultValue); - - members.put(name, method); } - sun.misc.SharedSecrets.getJavaLangAccess(). - setAnnotationType(annotationClass, this); - // Initialize retention, & inherited fields. Special treatment // of the corresponding annotation types breaks infinite recursion. if (annotationClass != Retention.class && annotationClass != Inherited.class) { - Retention ret = annotationClass.getAnnotation(Retention.class); + JavaLangAccess jla = sun.misc.SharedSecrets.getJavaLangAccess(); + Map<Class<? extends Annotation>, Annotation> metaAnnotations = + AnnotationParser.parseSelectAnnotations( + jla.getRawClassAnnotations(annotationClass), + jla.getConstantPool(annotationClass), + annotationClass, + Retention.class, Inherited.class + ); + Retention ret = (Retention) metaAnnotations.get(Retention.class); retention = (ret == null ? RetentionPolicy.CLASS : ret.value()); - inherited = annotationClass.isAnnotationPresent(Inherited.class); + inherited = metaAnnotations.containsKey(Inherited.class); + } + else { + retention = RetentionPolicy.RUNTIME; + inherited = false; } } @@ -205,11 +223,10 @@ * For debugging. */ public String toString() { - StringBuffer s = new StringBuffer("Annotation Type:" + "\n"); - s.append(" Member types: " + memberTypes + "\n"); - s.append(" Member defaults: " + memberDefaults + "\n"); - s.append(" Retention policy: " + retention + "\n"); - s.append(" Inherited: " + inherited); - return s.toString(); + return "Annotation Type:\n" + + " Member types: " + memberTypes + "\n" + + " Member defaults: " + memberDefaults + "\n" + + " Retention policy: " + retention + "\n" + + " Inherited: " + inherited; } }
--- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Thu Feb 27 10:36:18 2014 -0800 +++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Tue Mar 11 23:31:58 2014 -0700 @@ -375,20 +375,22 @@ boolean add = false; for (AccessDescription ad : adList) { CertStore cs = URICertStore.getInstance(ad); - try { - if (certs.addAll((Collection<X509Certificate>) - cs.getCertificates(caSelector))) { - add = true; - if (!searchAllCertStores) { - return true; + if (cs != null) { + try { + if (certs.addAll((Collection<X509Certificate>) + cs.getCertificates(caSelector))) { + add = true; + if (!searchAllCertStores) { + return true; + } } + } catch (CertStoreException cse) { + if (debug != null) { + debug.println("exception getting certs from CertStore:"); + cse.printStackTrace(); + } + continue; } - } catch (CertStoreException cse) { - if (debug != null) { - debug.println("exception getting certs from CertStore:"); - cse.printStackTrace(); - } - continue; } } return add;
--- a/src/solaris/native/java/net/PlainDatagramSocketImpl.c Thu Feb 27 10:36:18 2014 -0800 +++ b/src/solaris/native/java/net/PlainDatagramSocketImpl.c Tue Mar 11 23:31:58 2014 -0700 @@ -574,6 +574,8 @@ } else if (ret == JVM_IO_ERR) { if (errno == EBADF) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + } else if (errno == ENOMEM) { + JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed"); } else { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed"); } @@ -674,15 +676,18 @@ "Receive timed out"); return -1; } else if (ret == JVM_IO_ERR) { + if (errno == ENOMEM) { + JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed"); #ifdef __linux__ - if (errno == EBADF) { + } else if (errno == EBADF) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); } else { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed"); +#else + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); +#endif } -#else - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); -#endif return -1; } else if (ret == JVM_IO_INTR) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", @@ -910,15 +915,18 @@ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Receive timed out"); } else if (ret == JVM_IO_ERR) { + if (errno == ENOMEM) { + JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed"); #ifdef __linux__ - if (errno == EBADF) { + } else if (errno == EBADF) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); } else { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed"); +#else + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); +#endif } -#else - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); -#endif } else if (ret == JVM_IO_INTR) { JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", "operation interrupted");
--- a/src/solaris/native/java/net/PlainSocketImpl.c Thu Feb 27 10:36:18 2014 -0800 +++ b/src/solaris/native/java/net/PlainSocketImpl.c Tue Mar 11 23:31:58 2014 -0700 @@ -708,7 +708,6 @@ } else { ret = NET_Timeout(fd, timeout); } - if (ret == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Accept timed out"); @@ -716,6 +715,8 @@ } else if (ret == JVM_IO_ERR) { if (errno == EBADF) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + } else if (errno == ENOMEM) { + JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed"); } else { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed"); }
--- a/src/solaris/native/java/net/SocketInputStream.c Thu Feb 27 10:36:18 2014 -0800 +++ b/src/solaris/native/java/net/SocketInputStream.c Tue Mar 11 23:31:58 2014 -0700 @@ -108,6 +108,8 @@ } else if (nread == JVM_IO_ERR) { if (errno == EBADF) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + } else if (errno == ENOMEM) { + JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed"); } else { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "select/poll failed");
--- a/src/solaris/native/java/net/bsd_close.c Thu Feb 27 10:36:18 2014 -0800 +++ b/src/solaris/native/java/net/bsd_close.c Tue Mar 11 23:31:58 2014 -0700 @@ -25,6 +25,7 @@ #include <stdio.h> #include <stdlib.h> +#include <sys/param.h> #include <signal.h> #include <pthread.h> #include <sys/types.h> @@ -35,7 +36,6 @@ #include <sys/uio.h> #include <unistd.h> #include <errno.h> - #include <sys/poll.h> /* @@ -347,6 +347,10 @@ int NET_Timeout(int s, long timeout) { long prevtime = 0, newtime; struct timeval t, *tp = &t; + fd_set fds; + fd_set* fdsp = NULL; + int allocated = 0; + threadEntry_t self; fdEntry_t *fdEntry = getFdEntry(s); /* @@ -376,20 +380,29 @@ t.tv_usec = 0; } + if (s < FD_SETSIZE) { + fdsp = &fds; + FD_ZERO(fdsp); + } else { + int length = (howmany(s+1, NFDBITS)) * sizeof(int); + fdsp = (fd_set *) calloc(1, length); + if (fdsp == NULL) { + return -1; // errno will be set to ENOMEM + } + allocated = 1; + } + FD_SET(s, fdsp); + for(;;) { - fd_set rfds; int rv; - threadEntry_t self; /* * call select on the fd. If interrupted by our wakeup signal * errno will be set to EBADF. */ - FD_ZERO(&rfds); - FD_SET(s, &rfds); startOp(fdEntry, &self); - rv = select(s+1, &rfds, 0, 0, tp); + rv = select(s+1, fdsp, 0, 0, tp); endOp(fdEntry, &self); /* @@ -403,6 +416,8 @@ newtime = now.tv_sec * 1000 + now.tv_usec / 1000; timeout -= newtime - prevtime; if (timeout <= 0) { + if (allocated != 0) + free(fdsp); return 0; } prevtime = newtime; @@ -410,6 +425,8 @@ t.tv_usec = (timeout % 1000) * 1000; } } else { + if (allocated != 0) + free(fdsp); return rv; }
--- a/src/solaris/native/java/net/linux_close.c Thu Feb 27 10:36:18 2014 -0800 +++ b/src/solaris/native/java/net/linux_close.c Tue Mar 11 23:31:58 2014 -0700 @@ -34,7 +34,6 @@ #include <sys/uio.h> #include <unistd.h> #include <errno.h> - #include <sys/poll.h> /*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java Tue Mar 11 23:31:58 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. + */ + +import test.java.awt.regtesthelpers.Util; + +import javax.swing.*; +import java.awt.*; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @test + * @bug 8012026 + * @summary Component.getMousePosition() does not work in an applet on MacOS + * @author Petr Pchelko + * @library ../../regtesthelpers + * @build Util + * @compile GetMousePositionWithOverlay.java + * @run main/othervm GetMousePositionWithOverlay + */ + +public class GetMousePositionWithOverlay { + + static Frame backFrame; + static Frame frontFrame; + + public static void main(String[] args) throws Throwable { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + constructTestUI(); + } + }); + Util.waitForIdle(null); + + Robot r = new Robot(); + Util.pointOnComp(frontFrame, r); + Util.waitForIdle(null); + + Point pos = getMousePosition(backFrame); + if (pos != null) { + throw new RuntimeException("Test failed. Mouse position should be null but was" + pos); + } + + pos = getMousePosition(frontFrame); + if (pos == null) { + throw new RuntimeException("Test failed. Mouse position should not be null"); + } + + r.mouseMove(189, 189); + Util.waitForIdle(null); + + pos = getMousePosition(backFrame); + if (pos == null) { + throw new RuntimeException("Test failed. Mouse position should not be null"); + } + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + backFrame.dispose(); + frontFrame.dispose(); + } + }); + } + } + + private static Point getMousePosition(final Component component) throws Exception { + final AtomicReference<Point> pos = new AtomicReference<Point>(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + pos.set(component.getMousePosition()); + } + }); + return pos.get(); + } + + private static void constructTestUI() { + backFrame = new Frame(); + backFrame.setBounds(100, 100, 100, 100); + backFrame.setVisible(true); + + frontFrame = new Frame(); + frontFrame.setBounds(120, 120, 60, 60); + frontFrame.setVisible(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java Tue Mar 11 23:31:58 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. + */ + +import test.java.awt.regtesthelpers.Util; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; + +/** + * @test + * @bug 8012026 + * @summary Component.getMousePosition() does not work in an applet on MacOS + * @author Petr Pchelko + * @library ../../regtesthelpers + * @build Util + * @compile GetMousePositionWithPopup.java + * @run main/othervm GetMousePositionWithPopup + */ + +public class GetMousePositionWithPopup { + + private static Frame frame1; + private static Frame frame2; + + public static void main(String[] args) throws Exception { + try { + Robot r = Util.createRobot(); + r.mouseMove(0, 0); + Util.waitForIdle(null); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + constructTestUI(); + } + }); + + Util.waitForIdle(null); + r.mouseMove(149, 149); + Util.waitForIdle(null); + r.mouseMove(150, 150); + Util.waitForIdle(null); + + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame1.dispose(); + frame2.dispose(); + } + }); + } + } + + private static void constructTestUI() { + frame1 = new Frame(); + frame1.setBounds(100, 100, 100, 100); + frame1.addMouseMotionListener(new MouseMotionAdapter() { + + private boolean shown = false; + + @Override + public void mouseMoved(MouseEvent e) { + if (shown) { + return; + } + + shown = true; + + frame2 = new Frame(); + frame2.setBounds(120, 120, 120, 120); + frame2.setVisible(true); + + Point positionInFrame2 = frame2.getMousePosition(); + if (positionInFrame2.x != 30 || positionInFrame2.y != 30) { + throw new RuntimeException("Wrong position reported. Should be [30, 30] but was [" + + positionInFrame2.x + ", " + positionInFrame2.y + "]"); + } + + Point positionInFrame1 = frame1.getMousePosition(); + if (positionInFrame1 != null) { + throw new RuntimeException("Wrong position reported. Should be null"); + } + + } + }); + frame1.setVisible(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java Tue Mar 11 23:31:58 2014 -0700 @@ -0,0 +1,101 @@ +/* + * 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 7122142 + * @summary Test deadlock situation when recursive annotations are parsed + */ + +import java.lang.annotation.Retention; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +public class AnnotationTypeDeadlockTest { + + @Retention(RUNTIME) + @AnnB + public @interface AnnA { + } + + @Retention(RUNTIME) + @AnnA + public @interface AnnB { + } + + static class Task extends Thread { + final CountDownLatch prepareLatch; + final AtomicInteger goLatch; + final Class<?> clazz; + + Task(CountDownLatch prepareLatch, AtomicInteger goLatch, Class<?> clazz) { + super(clazz.getSimpleName()); + setDaemon(true); // in case it deadlocks + this.prepareLatch = prepareLatch; + this.goLatch = goLatch; + this.clazz = clazz; + } + + @Override + public void run() { + prepareLatch.countDown(); // notify we are prepared + while (goLatch.get() > 0); // spin-wait before go + clazz.getDeclaredAnnotations(); + } + } + + public static void main(String[] args) throws Exception { + CountDownLatch prepareLatch = new CountDownLatch(2); + AtomicInteger goLatch = new AtomicInteger(1); + Task taskA = new Task(prepareLatch, goLatch, AnnA.class); + Task taskB = new Task(prepareLatch, goLatch, AnnB.class); + taskA.start(); + taskB.start(); + // wait until both threads start-up + prepareLatch.await(); + // let them go + goLatch.set(0); + // obtain ThreadMXBean + ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); + // wait for threads to finish or dead-lock + while (taskA.isAlive() || taskB.isAlive()) { + // attempt to join threads + taskA.join(500L); + taskB.join(500L); + // detect dead-lock + long[] deadlockedIds = threadBean.findMonitorDeadlockedThreads(); + if (deadlockedIds != null && deadlockedIds.length > 0) { + StringBuilder sb = new StringBuilder("deadlock detected:\n\n"); + for (ThreadInfo ti : threadBean.getThreadInfo(deadlockedIds, Integer.MAX_VALUE)) { + sb.append(ti); + } + throw new IllegalStateException(sb.toString()); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/annotation/AnnotationType/AnnotationTypeRuntimeAssumptionTest.java Tue Mar 11 23:31:58 2014 -0700 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2013, 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 7122142 + * @summary Test consistent parsing of ex-RUNTIME annotations that + * were changed and separately compiled to have CLASS retention + */ + +import sun.misc.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * This test simulates a situation where there are two mutually recursive + * {@link RetentionPolicy#RUNTIME RUNTIME} annotations {@link AnnA_v1 AnnA_v1} + * and {@link AnnB AnnB} and then the first is changed to have + * {@link RetentionPolicy#CLASS CLASS} retention and separately compiled. + * When {@link AnnA_v1 AnnA_v1} annotation is looked-up on {@link AnnB AnnB} + * it still appears to have {@link RetentionPolicy#RUNTIME RUNTIME} retention. + */ +public class AnnotationTypeRuntimeAssumptionTest { + + @Retention(RUNTIME) + @AnnB + public @interface AnnA_v1 { + } + + // An alternative version of AnnA_v1 with CLASS retention instead. + // Used to simulate separate compilation (see AltClassLoader below). + @Retention(CLASS) + @AnnB + public @interface AnnA_v2 { + } + + @Retention(RUNTIME) + @AnnA_v1 + public @interface AnnB { + } + + @AnnA_v1 + public static class TestTask implements Runnable { + @Override + public void run() { + AnnA_v1 ann1 = getDeclaredAnnotation(TestTask.class, AnnA_v1.class); + if (ann1 != null) { + throw new IllegalStateException( + "@" + ann1.annotationType().getSimpleName() + + " found on: " + TestTask.class.getName() + + " should not be visible at runtime"); + } + AnnA_v1 ann2 = getDeclaredAnnotation(AnnB.class, AnnA_v1.class); + if (ann2 != null) { + throw new IllegalStateException( + "@" + ann2.annotationType().getSimpleName() + + " found on: " + AnnB.class.getName() + + " should not be visible at runtime"); + } + } + + private static <A extends Annotation> A getDeclaredAnnotation(Class<?> clazz, Class<A> annotationClass) { + for (Annotation ann : clazz.getDeclaredAnnotations()) { + if (ann.annotationType() == annotationClass) { + return annotationClass.cast(ann); + } + } + return null; + } + } + + public static void main(String[] args) throws Exception { + ClassLoader altLoader = new AltClassLoader( + AnnotationTypeRuntimeAssumptionTest.class.getClassLoader()); + + Runnable altTask = (Runnable) Class.forName( + TestTask.class.getName(), + true, + altLoader).newInstance(); + + altTask.run(); + } + + /** + * 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 AltClassLoader extends ClassLoader { + AltClassLoader(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); + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/net/ServerSocket/AnotherSelectFdsLimit.java Tue Mar 11 23:31:58 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 + * @bug 8035897 + * @summary FD_SETSIZE should be set on macosx + * @run main/othervm AnotherSelectFdsLimit 1023 + * @run main/othervm AnotherSelectFdsLimit 1024 + * @run main/othervm AnotherSelectFdsLimit 1025 + * @run main/othervm AnotherSelectFdsLimit 1600 + */ + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.List; + +public class AnotherSelectFdsLimit { + static final int DEFAULT_FDS_TO_USE = 1600; + + public static void main(String [] args) throws Exception { + if (!System.getProperty("os.name").contains("OS X")) { + System.out.println("Test only run on MAC. Exiting."); + return; + } + + int fdsToUse = DEFAULT_FDS_TO_USE; + if (args.length == 1) + fdsToUse = Integer.parseInt(args[0]); + + System.out.println("Using " + fdsToUse + " fds."); + + List<Thread> threads = new ArrayList<>(); + for (int i=0; i<fdsToUse; i++) + threads.add(new WorkerThread()); + + for (Thread t : threads) + t.start(); + + for (Thread t : threads) + t.join(); + } + + static class WorkerThread extends Thread { + public void run() { + try (ServerSocket ss = new ServerSocket(0)) { + ss.setSoTimeout(2000); + ss.accept(); + } catch (SocketTimeoutException x) { + // expected + } catch (IOException x) { + throw new RuntimeException(x); + } + } + } +}
--- a/test/sun/security/krb5/auto/TcpTimeout.java Thu Feb 27 10:36:18 2014 -0800 +++ b/test/sun/security/krb5/auto/TcpTimeout.java Tue Mar 11 23:31:58 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -24,7 +24,8 @@ /* * @test * @bug 6952519 - * @run main/timeout=40/othervm TcpTimeout + * @compile -XDignore.symbol.file TcpTimeout.java + * @run main/othervm TcpTimeout * @summary kdc_timeout is not being honoured when using TCP */ @@ -36,103 +37,71 @@ public static void main(String[] args) throws Exception { + // Set debug to grab debug output like ">>> KDCCommunication" System.setProperty("sun.security.krb5.debug", "true"); - final int p1 = 10000 + new java.util.Random().nextInt(10000); - final int p2 = 20000 + new java.util.Random().nextInt(10000); - final int p3 = 30000 + new java.util.Random().nextInt(10000); - KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, p3, true); + // Called before new ServerSocket on p1 and p2 to make sure + // customized nameservice is used + KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, 0, true); + int p3 = k.getPort(); k.addPrincipal(OneKDC.USER, OneKDC.PASS); k.addPrincipalRandKey("krbtgt/" + OneKDC.REALM); // Start two listener that does not communicate, simulate timeout - new Thread() { - public void run() { - try { - new ServerSocket(p1).accept(); - } catch (Exception e) { - }} - }.start(); - new Thread() { - public void run() { - try { - new ServerSocket(p2).accept(); - } catch (Exception e) { - }} - }.start(); + ServerSocket ss1 = null; + ServerSocket ss2 = null; + + try { + ss1 = new ServerSocket(0); + ss2 = new ServerSocket(0); + int p1 = ss1.getLocalPort(); + int p2 = ss2.getLocalPort(); + + FileWriter fw = new FileWriter("alternative-krb5.conf"); - FileWriter fw = new FileWriter("alternative-krb5.conf"); + fw.write("[libdefaults]\n" + + "udp_preference_limit = 1\n" + + "max_retries = 2\n" + + "default_realm = " + OneKDC.REALM + "\n" + + "kdc_timeout = 5000\n"); + fw.write("[realms]\n" + OneKDC.REALM + " = {\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p3 + "\n" + + "}\n"); - fw.write("[libdefaults]\n" + - "udp_preference_limit = 1\n" + - "max_retries = 2\n" + - "default_realm = " + OneKDC.REALM + "\n" + - "kdc_timeout = 5000\n"); - fw.write("[realms]\n" + OneKDC.REALM + " = {\n" + - "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" + - "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" + - "kdc = " + OneKDC.KDCHOST + ":" + p3 + "\n" + - "}\n"); + fw.close(); + System.setProperty("java.security.krb5.conf", + "alternative-krb5.conf"); + Config.refresh(); - fw.close(); - System.setProperty("java.security.krb5.conf", "alternative-krb5.conf"); - Config.refresh(); + System.out.println("Ports opened on " + p1 + ", " + p2 + ", " + p3); - // The correct behavior should be: - // 5 sec on p1, 5 sec on p1, fail - // 5 sec on p2, 5 sec on p2, fail - // p3 ok, p3 ok again for preauth. - // The total time should be 20sec + 2x. x is processing time for AS-REQ. - int count = 6; - long start = System.nanoTime(); + // The correct behavior should be: + // 5 sec on p1, 5 sec on p1, fail + // 5 sec on p2, 5 sec on p2, fail + // p3 ok, p3 ok again for preauth. + int count = 6; + + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + PrintStream oldout = System.out; + System.setOut(new PrintStream(bo)); + Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + System.setOut(oldout); - ByteArrayOutputStream bo = new ByteArrayOutputStream(); - PrintStream oldout = System.out; - System.setOut(new PrintStream(bo)); - Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); - System.setOut(oldout); - - String[] lines = new String(bo.toByteArray()).split("\n"); - for (String line: lines) { - if (line.startsWith(">>> KDCCommunication")) { - System.out.println(line); - count--; + String[] lines = new String(bo.toByteArray()).split("\n"); + for (String line: lines) { + if (line.startsWith(">>> KDCCommunication")) { + System.out.println(line); + count--; + } } - } - if (count != 0) { - throw new Exception("Retry count is " + count + " less"); - } - - long end = System.nanoTime(); - if ((end - start)/1000000000L < 20) { - throw new Exception("Too fast? " + (end - start)/1000000000L); + if (count != 0) { + throw new Exception("Retry count is " + count + " less"); + } + } finally { + if (ss1 != null) ss1.close(); + if (ss2 != null) ss2.close(); } } - - private static KDC on(int p) throws Exception { - KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, p, true); - k.addPrincipal(OneKDC.USER, OneKDC.PASS); - k.addPrincipalRandKey("krbtgt/" + OneKDC.REALM); - return k; - } - - private static void addFakeKDCs() - throws Exception { - BufferedReader fr = new BufferedReader(new FileReader(OneKDC.KRB5_CONF)); - FileWriter fw = new FileWriter("alternative-krb5.conf"); - while (true) { - String s = fr.readLine(); - if (s == null) { - break; - } - if (s.trim().startsWith("kdc = ")) { - fw.write(" kdc = localhost:33333\n"); - fw.write(" kdc = localhost:22222\n"); - } - fw.write(s + "\n"); - } - fr.close(); - fw.close(); - sun.security.krb5.Config.refresh(); - } }