diff --git a/.hgtags b/.hgtags index 58e1636aaaf5aed39f1fe6cfd64067633ad5248d..d8826fdc86c219b32ec3dc486b0bf3987db337c8 100644 --- a/.hgtags +++ b/.hgtags @@ -143,3 +143,5 @@ b71d1acfae5240d8c1359443cd02b5ddb587231c jdk8-b17 3778f85773055e81eab6c5ef828935ecca241810 jdk8-b19 39e938cd1b82ec3aab0a9aa66fd8a0457cd0c9c2 jdk8-b20 664fa4fb0ee411ef048903c479f8b962fcdb2f4b jdk8-b21 +dda27c73d8db4a9c7a23872b6f0c5106edcb2021 jdk8-b22 +54202e0148ec7d4570cab5bc9b00d216a7677569 jdk8-b23 diff --git a/make/javax/sound/jsoundalsa/Makefile b/make/javax/sound/jsoundalsa/Makefile index 11b4987dc88fc52b373cc8b4a1d9f5874ab3098c..5fa0124cc6846cae53afbb57cd56a4bbf7794c03 100644 --- a/make/javax/sound/jsoundalsa/Makefile +++ b/make/javax/sound/jsoundalsa/Makefile @@ -65,7 +65,7 @@ FILES_export = \ $(MIDIFILES_export) \ $(PORTFILES_export) -LDFLAGS += -lasound +OTHER_LDLIBS += -lasound CPPFLAGS += \ -DUSE_DAUDIO=TRUE \ diff --git a/make/sun/awt/Makefile b/make/sun/awt/Makefile index 071c36223cf337f4162cf5c9083aa3fedfbe268a..099daf173482fd83f62d365960d56765e24fa1d3 100644 --- a/make/sun/awt/Makefile +++ b/make/sun/awt/Makefile @@ -367,7 +367,8 @@ else FONTCONFIGS_SRC = $(CLOSED_SRC)/solaris/classes/sun/awt/fontconfigs _FONTCONFIGS = \ fontconfig.properties \ - fontconfig.RedHat.5.5.properties \ + fontconfig.RedHat.5.properties \ + fontconfig.RedHat.6.properties \ fontconfig.Turbo.properties \ fontconfig.SuSE.10.properties \ fontconfig.SuSE.11.properties diff --git a/src/share/classes/com/sun/beans/TypeResolver.java b/src/share/classes/com/sun/beans/TypeResolver.java index 8660213a050ee1630b9909c862e1ea208f47d979..baba362c4bccabea5739d5c84e730a62118d3019 100644 --- a/src/share/classes/com/sun/beans/TypeResolver.java +++ b/src/share/classes/com/sun/beans/TypeResolver.java @@ -154,7 +154,7 @@ public final class TypeResolver { * @see #resolve(Type) */ public static Type resolve(Type actual, Type formal) { - return new TypeResolver(actual).resolve(formal); + return getTypeResolver(actual).resolve(formal); } /** @@ -169,7 +169,7 @@ public final class TypeResolver { * @see #resolve(Type[]) */ public static Type[] resolve(Type actual, Type[] formals) { - return new TypeResolver(actual).resolve(formals); + return getTypeResolver(actual).resolve(formals); } /** @@ -228,9 +228,20 @@ public final class TypeResolver { return classes; } + public static TypeResolver getTypeResolver(Type type) { + synchronized (CACHE) { + TypeResolver resolver = CACHE.get(type); + if (resolver == null) { + resolver = new TypeResolver(type); + CACHE.put(type, resolver); + } + return resolver; + } + } + + private static final WeakCache CACHE = new WeakCache<>(); - private final Map, Type> map - = new HashMap, Type>(); + private final Map, Type> map = new HashMap<>(); /** * Constructs the type resolver for the given actual type. diff --git a/src/share/classes/java/awt/AWTKeyStroke.java b/src/share/classes/java/awt/AWTKeyStroke.java index 13f6edd81f0a77a91fe68c5feef3b8540ef0a516..8966d753fb7cb722245d87f9e64d3989195acad1 100644 --- a/src/share/classes/java/awt/AWTKeyStroke.java +++ b/src/share/classes/java/awt/AWTKeyStroke.java @@ -802,8 +802,11 @@ public class AWTKeyStroke implements Serializable { */ protected Object readResolve() throws java.io.ObjectStreamException { synchronized (AWTKeyStroke.class) { - return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease); + if (getClass().equals(getAWTKeyStrokeClass())) { + return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease); + } } + return this; } private static int mapOldModifiers(int modifiers) { diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java index f762d16707ea1c73884ae3122793275ccb43f331..b636f5ade1589f79ffe8551dbf9d0c76dcaf35fd 100644 --- a/src/share/classes/java/lang/Class.java +++ b/src/share/classes/java/lang/Class.java @@ -3118,4 +3118,9 @@ public final AnnotationType getAnnotationType() { return annotationType; } + + /* Backing store of user-defined values pertaining to this class. + * Maintained by the ClassValue class. + */ + transient ClassValue.ClassValueMap classValueMap; } diff --git a/src/share/classes/java/lang/ClassValue.java b/src/share/classes/java/lang/ClassValue.java index 02cf34f59da87b88be48d8f6dc8b1cd1f11c608c..6a824bcc4590e12cb643c7921127cafe74d5db6e 100644 --- a/src/share/classes/java/lang/ClassValue.java +++ b/src/share/classes/java/lang/ClassValue.java @@ -25,9 +25,14 @@ package java.lang; +import java.lang.ClassValue.ClassValueMap; import java.util.WeakHashMap; +import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; +import static java.lang.ClassValue.ClassValueMap.probeHomeLocation; +import static java.lang.ClassValue.ClassValueMap.probeBackupLocations; + /** * Lazily associate a computed value with (potentially) every type. * For example, if a dynamic language needs to construct a message dispatch @@ -92,14 +97,22 @@ public abstract class ClassValue { * @see #computeValue */ public T get(Class type) { - ClassValueMap map = getMap(type); - if (map != null) { - Object x = map.get(this); - if (x != null) { - return (T) map.unmaskNull(x); - } - } - return setComputedValue(type); + // non-racing this.hashCodeForCache : final int + Entry[] cache; + Entry e = probeHomeLocation(cache = getCacheCarefully(type), this); + // racing e : current value <=> stale value from current cache or from stale cache + // invariant: e is null or an Entry with readable Entry.version and Entry.value + if (match(e)) + // invariant: No false positive matches. False negatives are OK if rare. + // The key fact that makes this work: if this.version == e.version, + // then this thread has a right to observe (final) e.value. + return e.value(); + // The fast path can fail for any of these reasons: + // 1. no entry has been computed yet + // 2. hash code collision (before or after reduction mod cache.length) + // 3. an entry has been removed (either on this type or another) + // 4. the GC has somehow managed to delete e.version and clear the reference + return getFromBackup(cache, type); } /** @@ -157,83 +170,582 @@ public abstract class ClassValue { */ public void remove(Class type) { ClassValueMap map = getMap(type); - if (map != null) { - synchronized (map) { - map.remove(this); - } - } + map.removeEntry(this); } + // Possible functionality for JSR 292 MR 1 + /*public*/ void put(Class type, T value) { + ClassValueMap map = getMap(type); + map.changeEntry(this, value); + } + + /// -------- /// Implementation... - // FIXME: Use a data structure here similar that of ThreadLocal (7030453). + /// -------- + + /** Return the cache, if it exists, else a dummy empty cache. */ + private static Entry[] getCacheCarefully(Class type) { + // racing type.classValueMap{.cacheArray} : null => new Entry[X] <=> new Entry[Y] + ClassValueMap map = type.classValueMap; + if (map == null) return EMPTY_CACHE; + Entry[] cache = map.getCache(); + return cache; + // invariant: returned value is safe to dereference and check for an Entry + } + + /** Initial, one-element, empty cache used by all Class instances. Must never be filled. */ + private static final Entry[] EMPTY_CACHE = { null }; + + /** + * Slow tail of ClassValue.get to retry at nearby locations in the cache, + * or take a slow lock and check the hash table. + * Called only if the first probe was empty or a collision. + * This is a separate method, so compilers can process it independently. + */ + private T getFromBackup(Entry[] cache, Class type) { + Entry e = probeBackupLocations(cache, this); + if (e != null) + return e.value(); + return getFromHashMap(type); + } - private static final AtomicInteger STORE_BARRIER = new AtomicInteger(); + // Hack to suppress warnings on the (T) cast, which is a no-op. + @SuppressWarnings("unchecked") + Entry castEntry(Entry e) { return (Entry) e; } - /** Slow path for {@link #get}. */ - private T setComputedValue(Class type) { + /** Called when the fast path of get fails, and cache reprobe also fails. + */ + private T getFromHashMap(Class type) { + // The fail-safe recovery is to fall back to the underlying classValueMap. ClassValueMap map = getMap(type); - if (map == null) { - map = initializeMap(type); - } - T value = computeValue(type); - STORE_BARRIER.lazySet(0); - // All stores pending from computeValue are completed. - synchronized (map) { - // Warm up the table with a null entry. - map.preInitializeEntry(this); - } - STORE_BARRIER.lazySet(0); - // All stores pending from table expansion are completed. - synchronized (map) { - value = (T) map.initializeEntry(this, value); - // One might fear a possible race condition here - // if the code for map.put has flushed the write - // to map.table[*] before the writes to the Map.Entry - // are done. This is not possible, since we have - // warmed up the table with an empty entry. - } - return value; + for (;;) { + Entry e = map.startEntry(this); + if (!e.isPromise()) + return e.value(); + try { + // Try to make a real entry for the promised version. + e = makeEntry(e.version(), computeValue(type)); + } finally { + // Whether computeValue throws or returns normally, + // be sure to remove the empty entry. + e = map.finishEntry(this, e); + } + if (e != null) + return e.value(); + // else try again, in case a racing thread called remove (so e == null) + } + } + + /** Check that e is non-null, matches this ClassValue, and is live. */ + boolean match(Entry e) { + // racing e.version : null (blank) => unique Version token => null (GC-ed version) + // non-racing this.version : v1 => v2 => ... (updates are read faithfully from volatile) + return (e != null && e.get() == this.version); + // invariant: No false positives on version match. Null is OK for false negative. + // invariant: If version matches, then e.value is readable (final set in Entry.) + } + + /** Internal hash code for accessing Class.classValueMap.cacheArray. */ + final int hashCodeForCache = nextHashCode.getAndAdd(HASH_INCREMENT) & HASH_MASK; + + /** Value stream for hashCodeForCache. See similar structure in ThreadLocal. */ + private static final AtomicInteger nextHashCode = new AtomicInteger(); + + /** Good for power-of-two tables. See similar structure in ThreadLocal. */ + private static final int HASH_INCREMENT = 0x61c88647; + + /** Mask a hash code to be positive but not too large, to prevent wraparound. */ + static final int HASH_MASK = (-1 >>> 2); + + /** + * Private key for retrieval of this object from ClassValueMap. + */ + static class Identity { } + /** + * This ClassValue's identity, expressed as an opaque object. + * The main object {@code ClassValue.this} is incorrect since + * subclasses may override {@code ClassValue.equals}, which + * could confuse keys in the ClassValueMap. + */ + final Identity identity = new Identity(); - // Replace this map by a per-class slot. - private static final WeakHashMap, ClassValueMap> ROOT - = new WeakHashMap, ClassValueMap>(); + /** + * Current version for retrieving this class value from the cache. + * Any number of computeValue calls can be cached in association with one version. + * But the version changes when a remove (on any type) is executed. + * A version change invalidates all cache entries for the affected ClassValue, + * by marking them as stale. Stale cache entries do not force another call + * to computeValue, but they do require a synchronized visit to a backing map. + *

+ * All user-visible state changes on the ClassValue take place under + * a lock inside the synchronized methods of ClassValueMap. + * Readers (of ClassValue.get) are notified of such state changes + * when this.version is bumped to a new token. + * This variable must be volatile so that an unsynchronized reader + * will receive the notification without delay. + *

+ * If version were not volatile, one thread T1 could persistently hold onto + * a stale value this.value == V1, while while another thread T2 advances + * (under a lock) to this.value == V2. This will typically be harmless, + * but if T1 and T2 interact causally via some other channel, such that + * T1's further actions are constrained (in the JMM) to happen after + * the V2 event, then T1's observation of V1 will be an error. + *

+ * The practical effect of making this.version be volatile is that it cannot + * be hoisted out of a loop (by an optimizing JIT) or otherwise cached. + * Some machines may also require a barrier instruction to execute + * before this.version. + */ + private volatile Version version = new Version<>(this); + Version version() { return version; } + void bumpVersion() { version = new Version<>(this); } + static class Version { + private final ClassValue classValue; + private final Entry promise = new Entry<>(this); + Version(ClassValue classValue) { this.classValue = classValue; } + ClassValue classValue() { return classValue; } + Entry promise() { return promise; } + boolean isLive() { return classValue.version() == this; } + } + + /** One binding of a value to a class via a ClassValue. + * States are:

    + *
  • promise if value == Entry.this + *
  • else dead if version == null + *
  • else stale if version != classValue.version + *
  • else live
+ * Promises are never put into the cache; they only live in the + * backing map while a computeValue call is in flight. + * Once an entry goes stale, it can be reset at any time + * into the dead state. + */ + static class Entry extends WeakReference> { + final Object value; // usually of type T, but sometimes (Entry)this + Entry(Version version, T value) { + super(version); + this.value = value; // for a regular entry, value is of type T + } + private void assertNotPromise() { assert(!isPromise()); } + /** For creating a promise. */ + Entry(Version version) { + super(version); + this.value = this; // for a promise, value is not of type T, but Entry! + } + /** Fetch the value. This entry must not be a promise. */ + @SuppressWarnings("unchecked") // if !isPromise, type is T + T value() { assertNotPromise(); return (T) value; } + boolean isPromise() { return value == this; } + Version version() { return get(); } + ClassValue classValueOrNull() { + Version v = version(); + return (v == null) ? null : v.classValue(); + } + boolean isLive() { + Version v = version(); + if (v == null) return false; + if (v.isLive()) return true; + clear(); + return false; + } + Entry refreshVersion(Version v2) { + assertNotPromise(); + @SuppressWarnings("unchecked") // if !isPromise, type is T + Entry e2 = new Entry<>(v2, (T) value); + clear(); + // value = null -- caller must drop + return e2; + } + static final Entry DEAD_ENTRY = new Entry<>(null, null); + } + /** Return the backing map associated with this type. */ private static ClassValueMap getMap(Class type) { - type.getClass(); // test for null - return ROOT.get(type); + // racing type.classValueMap : null (blank) => unique ClassValueMap + // if a null is observed, a map is created (lazily, synchronously, uniquely) + // all further access to that map is synchronized + ClassValueMap map = type.classValueMap; + if (map != null) return map; + return initializeMap(type); } + private static final Object CRITICAL_SECTION = new Object(); private static ClassValueMap initializeMap(Class type) { - synchronized (ClassValue.class) { - ClassValueMap map = ROOT.get(type); - if (map == null) - ROOT.put(type, map = new ClassValueMap()); + ClassValueMap map; + synchronized (CRITICAL_SECTION) { // private object to avoid deadlocks + // happens about once per type + if ((map = type.classValueMap) == null) + type.classValueMap = map = new ClassValueMap(type); + } return map; } + + static Entry makeEntry(Version explicitVersion, T value) { + // Note that explicitVersion might be different from this.version. + return new Entry<>(explicitVersion, value); + + // As soon as the Entry is put into the cache, the value will be + // reachable via a data race (as defined by the Java Memory Model). + // This race is benign, assuming the value object itself can be + // read safely by multiple threads. This is up to the user. + // + // The entry and version fields themselves can be safely read via + // a race because they are either final or have controlled states. + // If the pointer from the entry to the version is still null, + // or if the version goes immediately dead and is nulled out, + // the reader will take the slow path and retry under a lock. } - static class ClassValueMap extends WeakHashMap { - /** Make sure this table contains an Entry for the given key, even if it is empty. */ - void preInitializeEntry(ClassValue key) { - if (!this.containsKey(key)) - this.put(key, null); - } - /** Make sure this table contains a non-empty Entry for the given key. */ - Object initializeEntry(ClassValue key, Object value) { - Object prior = this.get(key); - if (prior != null) { - return unmaskNull(prior); + // The following class could also be top level and non-public: + + /** A backing map for all ClassValues, relative a single given type. + * Gives a fully serialized "true state" for each pair (ClassValue cv, Class type). + * Also manages an unserialized fast-path cache. + */ + static class ClassValueMap extends WeakHashMap> { + private final Class type; + private Entry[] cacheArray; + private int cacheLoad, cacheLoadLimit; + + /** Number of entries initially allocated to each type when first used with any ClassValue. + * It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves. + * Must be a power of 2. + */ + private static final int INITIAL_ENTRIES = 32; + + /** Build a backing map for ClassValues, relative the given type. + * Also, create an empty cache array and install it on the class. + */ + ClassValueMap(Class type) { + this.type = type; + sizeCache(INITIAL_ENTRIES); + } + + Entry[] getCache() { return cacheArray; } + + /** Initiate a query. Store a promise (placeholder) if there is no value yet. */ + synchronized + Entry startEntry(ClassValue classValue) { + @SuppressWarnings("unchecked") // one map has entries for all value types + Entry e = (Entry) get(classValue.identity); + Version v = classValue.version(); + if (e == null) { + e = v.promise(); + // The presence of a promise means that a value is pending for v. + // Eventually, finishEntry will overwrite the promise. + put(classValue.identity, e); + // Note that the promise is never entered into the cache! + return e; + } else if (e.isPromise()) { + // Somebody else has asked the same question. + // Let the races begin! + if (e.version() != v) { + e = v.promise(); + put(classValue.identity, e); + } + return e; + } else { + // there is already a completed entry here; report it + if (e.version() != v) { + // There is a stale but valid entry here; make it fresh again. + // Once an entry is in the hash table, we don't care what its version is. + e = e.refreshVersion(v); + put(classValue.identity, e); + } + // Add to the cache, to enable the fast path, next time. + checkCacheLoad(); + addToCache(classValue, e); + return e; + } + } + + /** Finish a query. Overwrite a matching placeholder. Drop stale incoming values. */ + synchronized + Entry finishEntry(ClassValue classValue, Entry e) { + @SuppressWarnings("unchecked") // one map has entries for all value types + Entry e0 = (Entry) get(classValue.identity); + if (e == e0) { + // We can get here during exception processing, unwinding from computeValue. + assert(e.isPromise()); + remove(classValue.identity); + return null; + } else if (e0 != null && e0.isPromise() && e0.version() == e.version()) { + // If e0 matches the intended entry, there has not been a remove call + // between the previous startEntry and now. So now overwrite e0. + Version v = classValue.version(); + if (e.version() != v) + e = e.refreshVersion(v); + put(classValue.identity, e); + // Add to the cache, to enable the fast path, next time. + checkCacheLoad(); + addToCache(classValue, e); + return e; + } else { + // Some sort of mismatch; caller must try again. + return null; + } + } + + /** Remove an entry. */ + synchronized + void removeEntry(ClassValue classValue) { + // make all cache elements for this guy go stale: + if (remove(classValue.identity) != null) { + classValue.bumpVersion(); + removeStaleEntries(classValue); + } + } + + /** Change the value for an entry. */ + synchronized + void changeEntry(ClassValue classValue, T value) { + @SuppressWarnings("unchecked") // one map has entries for all value types + Entry e0 = (Entry) get(classValue.identity); + Version version = classValue.version(); + if (e0 != null) { + if (e0.version() == version && e0.value() == value) + // no value change => no version change needed + return; + classValue.bumpVersion(); + removeStaleEntries(classValue); + } + Entry e = makeEntry(version, value); + put(classValue.identity, e); + // Add to the cache, to enable the fast path, next time. + checkCacheLoad(); + addToCache(classValue, e); + } + + /// -------- + /// Cache management. + /// -------- + + // Statics do not need synchronization. + + /** Load the cache entry at the given (hashed) location. */ + static Entry loadFromCache(Entry[] cache, int i) { + // non-racing cache.length : constant + // racing cache[i & (mask)] : null <=> Entry + return cache[i & (cache.length-1)]; + // invariant: returned value is null or well-constructed (ready to match) + } + + /** Look in the cache, at the home location for the given ClassValue. */ + static Entry probeHomeLocation(Entry[] cache, ClassValue classValue) { + return classValue.castEntry(loadFromCache(cache, classValue.hashCodeForCache)); + } + + /** Given that first probe was a collision, retry at nearby locations. */ + static Entry probeBackupLocations(Entry[] cache, ClassValue classValue) { + if (PROBE_LIMIT <= 0) return null; + // Probe the cache carefully, in a range of slots. + int mask = (cache.length-1); + int home = (classValue.hashCodeForCache & mask); + Entry e2 = cache[home]; // victim, if we find the real guy + if (e2 == null) { + return null; // if nobody is at home, no need to search nearby + } + // assume !classValue.match(e2), but do not assert, because of races + int pos2 = -1; + for (int i = home + 1; i < home + PROBE_LIMIT; i++) { + Entry e = cache[i & mask]; + if (e == null) { + break; // only search within non-null runs + } + if (classValue.match(e)) { + // relocate colliding entry e2 (from cache[home]) to first empty slot + cache[home] = e; + if (pos2 >= 0) { + cache[i & mask] = Entry.DEAD_ENTRY; + } else { + pos2 = i; + } + cache[pos2 & mask] = ((entryDislocation(cache, pos2, e2) < PROBE_LIMIT) + ? e2 // put e2 here if it fits + : Entry.DEAD_ENTRY); + return classValue.castEntry(e); + } + // Remember first empty slot, if any: + if (!e.isLive() && pos2 < 0) pos2 = i; } - this.put(key, maskNull(value)); - return value; + return null; } - Object maskNull(Object x) { - return x == null ? this : x; + /** How far out of place is e? */ + private static int entryDislocation(Entry[] cache, int pos, Entry e) { + ClassValue cv = e.classValueOrNull(); + if (cv == null) return 0; // entry is not live! + int mask = (cache.length-1); + return (pos - cv.hashCodeForCache) & mask; } - Object unmaskNull(Object x) { - return x == this ? null : x; + + /// -------- + /// Below this line all functions are private, and assume synchronized access. + /// -------- + + private void sizeCache(int length) { + assert((length & (length-1)) == 0); // must be power of 2 + cacheLoad = 0; + cacheLoadLimit = (int) ((double) length * CACHE_LOAD_LIMIT / 100); + cacheArray = new Entry[length]; } + + /** Make sure the cache load stays below its limit, if possible. */ + private void checkCacheLoad() { + if (cacheLoad >= cacheLoadLimit) { + reduceCacheLoad(); + } + } + private void reduceCacheLoad() { + removeStaleEntries(); + if (cacheLoad < cacheLoadLimit) + return; // win + Entry[] oldCache = getCache(); + if (oldCache.length > HASH_MASK) + return; // lose + sizeCache(oldCache.length * 2); + for (Entry e : oldCache) { + if (e != null && e.isLive()) { + addToCache(e); + } + } + } + + /** Remove stale entries in the given range. + * Should be executed under a Map lock. + */ + private void removeStaleEntries(Entry[] cache, int begin, int count) { + if (PROBE_LIMIT <= 0) return; + int mask = (cache.length-1); + int removed = 0; + for (int i = begin; i < begin + count; i++) { + Entry e = cache[i & mask]; + if (e == null || e.isLive()) + continue; // skip null and live entries + Entry replacement = null; + if (PROBE_LIMIT > 1) { + // avoid breaking up a non-null run + replacement = findReplacement(cache, i); + } + cache[i & mask] = replacement; + if (replacement == null) removed += 1; + } + cacheLoad = Math.max(0, cacheLoad - removed); + } + + /** Clearing a cache slot risks disconnecting following entries + * from the head of a non-null run, which would allow them + * to be found via reprobes. Find an entry after cache[begin] + * to plug into the hole, or return null if none is needed. + */ + private Entry findReplacement(Entry[] cache, int home1) { + Entry replacement = null; + int haveReplacement = -1, replacementPos = 0; + int mask = (cache.length-1); + for (int i2 = home1 + 1; i2 < home1 + PROBE_LIMIT; i2++) { + Entry e2 = cache[i2 & mask]; + if (e2 == null) break; // End of non-null run. + if (!e2.isLive()) continue; // Doomed anyway. + int dis2 = entryDislocation(cache, i2, e2); + if (dis2 == 0) continue; // e2 already optimally placed + int home2 = i2 - dis2; + if (home2 <= home1) { + // e2 can replace entry at cache[home1] + if (home2 == home1) { + // Put e2 exactly where he belongs. + haveReplacement = 1; + replacementPos = i2; + replacement = e2; + } else if (haveReplacement <= 0) { + haveReplacement = 0; + replacementPos = i2; + replacement = e2; + } + // And keep going, so we can favor larger dislocations. + } + } + if (haveReplacement >= 0) { + if (cache[(replacementPos+1) & mask] != null) { + // Be conservative, to avoid breaking up a non-null run. + cache[replacementPos & mask] = (Entry) Entry.DEAD_ENTRY; + } else { + cache[replacementPos & mask] = null; + cacheLoad -= 1; + } + } + return replacement; + } + + /** Remove stale entries in the range near classValue. */ + private void removeStaleEntries(ClassValue classValue) { + removeStaleEntries(getCache(), classValue.hashCodeForCache, PROBE_LIMIT); + } + + /** Remove all stale entries, everywhere. */ + private void removeStaleEntries() { + Entry[] cache = getCache(); + removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1); + } + + /** Add the given entry to the cache, in its home location, unless it is out of date. */ + private void addToCache(Entry e) { + ClassValue classValue = e.classValueOrNull(); + if (classValue != null) + addToCache(classValue, e); + } + + /** Add the given entry to the cache, in its home location. */ + private void addToCache(ClassValue classValue, Entry e) { + if (PROBE_LIMIT <= 0) return; // do not fill cache + // Add e to the cache. + Entry[] cache = getCache(); + int mask = (cache.length-1); + int home = classValue.hashCodeForCache & mask; + Entry e2 = placeInCache(cache, home, e, false); + if (e2 == null) return; // done + if (PROBE_LIMIT > 1) { + // try to move e2 somewhere else in his probe range + int dis2 = entryDislocation(cache, home, e2); + int home2 = home - dis2; + for (int i2 = home2; i2 < home2 + PROBE_LIMIT; i2++) { + if (placeInCache(cache, i2 & mask, e2, true) == null) { + return; + } + } + } + // Note: At this point, e2 is just dropped from the cache. + } + + /** Store the given entry. Update cacheLoad, and return any live victim. + * 'Gently' means return self rather than dislocating a live victim. + */ + private Entry placeInCache(Entry[] cache, int pos, Entry e, boolean gently) { + Entry e2 = overwrittenEntry(cache[pos]); + if (gently && e2 != null) { + // do not overwrite a live entry + return e; + } else { + cache[pos] = e; + return e2; + } + } + + /** Note an entry that is about to be overwritten. + * If it is not live, quietly replace it by null. + * If it is an actual null, increment cacheLoad, + * because the caller is going to store something + * in its place. + */ + private Entry overwrittenEntry(Entry e2) { + if (e2 == null) cacheLoad += 1; + else if (e2.isLive()) return e2; + return null; + } + + /** Percent loading of cache before resize. */ + private static final int CACHE_LOAD_LIMIT = 67; // 0..100 + /** Maximum number of probes to attempt. */ + private static final int PROBE_LIMIT = 6; // 1.. + // N.B. Set PROBE_LIMIT=0 to disable all fast paths. } } diff --git a/src/share/classes/java/lang/invoke/AdapterMethodHandle.java b/src/share/classes/java/lang/invoke/AdapterMethodHandle.java index 7cfc774062765b22c03075a8e002c715824e233b..82ac57044033106b3daa35a41c3a228caeb791cb 100644 --- a/src/share/classes/java/lang/invoke/AdapterMethodHandle.java +++ b/src/share/classes/java/lang/invoke/AdapterMethodHandle.java @@ -378,6 +378,7 @@ class AdapterMethodHandle extends BoundMethodHandle { } /** Construct an adapter conversion descriptor for a single-argument conversion. */ + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeConv(int convOp, int argnum, int src, int dest) { assert(src == (src & CONV_TYPE_MASK)); assert(dest == (dest & CONV_TYPE_MASK)); @@ -390,6 +391,7 @@ class AdapterMethodHandle extends BoundMethodHandle { insertStackMove(stackMove) ); } + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeDupConv(int convOp, int argnum, int stackMove) { // simple argument motion, requiring one slot to specify assert(convOp == OP_DUP_ARGS || convOp == OP_DROP_ARGS); @@ -401,6 +403,7 @@ class AdapterMethodHandle extends BoundMethodHandle { insertStackMove(stackMove) ); } + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeSwapConv(int convOp, int srcArg, byte srcType, int destSlot, byte destType) { // more complex argument motion, requiring two slots to specify assert(convOp == OP_SWAP_ARGS || convOp == OP_ROT_ARGS); @@ -411,6 +414,7 @@ class AdapterMethodHandle extends BoundMethodHandle { (int) destSlot << CONV_VMINFO_SHIFT ); } + @SuppressWarnings("cast") // some (int) casts below provide clarity but trigger warnings private static long makeSpreadConv(int convOp, int argnum, int src, int dest, int stackMove) { // spreading or collecting, at a particular slot location assert(convOp == OP_SPREAD_ARGS || convOp == OP_COLLECT_ARGS || convOp == OP_FOLD_ARGS); diff --git a/src/share/classes/java/lang/invoke/MemberName.java b/src/share/classes/java/lang/invoke/MemberName.java index bf72c5bce2d10d33e2242a6cd8248bfa4d24653b..5a431a53a8bb0cebb1836dbe7ee744495ae4303d 100644 --- a/src/share/classes/java/lang/invoke/MemberName.java +++ b/src/share/classes/java/lang/invoke/MemberName.java @@ -353,7 +353,7 @@ import static java.lang.invoke.MethodHandleStatics.*; assert(isResolved()); } /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */ - public MemberName(Constructor ctor) { + public MemberName(Constructor ctor) { Object[] typeInfo = { void.class, ctor.getParameterTypes() }; init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers())); // fill in vmtarget, vmindex while we have ctor in hand: diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java index c0beb39fd9f7795e5965d5357aaaf3612f2a6ec7..2c5adb3e9e5b5486aa165d0ed95f36c8cb8ae02d 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -112,7 +112,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; assert(cookedConstructor.type().equals(ctype)); ctype = ctype.dropParameterTypes(0, 1); cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true); - MethodHandle allocator = new AllocateObject(allocateClass); + AllocateObject allocator = new AllocateObject(allocateClass); // allocate() => new C(void) assert(allocator.type().equals(MethodType.methodType(allocateClass))); ctype = ctype.dropParameterTypes(0, 1); @@ -120,19 +120,19 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return fold; } - static final class AllocateObject extends BoundMethodHandle { + static final class AllocateObject /**/ extends BoundMethodHandle { private static final Unsafe unsafe = Unsafe.getUnsafe(); - private final Class allocateClass; + private final Class /**/ allocateClass; // for allocation only: - private AllocateObject(Class allocateClass) { + private AllocateObject(Class /**/ allocateClass) { super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class))); this.allocateClass = allocateClass; } @SuppressWarnings("unchecked") - private C allocate() throws InstantiationException { - return (C) unsafe.allocateInstance(allocateClass); + private Object /*C*/ allocate() throws InstantiationException { + return unsafe.allocateInstance(allocateClass); } static final MethodHandle ALLOCATE; static { @@ -148,8 +148,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MethodHandle accessField(MemberName member, boolean isSetter, Class lookupClass) { // Use sun. misc.Unsafe to dig up the dirt on the field. - MethodHandle mh = new FieldAccessor(member, isSetter); - return mh; + FieldAccessor accessor = new FieldAccessor(member, isSetter); + return accessor; } static @@ -175,7 +175,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return mhs[isSetter ? 1 : 0]; } - static final class FieldAccessor extends BoundMethodHandle { + static final class FieldAccessor /**/ extends BoundMethodHandle { private static final Unsafe unsafe = Unsafe.getUnsafe(); final Object base; // for static refs only final long offset; @@ -190,26 +190,24 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @Override String debugString() { return addTypeString(name, this); } - int getFieldI(C obj) { return unsafe.getInt(obj, offset); } - void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } - long getFieldJ(C obj) { return unsafe.getLong(obj, offset); } - void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); } - float getFieldF(C obj) { return unsafe.getFloat(obj, offset); } - void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); } - double getFieldD(C obj) { return unsafe.getDouble(obj, offset); } - void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); } - boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); } - void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); } - byte getFieldB(C obj) { return unsafe.getByte(obj, offset); } - void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); } - short getFieldS(C obj) { return unsafe.getShort(obj, offset); } - void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); } - char getFieldC(C obj) { return unsafe.getChar(obj, offset); } - void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); } - @SuppressWarnings("unchecked") - V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); } - @SuppressWarnings("unchecked") - void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); } + int getFieldI(Object /*C*/ obj) { return unsafe.getInt(obj, offset); } + void setFieldI(Object /*C*/ obj, int x) { unsafe.putInt(obj, offset, x); } + long getFieldJ(Object /*C*/ obj) { return unsafe.getLong(obj, offset); } + void setFieldJ(Object /*C*/ obj, long x) { unsafe.putLong(obj, offset, x); } + float getFieldF(Object /*C*/ obj) { return unsafe.getFloat(obj, offset); } + void setFieldF(Object /*C*/ obj, float x) { unsafe.putFloat(obj, offset, x); } + double getFieldD(Object /*C*/ obj) { return unsafe.getDouble(obj, offset); } + void setFieldD(Object /*C*/ obj, double x) { unsafe.putDouble(obj, offset, x); } + boolean getFieldZ(Object /*C*/ obj) { return unsafe.getBoolean(obj, offset); } + void setFieldZ(Object /*C*/ obj, boolean x) { unsafe.putBoolean(obj, offset, x); } + byte getFieldB(Object /*C*/ obj) { return unsafe.getByte(obj, offset); } + void setFieldB(Object /*C*/ obj, byte x) { unsafe.putByte(obj, offset, x); } + short getFieldS(Object /*C*/ obj) { return unsafe.getShort(obj, offset); } + void setFieldS(Object /*C*/ obj, short x) { unsafe.putShort(obj, offset, x); } + char getFieldC(Object /*C*/ obj) { return unsafe.getChar(obj, offset); } + void setFieldC(Object /*C*/ obj, char x) { unsafe.putChar(obj, offset, x); } + Object /*V*/ getFieldL(Object /*C*/ obj) { return unsafe.getObject(obj, offset); } + void setFieldL(Object /*C*/ obj, Object /*V*/ x) { unsafe.putObject(obj, offset, x); } // cast (V) is OK here, since we wrap convertArguments around the MH. static Object staticBase(final MemberName field) { @@ -244,8 +242,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; void setStaticS(short x) { unsafe.putShort(base, offset, x); } char getStaticC() { return unsafe.getChar(base, offset); } void setStaticC(char x) { unsafe.putChar(base, offset, x); } - V getStaticL() { return (V) unsafe.getObject(base, offset); } - void setStaticL(V x) { unsafe.putObject(base, offset, x); } + @SuppressWarnings("unchecked") // (V) is for internal clarity but triggers warning + Object /*V*/ getStaticL() { return unsafe.getObject(base, offset); } + void setStaticL(Object /*V*/ x) { unsafe.putObject(base, offset, x); } static String fname(Class vclass, boolean isSetter, boolean isStatic) { String stem; diff --git a/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java index 46be8a9fdc83c800912d1801a1fcd988d697149e..8e068238b1f2b4c03a54d3ba37e35f21dce9f2e2 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -150,7 +150,7 @@ public class MethodHandleProxies { } return intfc.cast(Proxy.newProxyInstance( intfc.getClassLoader(), - new Class[]{ intfc, WrapperInstance.class }, + new Class[]{ intfc, WrapperInstance.class }, new InvocationHandler() { private Object getArg(String name) { if ((Object)name == "getWrapperInstanceTarget") return target; diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java index e49169d0bef1ec6e2cd7d8b7d1ee62699e866d19..58b7e6d507fd2a182bdf603aa568879b28a97793 100644 --- a/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/share/classes/java/lang/invoke/MethodHandles.java @@ -948,10 +948,11 @@ return mh1; public MethodHandle unreflect(Method m) throws IllegalAccessException { MemberName method = new MemberName(m); assert(method.isMethod()); - if (!m.isAccessible()) checkMethod(method.getDeclaringClass(), method, method.isStatic()); + if (m.isAccessible()) + return MethodHandleImpl.findMethod(method, true, /*no lookupClass*/ null); + checkMethod(method.getDeclaringClass(), method, method.isStatic()); MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); - if (!m.isAccessible()) mh = restrictProtectedReceiver(method, mh); - return mh; + return restrictProtectedReceiver(method, mh); } /** @@ -1006,11 +1007,17 @@ return mh1; * is set and {@code asVarargsCollector} fails * @throws NullPointerException if the argument is null */ + @SuppressWarnings("rawtypes") // Will be Constructor after JSR 292 MR public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException { MemberName ctor = new MemberName(c); assert(ctor.isConstructor()); - if (!c.isAccessible()) checkAccess(c.getDeclaringClass(), ctor); - MethodHandle rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull()); + MethodHandle rawCtor; + if (c.isAccessible()) { + rawCtor = MethodHandleImpl.findMethod(ctor, false, /*no lookupClass*/ null); + } else { + checkAccess(c.getDeclaringClass(), ctor); + rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull()); + } MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor); return fixVarargs(allocator, rawCtor); } @@ -1225,7 +1232,7 @@ return mh1; ? "expected a static field" : "expected a non-static field", this); if (trusted) - return MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull()); + return MethodHandleImpl.accessField(field, isSetter, /*no lookupClass*/ null); checkAccess(refc, field); MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull()); return restrictProtectedReceiver(field, mh); diff --git a/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java b/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java index f17b53739ed37c81317c1f4db489a36dcf14bf7a..f74edaf1ce4c17cbfe175e1ba422486f96770dce 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicTreeUI.java @@ -1932,20 +1932,22 @@ public class BasicTreeUI extends TreeUI else { Rectangle beginRect = getPathBounds(tree, getPathForRow (tree, beginRow)); - Rectangle visRect = tree.getVisibleRect(); - Rectangle testRect = beginRect; - int beginY = beginRect.y; - int maxY = beginY + visRect.height; - - for(int counter = beginRow + 1; counter <= endRow; counter++) { - testRect = getPathBounds(tree, - getPathForRow(tree, counter)); - if((testRect.y + testRect.height) > maxY) - counter = endRow; + if (beginRect != null) { + Rectangle visRect = tree.getVisibleRect(); + Rectangle testRect = beginRect; + int beginY = beginRect.y; + int maxY = beginY + visRect.height; + + for(int counter = beginRow + 1; counter <= endRow; counter++) { + testRect = getPathBounds(tree, + getPathForRow(tree, counter)); + if((testRect.y + testRect.height) > maxY) + counter = endRow; + } + tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, + testRect.y + testRect.height- + beginY)); } - tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, - testRect.y + testRect.height- - beginY)); } } } @@ -3485,7 +3487,7 @@ public class BasicTreeUI extends TreeUI } Rectangle bounds = getPathBounds(tree, path); - if (y > (bounds.y + bounds.height)) { + if (bounds == null || y > (bounds.y + bounds.height)) { return false; } diff --git a/src/share/classes/sun/invoke/util/ValueConversions.java b/src/share/classes/sun/invoke/util/ValueConversions.java index cab961a0ff2d85a9d992cae2f3a38615842d0a9e..5fd1e8b15c4d4a8a46d86d3cd7e4c6b54f6fc1c9 100644 --- a/src/share/classes/sun/invoke/util/ValueConversions.java +++ b/src/share/classes/sun/invoke/util/ValueConversions.java @@ -55,9 +55,9 @@ public class ValueConversions { private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); private static EnumMap[] newWrapperCaches(int n) { - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") // generic array creation EnumMap[] caches - = (EnumMap[]) new EnumMap[n]; // unchecked warning expected here + = (EnumMap[]) new EnumMap[n]; for (int i = 0; i < n; i++) caches[i] = new EnumMap<>(Wrapper.class); return caches; @@ -1097,7 +1097,7 @@ public class ValueConversions { } private static MethodHandle buildNewArray(int nargs) { - return MethodHandles.insertArguments(NEW_ARRAY, 0, (int) nargs); + return MethodHandles.insertArguments(NEW_ARRAY, 0, nargs); } private static final MethodHandle[] FILLERS = new MethodHandle[MAX_ARITY+1]; @@ -1122,7 +1122,7 @@ public class ValueConversions { } MethodHandle leftFill = filler(leftLen); // recursive fill MethodHandle rightFill = FILL_ARRAYS[rightLen]; - rightFill = MethodHandles.insertArguments(rightFill, 1, (int) leftLen); // [leftLen..nargs-1] + rightFill = MethodHandles.insertArguments(rightFill, 1, leftLen); // [leftLen..nargs-1] // Combine the two fills: right(left(newArray(nargs), x1..x20), x21..x23) MethodHandle mh = filler(0); // identity function produces result diff --git a/src/share/classes/sun/invoke/util/Wrapper.java b/src/share/classes/sun/invoke/util/Wrapper.java index f1344bd469a5a91badd209e7cdbed992e1da9012..927322bf06fec4cd28080fd4ed90a5423cc85100 100644 --- a/src/share/classes/sun/invoke/util/Wrapper.java +++ b/src/share/classes/sun/invoke/util/Wrapper.java @@ -31,7 +31,7 @@ public enum Wrapper { BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed(8)), SHORT(Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed(16)), CHAR(Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)), - INT(Integer.class, int.class, 'I', (Integer)(int)0, new int[0], Format.signed(32)), + INT(Integer.class, int.class, 'I', (Integer)/*(int)*/0, new int[0], Format.signed(32)), LONG(Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed(64)), FLOAT(Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)), DOUBLE(Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)), @@ -539,7 +539,7 @@ public enum Wrapper { switch (basicTypeChar) { case 'L': throw newIllegalArgumentException("cannot wrap to object type"); case 'V': return null; - case 'I': return Integer.valueOf((int)x); + case 'I': return Integer.valueOf(x); case 'J': return Long.valueOf(x); case 'F': return Float.valueOf(x); case 'D': return Double.valueOf(x); diff --git a/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java b/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java index 41f5398a788cf3972d79f1d87c2aec1a98955751..ebd434a96df289b254b9b1ab7fcbabd9bd86767d 100644 --- a/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java +++ b/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java @@ -76,9 +76,12 @@ class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer { accessor.setFiles(fd, null, null); } else { // Fix 6987233: add the trailing slash if it's absent - accessor.setDirectory(fd, directory + - (directory.endsWith(File.separator) ? - "" : File.separator)); + String with_separator = directory; + if (directory != null) { + with_separator = directory.endsWith(File.separator) ? + directory : (directory + File.separator); + } + accessor.setDirectory(fd, with_separator); accessor.setFile(fd, filenames[0]); accessor.setFiles(fd, directory, filenames); } diff --git a/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java b/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java index b4b8c4c15e039e04d6f34626afedd9dc07826da0..1264d53961104db1825832765e7bcd1837540d7b 100644 --- a/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java +++ b/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java @@ -28,6 +28,9 @@ package sun.java2d.xr; import java.awt.*; import java.awt.geom.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + import sun.font.*; import sun.java2d.*; import sun.java2d.jules.*; @@ -83,7 +86,13 @@ public class XRCompositeManager { con = new XRBackendNative(); // con = XRBackendJava.getInstance(); - String gradProp = System.getProperty("sun.java2d.xrgradcache"); + String gradProp = + AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty("sun.java2d.xrgradcache"); + } + }); + enableGradCache = gradProp == null || !(gradProp.equalsIgnoreCase("false") || gradProp.equalsIgnoreCase("f")); diff --git a/test/java/lang/invoke/CallSiteTest.java b/test/java/lang/invoke/CallSiteTest.java index ee604994cc63e6da894ff37fa94dd7f0e4362234..5e0a875e561ffac185b547f4292173a336c1c3db 100644 --- a/test/java/lang/invoke/CallSiteTest.java +++ b/test/java/lang/invoke/CallSiteTest.java @@ -43,7 +43,7 @@ import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; public class CallSiteTest { - private final static Class CLASS = CallSiteTest.class; + private final static Class CLASS = CallSiteTest.class; private static CallSite mcs; private static CallSite vcs; diff --git a/test/java/lang/invoke/ClassValueTest.java b/test/java/lang/invoke/ClassValueTest.java index 121c260dfa187621c03e621f9af982e562956e5d..56b577159d5eb888ce3a83b191844efc56918e17 100644 --- a/test/java/lang/invoke/ClassValueTest.java +++ b/test/java/lang/invoke/ClassValueTest.java @@ -38,10 +38,6 @@ package test.java.lang.invoke; -import java.util.*; - -import java.lang.invoke.*; - import org.junit.*; import static org.junit.Assert.*; @@ -61,7 +57,7 @@ public class ClassValueTest { } } - static final Class[] CLASSES = { + static final Class[] CLASSES = { String.class, Integer.class, int.class, @@ -73,11 +69,11 @@ public class ClassValueTest { @Test public void testGet() { countForCV1 = 0; - for (Class c : CLASSES) { + for (Class c : CLASSES) { assertEquals(nameForCV1(c), CV1.get(c)); } assertEquals(CLASSES.length, countForCV1); - for (Class c : CLASSES) { + for (Class c : CLASSES) { assertEquals(nameForCV1(c), CV1.get(c)); } assertEquals(CLASSES.length, countForCV1); @@ -85,7 +81,7 @@ public class ClassValueTest { @Test public void testRemove() { - for (Class c : CLASSES) { + for (Class c : CLASSES) { CV1.get(c); } countForCV1 = 0; @@ -94,7 +90,7 @@ public class ClassValueTest { CV1.remove(CLASSES[i]); } assertEquals(0, countForCV1); // no change - for (Class c : CLASSES) { + for (Class c : CLASSES) { assertEquals(nameForCV1(c), CV1.get(c)); } assertEquals(REMCOUNT, countForCV1); @@ -124,7 +120,7 @@ public class ClassValueTest { for (int pass = 0; pass <= 2; pass++) { for (int i1 = 0; i1 < CVN_COUNT1; i1++) { eachClass: - for (Class c : CLASSES) { + for (Class c : CLASSES) { for (int i2 = 0; i2 < CVN_COUNT2; i2++) { int n = i1*CVN_COUNT2 + i2; assertEquals(0, countForCVN); @@ -156,8 +152,10 @@ public class ClassValueTest { } } assertEquals(countForCVN, 0); - for (int n = 0; n < cvns.length; n++) { - for (Class c : CLASSES) { + System.out.println("[rechecking values]"); + for (int i = 0; i < cvns.length * 10; i++) { + int n = i % cvns.length; + for (Class c : CLASSES) { assertEquals(nameForCVN(c, n), cvns[n].get(c)); } } diff --git a/test/java/lang/invoke/InvokeGenericTest.java b/test/java/lang/invoke/InvokeGenericTest.java index 87393b4055f89778fa5d8263ce7c6742d983cecc..b95a5d34f8a08932dbe8efca94290c75f0cebdf0 100644 --- a/test/java/lang/invoke/InvokeGenericTest.java +++ b/test/java/lang/invoke/InvokeGenericTest.java @@ -45,6 +45,7 @@ import static org.junit.Assume.*; * * @author jrose */ +@SuppressWarnings("cast") // various casts help emphasize arguments to invokeExact public class InvokeGenericTest { // How much output? static int verbosity = 0; @@ -129,7 +130,7 @@ public class InvokeGenericTest { } } - static List calledLog = new ArrayList(); + static List calledLog = new ArrayList<>(); static Object logEntry(String name, Object... args) { return Arrays.asList(name, Arrays.asList(args)); } @@ -237,8 +238,7 @@ public class InvokeGenericTest { else try { return param.newInstance(); - } catch (InstantiationException ex) { - } catch (IllegalAccessException ex) { + } catch (InstantiationException | IllegalAccessException ex) { } return null; // random class not Object, String, Integer, etc. } @@ -274,9 +274,11 @@ public class InvokeGenericTest { return zeroArgs(params.toArray(new Class[0])); } + @SafeVarargs @SuppressWarnings("varargs") static T[] array(Class atype, E... a) { return Arrays.copyOf(a, a.length, atype); } + @SafeVarargs @SuppressWarnings("varargs") static T[] cat(T[] a, T... b) { int alen = a.length, blen = b.length; if (blen == 0) return a; @@ -311,7 +313,7 @@ public class InvokeGenericTest { int beg, int end, Class argType) { MethodType targetType = target.type(); end = Math.min(end, targetType.parameterCount()); - ArrayList> argTypes = new ArrayList>(targetType.parameterList()); + ArrayList> argTypes = new ArrayList<>(targetType.parameterList()); Collections.fill(argTypes.subList(beg, end), argType); MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); return target.asType(ttype2); @@ -320,7 +322,7 @@ public class InvokeGenericTest { // This lookup is good for all members in and under InvokeGenericTest. static final Lookup LOOKUP = MethodHandles.lookup(); - Map>, MethodHandle> CALLABLES = new HashMap>, MethodHandle>(); + Map>, MethodHandle> CALLABLES = new HashMap<>(); MethodHandle callable(List> params) { MethodHandle mh = CALLABLES.get(params); if (mh == null) { @@ -353,8 +355,8 @@ public class InvokeGenericTest { countTest(); String[] args = { "one", "two" }; MethodHandle mh = callable(Object.class, String.class); - Object res; List resl; - res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); + Object res; List resl; + res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); } @@ -365,8 +367,8 @@ public class InvokeGenericTest { countTest(); int[] args = { 1, 2 }; MethodHandle mh = callable(Object.class, Object.class); - Object res; List resl; - res = resl = (List) mh.invoke(args[0], args[1]); + Object res; List resl; + res = resl = (List) mh.invoke(args[0], args[1]); //System.out.println(res); assertEquals(Arrays.toString(args), res.toString()); } @@ -377,8 +379,8 @@ public class InvokeGenericTest { countTest(); String[] args = { "one", "two" }; MethodHandle mh = callable(Object.class, String.class); - Object res; List resl; - res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); + Object res; List resl; + res = resl = (List) mh.invoke((String)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); } @@ -440,9 +442,9 @@ public class InvokeGenericTest { * A void return type is possible iff the first type is void.class. */ static List allMethodTypes(int minargc, int maxargc, Class... types) { - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); if (types.length > 0) { - ArrayList argcTypes = new ArrayList(); + ArrayList argcTypes = new ArrayList<>(); // build arity-zero types first for (Class rtype : types) { argcTypes.add(MethodType.methodType(rtype)); @@ -456,7 +458,7 @@ public class InvokeGenericTest { if (argc >= maxargc) break; ArrayList prevTypes = argcTypes; - argcTypes = new ArrayList(); + argcTypes = new ArrayList<>(); for (MethodType prevType : prevTypes) { for (Class ptype : types) { argcTypes.add(prevType.insertParameterTypes(argc, ptype)); @@ -524,8 +526,8 @@ public class InvokeGenericTest { countTest(); Object[] args = { 1, 2 }; MethodHandle mh = callable(Object.class, int.class); - Object res; List resl; int resi; - res = resl = (List) mh.invoke((int)args[0], (Object)args[1]); + Object res; List resl; int resi; + res = resl = (List) mh.invoke((int)args[0], (Object)args[1]); //System.out.println(res); assertEquals(Arrays.asList(args), res); mh = MethodHandles.identity(int.class); diff --git a/test/java/lang/invoke/JavaDocExamplesTest.java b/test/java/lang/invoke/JavaDocExamplesTest.java index 5206df988e94f6a58e608d680b22e8d4507d9f78..9c10f6aa17e4ea60914570f689e0d36d7b62e703 100644 --- a/test/java/lang/invoke/JavaDocExamplesTest.java +++ b/test/java/lang/invoke/JavaDocExamplesTest.java @@ -54,6 +54,7 @@ import static org.junit.Assert.*; /** * @author jrose */ +@SuppressWarnings("LocalVariableHidesMemberVariable") public class JavaDocExamplesTest { /** Wrapper for running the JUnit tests in this module. * Put JUnit on the classpath! @@ -336,6 +337,7 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); }} } + @SuppressWarnings("rawtypes") @Test public void testAsVarargsCollector() throws Throwable { {{ {} /// JAVADOC diff --git a/test/java/lang/invoke/MethodHandlesTest.java b/test/java/lang/invoke/MethodHandlesTest.java index bea81b6ddac2490e863253616ceef8fbaae06187..7f04ee07550c41bdc000af8c49f2ebcb04108f6a 100644 --- a/test/java/lang/invoke/MethodHandlesTest.java +++ b/test/java/lang/invoke/MethodHandlesTest.java @@ -176,7 +176,7 @@ public class MethodHandlesTest { } } - static List calledLog = new ArrayList(); + static List calledLog = new ArrayList<>(); static Object logEntry(String name, Object... args) { return Arrays.asList(name, Arrays.asList(args)); } @@ -211,6 +211,7 @@ public class MethodHandlesTest { return dst.cast(value); } + @SuppressWarnings("cast") // primitive cast to (long) is part of the pattern static Object castToWrapperOrNull(long value, Class dst) { if (dst == int.class || dst == Integer.class) return (int)(value); @@ -284,8 +285,7 @@ public class MethodHandlesTest { else try { return param.newInstance(); - } catch (InstantiationException ex) { - } catch (IllegalAccessException ex) { + } catch (InstantiationException | IllegalAccessException ex) { } return null; // random class not Object, String, Integer, etc. } @@ -302,9 +302,11 @@ public class MethodHandlesTest { return args; } + @SafeVarargs @SuppressWarnings("varargs") static T[] array(Class atype, E... a) { return Arrays.copyOf(a, a.length, atype); } + @SafeVarargs @SuppressWarnings("varargs") static T[] cat(T[] a, T... b) { int alen = a.length, blen = b.length; if (blen == 0) return a; @@ -354,14 +356,14 @@ public class MethodHandlesTest { try { LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString", MethodType.methodType(String.class, List.class)); - } catch (Exception ex) { throw new RuntimeException(ex); } + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } list = MethodHandles.filterReturnValue(list, LIST_TO_STRING); } else if (rtype.isPrimitive()) { if (LIST_TO_INT == null) try { LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt", MethodType.methodType(int.class, List.class)); - } catch (Exception ex) { throw new RuntimeException(ex); } + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } list = MethodHandles.filterReturnValue(list, LIST_TO_INT); list = MethodHandles.explicitCastArguments(list, listType); } else { @@ -370,8 +372,8 @@ public class MethodHandlesTest { return list.asType(listType); } private static MethodHandle LIST_TO_STRING, LIST_TO_INT; - private static String listToString(List x) { return x.toString(); } - private static int listToInt(List x) { return x.toString().hashCode(); } + private static String listToString(List x) { return x.toString(); } + private static int listToInt(List x) { return x.toString().hashCode(); } static MethodHandle changeArgTypes(MethodHandle target, Class argType) { return changeArgTypes(target, 0, 999, argType); @@ -380,7 +382,7 @@ public class MethodHandlesTest { int beg, int end, Class argType) { MethodType targetType = target.type(); end = Math.min(end, targetType.parameterCount()); - ArrayList> argTypes = new ArrayList>(targetType.parameterList()); + ArrayList> argTypes = new ArrayList<>(targetType.parameterList()); Collections.fill(argTypes.subList(beg, end), argType); MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); return target.asType(ttype2); @@ -405,6 +407,7 @@ public class MethodHandlesTest { final String name; public Example() { name = "Example#"+nextArg(); } protected Example(String name) { this.name = name; } + @SuppressWarnings("LeakingThisInConstructor") protected Example(int x) { this(); called("protected ", this, x); } @Override public String toString() { return name; } @@ -441,6 +444,7 @@ public class MethodHandlesTest { static class SubExample extends Example { @Override public void v0() { called("Sub/v0", this); } @Override void pkg_v0() { called("Sub/pkg_v0", this); } + @SuppressWarnings("LeakingThisInConstructor") private SubExample(int x) { called("", this, x); } public SubExample() { super("SubExample#"+nextArg()); } } @@ -912,7 +916,7 @@ public class MethodHandlesTest { static final Object[][] CASES; static { - ArrayList cases = new ArrayList(); + ArrayList cases = new ArrayList<>(); Object types[][] = { {'L',Object.class}, {'R',String.class}, {'I',int.class}, {'J',long.class}, @@ -931,12 +935,12 @@ public class MethodHandlesTest { Field field; try { field = HasFields.class.getDeclaredField(name); - } catch (Exception ex) { + } catch (NoSuchFieldException | SecurityException ex) { throw new InternalError("no field HasFields."+name); } try { value = field.get(fields); - } catch (Exception ex) { + } catch (IllegalArgumentException | IllegalAccessException ex) { throw new InternalError("cannot fetch field HasFields."+name); } if (type == float.class) { @@ -1257,7 +1261,7 @@ public class MethodHandlesTest { List array2list(Object array) { int length = Array.getLength(array); - ArrayList model = new ArrayList(length); + ArrayList model = new ArrayList<>(length); for (int i = 0; i < length; i++) model.add(Array.get(array, i)); return model; @@ -1288,7 +1292,7 @@ public class MethodHandlesTest { String name = pfx+"id"; try { return PRIVATE.findStatic(Callee.class, name, type); - } catch (Exception ex) { + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } } @@ -1365,7 +1369,7 @@ public class MethodHandlesTest { MethodHandle vac = vac0.asVarargsCollector(Object[].class); testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); testConvert(true, vac.asType(MethodType.genericMethodType(0)), null, "vac"); - for (Class at : new Class[] { Object.class, String.class, Integer.class }) { + for (Class at : new Class[] { Object.class, String.class, Integer.class }) { testConvert(true, vac.asType(MethodType.genericMethodType(1)), null, "vac", at); testConvert(true, vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at); } @@ -1514,7 +1518,7 @@ public class MethodHandlesTest { public void testSpreadArguments() throws Throwable { if (CAN_SKIP_WORKING) return; startTest("spreadArguments"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { if (verbosity >= 3) System.out.println("spreadArguments "+argType); for (int nargs = 0; nargs < 50; nargs++) { @@ -1538,7 +1542,7 @@ public class MethodHandlesTest { Object[] args = randomArgs(target2.type().parameterArray()); // make sure the target does what we think it does: if (pos == 0 && nargs < 5 && !argType.isPrimitive()) { - Object[] check = (Object[]) (Object) target.invokeWithArguments(args); + Object[] check = (Object[]) target.invokeWithArguments(args); assertArrayEquals(args, check); switch (nargs) { case 0: @@ -1555,7 +1559,7 @@ public class MethodHandlesTest { break; } } - List> newParams = new ArrayList>(target2.type().parameterList()); + List> newParams = new ArrayList<>(target2.type().parameterList()); { // modify newParams in place List> spreadParams = newParams.subList(pos, nargs); spreadParams.clear(); spreadParams.add(arrayType); @@ -1608,7 +1612,7 @@ public class MethodHandlesTest { public void testCollectArguments() throws Throwable { if (CAN_SKIP_WORKING) return; startTest("collectArguments"); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { if (verbosity >= 3) System.out.println("collectArguments "+argType); for (int nargs = 0; nargs < 50; nargs++) { @@ -1670,12 +1674,13 @@ public class MethodHandlesTest { MethodHandle target = varargsArray(nargs + ins); Object[] args = randomArgs(target.type().parameterArray()); List resList = Arrays.asList(args); - List argsToPass = new ArrayList(resList); + List argsToPass = new ArrayList<>(resList); List argsToInsert = argsToPass.subList(pos, pos + ins); if (verbosity >= 3) System.out.println("insert: "+argsToInsert+" into "+target); + @SuppressWarnings("cast") // cast to spread Object... is helpful MethodHandle target2 = MethodHandles.insertArguments(target, pos, - (Object[]) argsToInsert.toArray()); + (Object[]/*...*/) argsToInsert.toArray()); argsToInsert.clear(); // remove from argsToInsert Object res2 = target2.invokeWithArguments(argsToPass); Object res2List = Arrays.asList((Object[])res2); @@ -1693,7 +1698,7 @@ public class MethodHandlesTest { Class classOfVCList = varargsList(1).invokeWithArguments(0).getClass(); assertTrue(List.class.isAssignableFrom(classOfVCList)); for (int nargs = 0; nargs <= 3; nargs++) { - for (Class rtype : new Class[] { Object.class, + for (Class rtype : new Class[] { Object.class, List.class, int.class, byte.class, @@ -1790,7 +1795,7 @@ public class MethodHandlesTest { System.out.println("fold "+target+" with "+combine); MethodHandle target2 = MethodHandles.foldArguments(target, combine); // Simulate expected effect of combiner on arglist: - List expected = new ArrayList(argsToPass); + List expected = new ArrayList<>(argsToPass); List argsToFold = expected.subList(pos, pos + fold); if (verbosity >= 3) System.out.println("fold: "+argsToFold+" into "+target2); @@ -1822,9 +1827,9 @@ public class MethodHandlesTest { MethodHandle target = varargsArray(nargs); Object[] args = randomArgs(target.type().parameterArray()); MethodHandle target2 = MethodHandles.dropArguments(target, pos, - Collections.nCopies(drop, Object.class).toArray(new Class[0])); + Collections.nCopies(drop, Object.class).toArray(new Class[0])); List resList = Arrays.asList(args); - List argsToDrop = new ArrayList(resList); + List argsToDrop = new ArrayList<>(resList); for (int i = drop; i > 0; i--) { argsToDrop.add(pos, "blort#"+i); } @@ -1840,11 +1845,11 @@ public class MethodHandlesTest { if (CAN_SKIP_WORKING) return; startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker"); // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker - Set done = new HashSet(); + Set done = new HashSet<>(); for (int i = 0; i <= 6; i++) { if (CAN_TEST_LIGHTLY && i > 3) break; MethodType gtype = MethodType.genericMethodType(i); - for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { for (int j = -1; j < i; j++) { MethodType type = gtype; if (j < 0) @@ -1873,7 +1878,7 @@ public class MethodHandlesTest { assertTrue(target.isVarargsCollector()); target = target.asType(type); Object[] args = randomArgs(type.parameterArray()); - List targetPlusArgs = new ArrayList(Arrays.asList(args)); + List targetPlusArgs = new ArrayList<>(Arrays.asList(args)); targetPlusArgs.add(0, target); int code = (Integer) invokee(args); Object log = logEntry("invokee", args); @@ -1960,7 +1965,7 @@ public class MethodHandlesTest { .appendParameterTypes(Object[].class) .insertParameterTypes(0, MethodHandle.class)); assertEquals(expType, inv.type()); - List targetPlusVarArgs = new ArrayList(targetPlusArgs); + List targetPlusVarArgs = new ArrayList<>(targetPlusArgs); List tailList = targetPlusVarArgs.subList(1+k, 1+nargs); Object[] tail = tailList.toArray(); tailList.clear(); tailList.add(tail); @@ -2191,7 +2196,7 @@ public class MethodHandlesTest { if (throwMode == THROW_NOTHING) { assertSame(arg0, returned); } else if (throwMode == THROW_CAUGHT) { - List catchArgs = new ArrayList(Arrays.asList(args)); + List catchArgs = new ArrayList<>(Arrays.asList(args)); // catcher receives an initial subsequence of target arguments: catchArgs.subList(nargs - catchDrops, nargs).clear(); // catcher also receives the exception, prepended: @@ -2317,12 +2322,13 @@ public class MethodHandlesTest { INT_IDENTITY = PRIVATE.findStatic( Surprise.class, "intIdentity", MethodType.methodType(int.class, int.class)); - } catch (Exception ex) { + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } } } + @SuppressWarnings("ConvertToStringSwitch") void testCastFailure(String mode, int okCount) throws Throwable { countTest(false); if (verbosity > 2) System.out.println("mode="+mode); @@ -2418,13 +2424,14 @@ public class MethodHandlesTest { } public interface Fooable { // overloads: - Object foo(Object x, String y); - List foo(String x, int y); - Object foo(String x); + Object foo(Object x, String y); + List foo(String x, int y); + Object foo(String x); } static Object fooForFooable(String x, Object... y) { return called("fooForFooable/"+x, y); } + @SuppressWarnings("serial") // not really a public API, just a test case public static class MyCheckedException extends Exception { } public interface WillThrow { @@ -2453,7 +2460,7 @@ public class MethodHandlesTest { { countTest(); if (verbosity >= 2) System.out.println("Appendable"); - ArrayList appendResults = new ArrayList(); + ArrayList> appendResults = new ArrayList<>(); MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class)); append = append.asType(MethodType.methodType(void.class, List.class)); // specialize the type MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class)); @@ -2475,11 +2482,11 @@ public class MethodHandlesTest { formatter.format(fmt, fmtArgs); String actual = ""; if (verbosity >= 3) System.out.println("appendResults="+appendResults); - for (List l : appendResults) { + for (List l : appendResults) { Object x = l.get(0); switch (l.size()) { case 1: actual += x; continue; - case 3: actual += ((String)x).substring((int)l.get(1), (int)l.get(2)); continue; + case 3: actual += ((String)x).substring((int)(Object)l.get(1), (int)(Object)l.get(2)); continue; } actual += l; } @@ -2551,7 +2558,7 @@ public class MethodHandlesTest { } } // Test error checking on bad interfaces: - for (Class nonSMI : new Class[] { Object.class, + for (Class nonSMI : new Class[] { Object.class, String.class, CharSequence.class, java.io.Serializable.class, @@ -2579,7 +2586,7 @@ public class MethodHandlesTest { } } // Test error checking on interfaces with the wrong method type: - for (Class intfc : new Class[] { Runnable.class /*arity 0*/, + for (Class intfc : new Class[] { Runnable.class /*arity 0*/, Fooable.class /*arity 1 & 2*/ }) { int badArity = 1; // known to be incompatible if (verbosity > 2) System.out.println(intfc.getName()); @@ -2657,7 +2664,7 @@ class ValueConversions { Object a8, Object a9) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } static MethodHandle[] makeArrays() { - ArrayList arrays = new ArrayList(); + ArrayList arrays = new ArrayList<>(); MethodHandles.Lookup lookup = IMPL_LOOKUP; for (;;) { int nargs = arrays.size(); @@ -2746,7 +2753,7 @@ class ValueConversions { Object a8, Object a9) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } static MethodHandle[] makeLists() { - ArrayList lists = new ArrayList(); + ArrayList lists = new ArrayList<>(); MethodHandles.Lookup lookup = IMPL_LOOKUP; for (;;) { int nargs = lists.size(); @@ -2769,7 +2776,7 @@ class ValueConversions { static { try { AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class)); - } catch (Exception ex) { throw new RuntimeException(ex); } + } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); } } /** Return a method handle that takes the indicated number of Object diff --git a/test/java/lang/invoke/MethodTypeTest.java b/test/java/lang/invoke/MethodTypeTest.java index aa540b0c89cc1b878e7520fc6796802c2c822302..d8d460fd1915e3a77c0a2c38934dfbc888df4f53 100644 --- a/test/java/lang/invoke/MethodTypeTest.java +++ b/test/java/lang/invoke/MethodTypeTest.java @@ -29,6 +29,7 @@ package test.java.lang.invoke; +import java.io.IOException; import java.lang.invoke.MethodType; import java.lang.reflect.Method; @@ -378,7 +379,7 @@ public class MethodTypeTest { public void testHashCode() { System.out.println("hashCode"); MethodType instance = mt_viS; - ArrayList> types = new ArrayList>(); + ArrayList> types = new ArrayList<>(); types.add(instance.returnType()); types.addAll(instance.parameterList()); int expResult = types.hashCode(); @@ -556,7 +557,7 @@ public class MethodTypeTest { Object decode; try { decode = readSerial(wire); - } catch (Exception ex) { + } catch (IOException | ClassNotFoundException ex) { decode = ex; // oops! } assertEquals(mt, decode); diff --git a/test/java/lang/invoke/PermuteArgsTest.java b/test/java/lang/invoke/PermuteArgsTest.java index e02137e256043f926f1dcce6dff29ca7ad3a373e..07cbbe59ec9f962937fed759045b96164821c11b 100644 --- a/test/java/lang/invoke/PermuteArgsTest.java +++ b/test/java/lang/invoke/PermuteArgsTest.java @@ -45,7 +45,7 @@ import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; public class PermuteArgsTest { - private static final Class CLASS = PermuteArgsTest.class; + private static final Class CLASS = PermuteArgsTest.class; private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 8); private static final boolean DRY_RUN = Boolean.getBoolean(CLASS.getSimpleName()+".DRY_RUN"); private static final boolean VERBOSE = Boolean.getBoolean(CLASS.getSimpleName()+".VERBOSE") || DRY_RUN; @@ -99,12 +99,12 @@ public class PermuteArgsTest { return Arrays.asList(w, x, y, z); } static Object listI_etc(int... va) { - ArrayList res = new ArrayList(); + ArrayList res = new ArrayList<>(); for (int x : va) res.add(x); return res; } static Object listIJL_etc(int x, long y, Object z, Object... va) { - ArrayList res = new ArrayList(); + ArrayList res = new ArrayList<>(); res.addAll(Arrays.asList(x, y, z)); res.addAll(Arrays.asList(va)); return res; @@ -168,7 +168,7 @@ public class PermuteArgsTest { mh1 = adjustArity(mh, arity); } catch (IllegalArgumentException ex) { System.out.println("*** mh = "+name+" : "+mh+"; arity = "+arity+" => "+ex); - ex.printStackTrace(); + ex.printStackTrace(System.out); break; // cannot get this arity for this type } test("("+arity+")"+name, mh1); @@ -213,7 +213,7 @@ public class PermuteArgsTest { } static void testPermutations(MethodHandle mh) throws Throwable { - HashSet done = new HashSet(); + HashSet done = new HashSet<>(); MethodType mt = mh.type(); int[] perm = nullPerm(mt.parameterCount()); final int MARGIN = (perm.length <= 10 ? 2 : 0); @@ -326,8 +326,8 @@ public class PermuteArgsTest { Class pt = ptypes[i]; Object arg; if (pt == Void.class) arg = null; - else if (pt == int.class) arg = (int) i + 101; - else if (pt == long.class) arg = (long) i + 10_000_000_001L; + else if (pt == int.class) arg = i + 101; + else if (pt == long.class) arg = i + 10_000_000_001L; else arg = "#" + (i + 1); args[i] = arg; } diff --git a/test/java/lang/invoke/RicochetTest.java b/test/java/lang/invoke/RicochetTest.java index bc59ae345c011153f012e64f6640ed2d7cb229eb..d260375ec615bc3c8bab7d11206f63a5afd6b05d 100644 --- a/test/java/lang/invoke/RicochetTest.java +++ b/test/java/lang/invoke/RicochetTest.java @@ -40,7 +40,6 @@ import org.junit.*; import static java.lang.invoke.MethodType.*; import static java.lang.invoke.MethodHandles.*; import static org.junit.Assert.*; -import static org.junit.Assume.*; /** @@ -48,7 +47,7 @@ import static org.junit.Assume.*; * @author jrose */ public class RicochetTest { - private static final Class CLASS = RicochetTest.class; + private static final Class CLASS = RicochetTest.class; private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40); public static void main(String... av) throws Throwable { @@ -148,7 +147,7 @@ public class RicochetTest { for (int nargs = 0; nargs <= MAX; nargs++) { if (nargs > 30 && nargs < MAX-20) nargs += 10; int[] args = new int[nargs]; - for (int j = 0; j < args.length; j++) args[j] = (int)(j + 11); + for (int j = 0; j < args.length; j++) args[j] = j + 11; //System.out.println("testIntSpreads "+Arrays.toString(args)); int[] args1 = (int[]) id.invokeExact(args); assertArrayEquals(args, args1); @@ -388,6 +387,7 @@ public class RicochetTest { java.util.Random random; final MethodHandle[] fns; int depth; + @SuppressWarnings("LeakingThisInConstructor") RFCB(int seed) throws Throwable { this.random = new java.util.Random(seed); this.fns = new MethodHandle[Math.max(29, (1 << MAX_DEPTH-2)/3)]; @@ -408,7 +408,7 @@ public class RicochetTest { case 1: Throwable ex = new RuntimeException(); ex.fillInStackTrace(); - if (VERBOSITY >= 2) ex.printStackTrace(); + if (VERBOSITY >= 2) ex.printStackTrace(System.out); x = "ST; " + x; break; case 2: @@ -467,7 +467,7 @@ public class RicochetTest { return mh.invokeWithArguments(args); } catch (Throwable ex) { System.out.println("threw: "+mh+Arrays.asList(args)); - ex.printStackTrace(); + ex.printStackTrace(System.out); return ex; } } @@ -515,8 +515,8 @@ public class RicochetTest { private static long opJ(long x) { return (long) opI((int)x); } private static Object opL2(Object x, Object y) { return (Object) opI2((int)x, (int)y); } private static Object opL(Object x) { return (Object) opI((int)x); } - private static int opL2_I(Object x, Object y) { return (int) opI2((int)x, (int)y); } - private static int opL_I(Object x) { return (int) opI((int)x); } + private static int opL2_I(Object x, Object y) { return opI2((int)x, (int)y); } + private static int opL_I(Object x) { return opI((int)x); } private static long opL_J(Object x) { return (long) opI((int)x); } private static final MethodHandle opI, opI2, opI3, opI4, opI_L, opJ, opJ2, opJ3, opL2, opL, opL2_I, opL_I, opL_J; static { @@ -570,8 +570,8 @@ public class RicochetTest { INT_LISTERS[i] = lister; LONG_LISTERS[i] = llister; if (i == 0) break; - lister = insertArguments(lister, i-1, (int)0); - llister = insertArguments(llister, i-1, (long)0); + lister = insertArguments(lister, i-1, 0); + llister = insertArguments(llister, i-1, 0L); } } diff --git a/test/java/lang/invoke/ThrowExceptionsTest.java b/test/java/lang/invoke/ThrowExceptionsTest.java index 0065e92d47cee5d98a8dba52b6e6f0baa30da98c..772901542c5fcc3f22c5f57bd2a80da8ec1c5d6d 100644 --- a/test/java/lang/invoke/ThrowExceptionsTest.java +++ b/test/java/lang/invoke/ThrowExceptionsTest.java @@ -40,7 +40,7 @@ import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; public class ThrowExceptionsTest { - private static final Class CLASS = ThrowExceptionsTest.class; + private static final Class CLASS = ThrowExceptionsTest.class; private static final Lookup LOOKUP = lookup(); public static void main(String argv[]) throws Throwable { @@ -132,9 +132,9 @@ public class ThrowExceptionsTest { int tc = testCases; try { m.invoke(this); - } catch (Throwable ex) { + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { System.out.println("*** "+ex); - ex.printStackTrace(); + ex.printStackTrace(System.out); } if (testCases == tc) testCases++; } diff --git a/test/javax/swing/JSplitPane/4885629/bug4885629.java b/test/javax/swing/JSplitPane/4885629/bug4885629.java new file mode 100644 index 0000000000000000000000000000000000000000..e475aecfab3fe36f46893354967c91a2ca997c1b --- /dev/null +++ b/test/javax/swing/JSplitPane/4885629/bug4885629.java @@ -0,0 +1,115 @@ +/* + * 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. + * + * 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 4885629 + * @summary With JSplitPane in VERTICAL_SPLIT, SplitPaneBorder draws bottom edge of divider + * @author Andrey Pikalev + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.plaf.basic.BasicBorders; +import javax.swing.plaf.basic.BasicLookAndFeel; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import java.awt.*; + + +public class bug4885629 { + + private static final Color darkShadow = new Color(100,120,200); + private static final Color darkHighlight = new Color(200,120,50); + private static final Color lightHighlight = darkHighlight.brighter(); + private static final Color BGCOLOR = Color.blue; + + private static JSplitPane sp; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new BasicLookAndFeel() { + public boolean isSupportedLookAndFeel(){ return true; } + public boolean isNativeLookAndFeel(){ return false; } + public String getDescription() { return "Foo"; } + public String getID() { return "FooID"; } + public String getName() { return "FooName"; } + }); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + JFrame frame = new JFrame(); + + JComponent a = new JPanel(); + a.setBackground(Color.white); + a.setMinimumSize(new Dimension(10, 10)); + + JComponent b = new JPanel(); + b.setBackground(Color.white); + b.setMinimumSize(new Dimension(10, 10)); + + sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, a, b); + sp.setPreferredSize(new Dimension(20, 20)); + sp.setBackground(BGCOLOR); + + Border bo = new BasicBorders.SplitPaneBorder(lightHighlight, + Color.red); + Border ibo = new EmptyBorder(0, 0, 0, 0); + sp.setBorder(bo); + sp.setMinimumSize(new Dimension(200, 200)); + + ((BasicSplitPaneUI) sp.getUI()).getDivider().setBorder(ibo); + + frame.getContentPane().setLayout(new FlowLayout()); + frame.getContentPane().setBackground(darkShadow); + frame.getContentPane().add(sp); + + frame.setSize(200, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + }); + + ((SunToolkit) SunToolkit.getDefaultToolkit()).realSync(); + + final Robot robot = new Robot(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Rectangle rect = ((BasicSplitPaneUI) sp.getUI()).getDivider().getBounds(); + + Point p = rect.getLocation(); + + SwingUtilities.convertPointToScreen(p, sp); + + for (int i = 0; i < rect.width; i++) { + if (!BGCOLOR.equals(robot.getPixelColor(p.x + i, p.y + rect.height - 1))) { + throw new Error("The divider's area has incorrect color."); + } + } + } + }); + } +} diff --git a/test/javax/swing/JTextArea/4697612/bug4697612.java b/test/javax/swing/JTextArea/4697612/bug4697612.java new file mode 100644 index 0000000000000000000000000000000000000000..54cd12cb2252e6e678c759fca5e09754f779ed29 --- /dev/null +++ b/test/javax/swing/JTextArea/4697612/bug4697612.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 4697612 6244705 + * @author Peter Zhelezniakov + * @library ../../regtesthelpers + * @build Util + * @run main bug4697612 + */ +import java.io.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import javax.swing.text.BadLocationException; +import sun.awt.SunToolkit; + +public class bug4697612 { + + static final int FRAME_WIDTH = 300; + static final int FRAME_HEIGHT = 300; + static final int FONT_HEIGHT = 16; + private static volatile int frameHeight; + private static volatile int fontHeight; + private static JFrame frame; + private static JTextArea text; + private static JScrollPane scroller; + + public static void main(String[] args) throws Throwable { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(100); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + text.requestFocus(); + } + }); + + toolkit.realSync(); + + // 4697612: pressing PgDn + PgUp should not alter caret position + Util.hitKeys(robot, KeyEvent.VK_HOME); + Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN); + + + int pos0 = getTextCaretPosition(); + int caretHeight = getTextCaretHeight(); + fontHeight = FONT_HEIGHT; + + // iterate two times, for different (even and odd) font height + for (int i = 0; i < 2; i++) { + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + text.setFont(text.getFont().deriveFont(fontHeight)); + } + }); + + frameHeight = FRAME_HEIGHT; + + for (int j = 0; j < caretHeight; j++) { + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + frame.setSize(FRAME_WIDTH, frameHeight); + } + }); + + toolkit.realSync(); + + Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN); + Util.hitKeys(robot, KeyEvent.VK_PAGE_UP); + toolkit.realSync(); + + int pos = getTextCaretPosition(); + if (pos0 != pos) { + throw new RuntimeException("Failed 4697612: PgDn & PgUp keys scroll by different amounts"); + } + frameHeight++; + } + fontHeight++; + } + + + // 6244705: pressing PgDn at the very bottom should not scroll + LookAndFeel laf = UIManager.getLookAndFeel(); + if (laf.getID().equals("Aqua")) { + Util.hitKeys(robot, KeyEvent.VK_END); + } else { + Util.hitKeys(robot, KeyEvent.VK_CONTROL, KeyEvent.VK_END); + } + + toolkit.realSync(); + + pos0 = getScrollerViewPosition(); + Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN); + toolkit.realSync(); + + int pos = getScrollerViewPosition(); + + if (pos0 != pos) { + throw new RuntimeException("Failed 6244705: PgDn at the bottom causes scrolling"); + } + } + + private static int getTextCaretPosition() throws Exception { + final int[] result = new int[1]; + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + result[0] = text.getCaretPosition(); + } + }); + + return result[0]; + } + + private static int getTextCaretHeight() throws Exception { + final int[] result = new int[1]; + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + int pos0 = text.getCaretPosition(); + Rectangle dotBounds = text.modelToView(pos0); + result[0] = dotBounds.height; + } catch (BadLocationException ex) { + throw new RuntimeException(ex); + } + } + }); + + return result[0]; + } + + private static int getScrollerViewPosition() throws Exception { + final int[] result = new int[1]; + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + result[0] = scroller.getViewport().getViewPosition().y; + } + }); + + return result[0]; + } + + private static void createAndShowGUI() { + frame = new JFrame(); + frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + text = new JTextArea(); + try { + InputStream is = + bug4697612.class.getResourceAsStream("bug4697612.txt"); + text.read(new InputStreamReader(is), null); + } catch (IOException e) { + throw new Error(e); + } + + scroller = new JScrollPane(text); + + frame.getContentPane().add(scroller); + + frame.pack(); + frame.setVisible(true); + } +} diff --git a/test/javax/swing/JTextArea/4697612/bug4697612.txt b/test/javax/swing/JTextArea/4697612/bug4697612.txt new file mode 100644 index 0000000000000000000000000000000000000000..55641054e540dd3b84ff6f4d5ec7bc2eb4100b1c --- /dev/null +++ b/test/javax/swing/JTextArea/4697612/bug4697612.txt @@ -0,0 +1,223 @@ + README + + Java(TM) 2 SDK, Standard Edition + Version 1.4.2 Beta + + For a more extensive HTML version of this file, see README.html. + +Contents + + * Introduction + * Release Notes + * Bug Reports and Feedback + * Java 2 SDK Documentation + * Redistribution + * Web Pages + + +Introduction + + Thank you for downloading this release of the Java(TM) 2 SDK, + Standard Edition. The Java 2 SDK is a development environment for + building applications, applets, and components that can be + deployed on the Java platform. + + The Java 2 SDK software includes tools useful for developing and + testing programs written in the Java programming language and + running on the Java platform. These tools are designed to be used + from the command line. Except for appletviewer, these tools do not + provide a graphical user interface. + + +Release Notes + + See the Release Notes on the Java Software web site for additional + information pertaining to this release. + + http://java.sun.com/j2se/1.4.2/relnotes.html + + The on-line release notes will be updated as needed, so you should + check it occasionally for the latest information. + + +Bug Reports and Feedback + + The Bug Parade Web Page on the Java Developer Connection(SM) web + site lets you search for and examine existing bug reports, submit + your own bug reports, and tell us which bug fixes matter most to you. + + http://java.sun.com/jdc/bugParade/ + + To directly submit a bug or request a feature, fill out this form: + + http://java.sun.com/cgi-bin/bugreport.cgi + + You can also send comments directly to Java Software engineering + team email addresses. + + http://java.sun.com/mail/ + + +Java 2 SDK Documentation + + The on-line Java 2 SDK Documentation contains API specifications, + feature descriptions, developer guides, tool reference pages, demos, + and links to related information. It is located at + + http://java.sun.com/j2se/1.4.2/docs/ + + The Java 2 SDK documentation is also available in a download bundle + which you can install locally on your machine. See the + Java 2 SDK download page: + + http://java.sun.com/j2se/1.4.2/download.html + + +Redistribution + + The term "vendors" used here refers to licensees, developers, + and independent software vendors (ISVs) who license and + distribute the Java 2 Runtime Environment with their programs. + Vendors must follow the terms of the Java 2 SDK, Standard + Edition, Binary Code License agreement. + Required vs. Optional Files + + The files that make up the Java 2 SDK, Standard Edition, are + divided into two categories: required and optional. Optional + files may be excluded from redistributions of the Java 2 SDK + at the vendor's discretion. The following section contains a + list of the files and directories that may optionally be + omitted from redistributions of the Java 2 SDK. All files not + in these lists of optional files must be included in + redistributions of the Java 2 SDK. + + Optional Files and Directories + + The following files may be optionally excluded from + redistributions: + + jre/lib/charsets.jar + Character conversion classes + jre/lib/ext/ + sunjce_provider.jar - the SunJCE provider for Java + Cryptography APIs + localedata.jar - contains many of the resources + needed for non US English locales + ldapsec.jar - contains security features supported + by the LDAP service provider + dnsns.jar - for the InetAddress wrapper of JNDI DNS + provider + bin/rmid and jre/bin/rmid + Java RMI Activation System Daemon + bin/rmiregistry and jre/bin/rmiregistry + Java Remote Object Registry + bin/tnameserv and jre/bin/tnameserv + Java IDL Name Server + bin/keytool and jre/bin/keytool + Key and Certificate Management Tool + bin/kinit and jre/bin/kinit + Used to obtain and cache Kerberos ticket-granting tickets + bin/klist and jre/bin/klist + Kerberos display entries in credentials cache and keytab + bin/ktab and jre/bin/ktab + Kerberos key table manager + bin/policytool and jre/bin/policytool + Policy File Creation and Management Tool + bin/orbd and jre/bin/orbd + Object Request Broker Daemon + bin/servertool and jre/bin/servertool + Java IDL Server Tool + src.zip + Archive of source files + + In addition, the Java Web Start product may be excluded from + redistributions. The Java Web Start product is contained in a + file named javaws-1_2-solaris-sparc-i.zip, + javaws-1_2-solaris-i586-i.zip, + javaws-1_2-linux-i586-i.zip, or + javaws-1_2-windows-i586-i.exe, depending on the platform. + + + Unlimited Strength Java Cryptography Extension + + Due to import control restrictions for some countries, the + Java Cryptography Extension (JCE) policy files shipped with + the Java 2 SDK, Standard Edition and the Java 2 Runtime + Environment allow strong but limited cryptography to be + used. These files are located at + + /lib/security/local_policy.jar + /lib/security/US_export_policy.jar + + where is the jre directory of the Java 2 + SDK or the top-level directory of the Java 2 Runtime + Environment. + + An unlimited strength version of these files indicating + no restrictions on cryptographic strengths is available + on the Java 2 SDK web site for those living in eligible + countries. Those living in eligible countries may download + the unlimited strength version and replace the strong + cryptography jar files with the unlimited strength files. + + + Endorsed Standards Override Mechanism + + An endorsed standard is a Java API defined through a standards + process other than the Java Community Process(SM) (JCP(SM)). + Because endorsed standards are defined outside the JCP, it is + anticipated that such standards will be revised between + releases of the Java 2 Platform. In order to take advantage of + new revisions to endorsed standards, developers and software + vendors may use the Endorsed Standards Override Mechanism to + provide newer versions of an endorsed standard than those + included in the Java 2 Platform as released by Sun Microsystems. + + For more information on the Endorsed Standards Override + Mechanism, including the list of platform packages that it may + be used to override, see + + http://java.sun.com/j2se/1.4.2/docs/guide/standards/ + + Classes in the packages listed on that web page may be replaced + only by classes implementing a more recent version of the API + as defined by the appropriate standards body. + + In addition to the packages listed in the document at the above + URL, which are part of the Java 2 Platform, Standard Edition + (J2SE(TM)) specification, redistributors of Sun's J2SE + Reference Implementation are allowed to override classes whose + sole purpose is to implement the functionality provided by + public APIs defined in these Endorsed Standards packages. + Redistributors may also override classes in the org.w3c.dom.* + packages, or other classes whose sole purpose is to implement + these APIs. + + +Sun Java Web Pages + + For additional information, refer to these Sun Microsystems pages + on the World Wide Web: + + http://java.sun.com/ + The Java Software web site, with the latest information on + Java technology, product information, news, and features. + http://java.sun.com/docs + Java Platform Documentation provides access to white papers, + the Java Tutorial and other documents. + http://java.sun.com/jdc + The Java Developer Connection(SM) web site. (Free registration + required.) Additional technical information, news, and + features; user forums; support information, and much more. + http://java.sun.com/products/ + Java Technology Products & API + + +------------------------------------------------------------------------ +The Java 2 SDK, Standard Edition, is a product of Sun Microsystems(TM), +Inc. This product includes code licensed from RSA Security. + +Copyright 2003 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +California 95054, U.S.A. All rights reserved. + + diff --git a/test/javax/swing/JTree/6505523/bug6505523.java b/test/javax/swing/JTree/6505523/bug6505523.java new file mode 100644 index 0000000000000000000000000000000000000000..40357dee6c92b6eb28a9692adb34fd27404241ef --- /dev/null +++ b/test/javax/swing/JTree/6505523/bug6505523.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6505523 + * @summary NullPointerException in BasicTreeUI when a node is removed by expansion listener + * @author Alexandr Scherbatiy + * @run main bug6505523 + */ +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import sun.awt.SunToolkit; + +public class bug6505523 { + + private static JTree tree; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point point = getRowPointToClick(2); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + toolkit.realSync(); + + } + + private static Point getRowPointToClick(final int row) throws Exception { + + final Point[] result = new Point[1]; + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + Rectangle rect = tree.getRowBounds(row); + Point point = new Point(rect.x - 5, rect.y + rect.height / 2); + SwingUtilities.convertPointToScreen(point, tree); + result[0] = point; + } + }); + + return result[0]; + } + + private static void createAndShowGUI() { + final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Problem with NPE under JDK 1.6"); + final DefaultMutableTreeNode problematic = new DefaultMutableTreeNode("Expand me and behold a NPE in stderr"); + problematic.add(new DefaultMutableTreeNode("some content")); + root.add(new DefaultMutableTreeNode("irrelevant...")); + root.add(problematic); + + final DefaultTreeModel model = new DefaultTreeModel(root); + tree = new JTree(model); + tree.setRootVisible(true); + tree.setShowsRootHandles(true); + tree.expandRow(0); + tree.collapseRow(2); + + // this is critical - without dragEnabled everything works + tree.setDragEnabled(true); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + + @Override + public void treeExpanded(TreeExpansionEvent event) { + TreeNode parent = problematic.getParent(); + if (parent instanceof DefaultMutableTreeNode) { + model.removeNodeFromParent(problematic); + } + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + } + }); + + JFrame frame = new JFrame("JTree Problem"); + frame.add(new JScrollPane(tree)); + frame.setSize(500, 300); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } +} \ No newline at end of file diff --git a/test/sun/invoke/util/ValueConversionsTest.java b/test/sun/invoke/util/ValueConversionsTest.java index 6b1253e77b296ce544fe69099c0da56bf92557ac..57205f898053d0860abd93c794c17206e1f33abc 100644 --- a/test/sun/invoke/util/ValueConversionsTest.java +++ b/test/sun/invoke/util/ValueConversionsTest.java @@ -27,11 +27,9 @@ import sun.invoke.util.ValueConversions; import sun.invoke.util.Wrapper; import java.lang.invoke.MethodType; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; -import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.*; @@ -52,7 +50,7 @@ import static org.junit.Assert.*; * @author jrose */ public class ValueConversionsTest { - private static final Class CLASS = ValueConversionsTest.class; + private static final Class CLASS = ValueConversionsTest.class; private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40); private static final int START_ARITY = Integer.getInteger(CLASS.getSimpleName()+".START_ARITY", 0); private static final boolean EXHAUSTIVE = Boolean.getBoolean(CLASS.getSimpleName()+".EXHAUSTIVE"); @@ -165,7 +163,7 @@ public class ValueConversionsTest { Object expResult = box; Object result = null; switch (w) { - case INT: result = boxer.invokeExact((int)n); break; + case INT: result = boxer.invokeExact(/*int*/n); break; case LONG: result = boxer.invokeExact((long)n); break; case FLOAT: result = boxer.invokeExact((float)n); break; case DOUBLE: result = boxer.invokeExact((double)n); break; @@ -361,6 +359,7 @@ public class ValueConversionsTest { assert(stype == MethodType.methodType(arrayType, arrayType)); if (nargs <= 5) { // invoke target as a spreader also: + @SuppressWarnings("cast") Object res2 = spreader.invokeWithArguments((Object)res); String res2String = toArrayString(res2); assertEquals(Arrays.toString(args), res2String);