From 9aa36236bebb5db7fb95293a4c4eec8f6f4611dc Mon Sep 17 00:00:00 2001 From: Alexandre Iline Date: Tue, 6 Sep 2016 17:07:06 -0400 Subject: [PATCH 01/38] 8148859: Fix module dependences for java/time tests Reviewed-by: alanb, rriggs --- jdk/test/java/time/TEST.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/test/java/time/TEST.properties b/jdk/test/java/time/TEST.properties index f480a511913..82224020e8e 100644 --- a/jdk/test/java/time/TEST.properties +++ b/jdk/test/java/time/TEST.properties @@ -1,4 +1,6 @@ # Threeten test uses TestNG TestNG.dirs = . othervm.dirs = tck/java/time/chrono test/java/time/chrono test/java/time/format +modules = jdk.localedata lib.dirs = ../../lib/testlibrary +lib.build = jdk.testlibrary.RandomFactory From 97fa8cd04e629e51aaf66ff26465ad1543d30724 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Tue, 6 Sep 2016 16:08:54 -0700 Subject: [PATCH 02/38] 8159404: throw UnsupportedOperationException unconditionally for mutator methods Reviewed-by: martin, psandoz --- .../java/util/ImmutableCollections.java | 68 +++++++++-- .../share/classes/java/util/List.java | 3 +- .../share/classes/java/util/Map.java | 3 +- .../share/classes/java/util/Set.java | 3 +- jdk/test/java/util/Collection/MOAT.java | 111 +++++++++++++++++- 5 files changed, 173 insertions(+), 15 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java index 8414311e425..494dce83a89 100644 --- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -31,6 +31,10 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; /** * Container class for immutable collections. Not part of the public API. @@ -61,9 +65,25 @@ class ImmutableCollections { */ static final double EXPAND_FACTOR = 2.0; + static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); } + // ---------- List Implementations ---------- - static final class List0 extends AbstractList implements RandomAccess, Serializable { + abstract static class AbstractImmutableList extends AbstractList + implements RandomAccess, Serializable { + @Override public boolean add(E e) { throw uoe(); } + @Override public boolean addAll(Collection c) { throw uoe(); } + @Override public boolean addAll(int index, Collection c) { throw uoe(); } + @Override public void clear() { throw uoe(); } + @Override public boolean remove(Object o) { throw uoe(); } + @Override public boolean removeAll(Collection c) { throw uoe(); } + @Override public boolean removeIf(Predicate filter) { throw uoe(); } + @Override public void replaceAll(UnaryOperator operator) { throw uoe(); } + @Override public boolean retainAll(Collection c) { throw uoe(); } + @Override public void sort(Comparator c) { throw uoe(); } + } + + static final class List0 extends AbstractImmutableList { List0() { } @Override @@ -86,7 +106,7 @@ class ImmutableCollections { } } - static final class List1 extends AbstractList implements RandomAccess, Serializable { + static final class List1 extends AbstractImmutableList { private final E e0; List1(E e0) { @@ -114,7 +134,7 @@ class ImmutableCollections { } } - static final class List2 extends AbstractList implements RandomAccess, Serializable { + static final class List2 extends AbstractImmutableList { private final E e0; private final E e1; @@ -147,7 +167,7 @@ class ImmutableCollections { } } - static final class ListN extends AbstractList implements RandomAccess, Serializable { + static final class ListN extends AbstractImmutableList { private final E[] elements; @SafeVarargs @@ -183,7 +203,17 @@ class ImmutableCollections { // ---------- Set Implementations ---------- - static final class Set0 extends AbstractSet implements Serializable { + abstract static class AbstractImmutableSet extends AbstractSet implements Serializable { + @Override public boolean add(E e) { throw uoe(); } + @Override public boolean addAll(Collection c) { throw uoe(); } + @Override public void clear() { throw uoe(); } + @Override public boolean remove(Object o) { throw uoe(); } + @Override public boolean removeAll(Collection c) { throw uoe(); } + @Override public boolean removeIf(Predicate filter) { throw uoe(); } + @Override public boolean retainAll(Collection c) { throw uoe(); } + } + + static final class Set0 extends AbstractImmutableSet { Set0() { } @Override @@ -210,7 +240,7 @@ class ImmutableCollections { } } - static final class Set1 extends AbstractSet implements Serializable { + static final class Set1 extends AbstractImmutableSet { private final E e0; Set1(E e0) { @@ -241,7 +271,7 @@ class ImmutableCollections { } } - static final class Set2 extends AbstractSet implements Serializable { + static final class Set2 extends AbstractImmutableSet { private final E e0; private final E e1; @@ -312,7 +342,7 @@ class ImmutableCollections { * least one null is always present. * @param the element type */ - static final class SetN extends AbstractSet implements Serializable { + static final class SetN extends AbstractImmutableSet { private final E[] elements; private final int size; @@ -403,7 +433,23 @@ class ImmutableCollections { // ---------- Map Implementations ---------- - static final class Map0 extends AbstractMap implements Serializable { + abstract static class AbstractImmutableMap extends AbstractMap implements Serializable { + @Override public void clear() { throw uoe(); } + @Override public V compute(K key, BiFunction rf) { throw uoe(); } + @Override public V computeIfAbsent(K key, Function mf) { throw uoe(); } + @Override public V computeIfPresent(K key, BiFunction rf) { throw uoe(); } + @Override public V merge(K key, V value, BiFunction rf) { throw uoe(); } + @Override public V put(K key, V value) { throw uoe(); } + @Override public void putAll(Map m) { throw uoe(); } + @Override public V putIfAbsent(K key, V value) { throw uoe(); } + @Override public V remove(Object key) { throw uoe(); } + @Override public boolean remove(Object key, Object value) { throw uoe(); } + @Override public V replace(K key, V value) { throw uoe(); } + @Override public boolean replace(K key, V oldValue, V newValue) { throw uoe(); } + @Override public void replaceAll(BiFunction f) { throw uoe(); } + } + + static final class Map0 extends AbstractImmutableMap { Map0() { } @Override @@ -430,7 +476,7 @@ class ImmutableCollections { } } - static final class Map1 extends AbstractMap implements Serializable { + static final class Map1 extends AbstractImmutableMap { private final K k0; private final V v0; @@ -472,7 +518,7 @@ class ImmutableCollections { * @param the key type * @param the value type */ - static final class MapN extends AbstractMap implements Serializable { + static final class MapN extends AbstractImmutableMap { private final Object[] table; // pairs of key, value private final int size; // number of pairs diff --git a/jdk/src/java.base/share/classes/java/util/List.java b/jdk/src/java.base/share/classes/java/util/List.java index 3819d94e831..8e97c2ea259 100644 --- a/jdk/src/java.base/share/classes/java/util/List.java +++ b/jdk/src/java.base/share/classes/java/util/List.java @@ -94,7 +94,8 @@ import java.util.function.UnaryOperator; * *
    *
  • They are structurally immutable. Elements cannot be added, removed, - * or replaced. Attempts to do so result in {@code UnsupportedOperationException}. + * or replaced. Calling any mutator method will always cause + * {@code UnsupportedOperationException} to be thrown. * However, if the contained elements are themselves mutable, * this may cause the List's contents to appear to change. *
  • They disallow {@code null} elements. Attempts to create them with diff --git a/jdk/src/java.base/share/classes/java/util/Map.java b/jdk/src/java.base/share/classes/java/util/Map.java index 9b71b0552b6..d4ea203edee 100644 --- a/jdk/src/java.base/share/classes/java/util/Map.java +++ b/jdk/src/java.base/share/classes/java/util/Map.java @@ -119,7 +119,8 @@ import java.io.Serializable; * *
      *
    • They are structurally immutable. Keys and values cannot be added, - * removed, or updated. Attempts to do so result in {@code UnsupportedOperationException}. + * removed, or updated. Calling any mutator method will always cause + * {@code UnsupportedOperationException} to be thrown. * However, if the contained keys or values are themselves mutable, this may cause the * Map to behave inconsistently or its contents to appear to change. *
    • They disallow {@code null} keys and values. Attempts to create them with diff --git a/jdk/src/java.base/share/classes/java/util/Set.java b/jdk/src/java.base/share/classes/java/util/Set.java index 15a594a5e28..a1911c13e1b 100644 --- a/jdk/src/java.base/share/classes/java/util/Set.java +++ b/jdk/src/java.base/share/classes/java/util/Set.java @@ -70,7 +70,8 @@ package java.util; * *
        *
      • They are structurally immutable. Elements cannot be added or - * removed. Attempts to do so result in {@code UnsupportedOperationException}. + * removed. Calling any mutator method will always cause + * {@code UnsupportedOperationException} to be thrown. * However, if the contained elements are themselves mutable, this may cause the * Set to behave inconsistently or its contents to appear to change. *
      • They disallow {@code null} elements. Attempts to create them with diff --git a/jdk/test/java/util/Collection/MOAT.java b/jdk/test/java/util/Collection/MOAT.java index fe17c5034a3..f74a1785e26 100644 --- a/jdk/test/java/util/Collection/MOAT.java +++ b/jdk/test/java/util/Collection/MOAT.java @@ -112,7 +112,6 @@ public class MOAT { testCollection(Arrays.asList(1,2,3)); testCollection(nCopies(25,1)); testImmutableList(nCopies(25,1)); - testImmutableList(unmodifiableList(Arrays.asList(1,2,3))); testMap(new HashMap()); testMap(new LinkedHashMap()); @@ -134,6 +133,20 @@ public class MOAT { testMap(Collections.synchronizedSortedMap(new TreeMap())); testMap(Collections.synchronizedNavigableMap(new TreeMap())); + // Unmodifiable wrappers + testImmutableSet(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3)))); + testImmutableList(unmodifiableList(Arrays.asList(1,2,3))); + testImmutableMap(unmodifiableMap(Collections.singletonMap(1,2))); + testCollMutatorsAlwaysThrow(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3)))); + testCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet())); + testEmptyCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet())); + testListMutatorsAlwaysThrow(unmodifiableList(Arrays.asList(1,2,3))); + testListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList())); + testEmptyListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList())); + testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.singletonMap(1,2))); + testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap())); + testEmptyMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap())); + // Empty collections final List emptyArray = Arrays.asList(new Integer[]{}); testCollection(emptyArray); @@ -196,6 +209,8 @@ public class MOAT { // Immutable List testEmptyList(List.of()); + testListMutatorsAlwaysThrow(List.of()); + testEmptyListMutatorsAlwaysThrow(List.of()); for (List list : Arrays.asList( List.of(), List.of(1), @@ -211,10 +226,13 @@ public class MOAT { List.of(integerArray))) { testCollection(list); testImmutableList(list); + testListMutatorsAlwaysThrow(list); } // Immutable Set testEmptySet(Set.of()); + testCollMutatorsAlwaysThrow(Set.of()); + testEmptyCollMutatorsAlwaysThrow(Set.of()); for (Set set : Arrays.asList( Set.of(), Set.of(1), @@ -230,6 +248,7 @@ public class MOAT { Set.of(integerArray))) { testCollection(set); testImmutableSet(set); + testCollMutatorsAlwaysThrow(set); } // Immutable Map @@ -241,6 +260,8 @@ public class MOAT { } testEmptyMap(Map.of()); + testMapMutatorsAlwaysThrow(Map.of()); + testEmptyMapMutatorsAlwaysThrow(Map.of()); for (Map map : Arrays.asList( Map.of(), Map.of(1, 101), @@ -256,6 +277,7 @@ public class MOAT { Map.ofEntries(ea))) { testMap(map); testImmutableMap(map); + testMapMutatorsAlwaysThrow(map); } } @@ -358,6 +380,93 @@ public class MOAT { it.remove(); }); } + /** + * Test that calling a mutator always throws UOE, even if the mutator + * wouldn't actually do anything, given its arguments. + * + * @param c the collection instance to test + */ + private static void testCollMutatorsAlwaysThrow(Collection c) { + THROWS(UnsupportedOperationException.class, + () -> c.addAll(Collections.emptyList()), + () -> c.remove(ABSENT_VALUE), + () -> c.removeAll(Collections.emptyList()), + () -> c.removeIf(x -> false), + () -> c.retainAll(c)); + } + + /** + * Test that calling a mutator always throws UOE, even if the mutator + * wouldn't actually do anything on an empty collection. + * + * @param c the collection instance to test, must be empty + */ + private static void testEmptyCollMutatorsAlwaysThrow(Collection c) { + if (! c.isEmpty()) { + fail("collection is not empty"); + } + THROWS(UnsupportedOperationException.class, + () -> c.clear()); + } + + /** + * As above, for a list. + * + * @param c the list instance to test + */ + private static void testListMutatorsAlwaysThrow(List c) { + testCollMutatorsAlwaysThrow(c); + THROWS(UnsupportedOperationException.class, + () -> c.addAll(0, Collections.emptyList())); + } + + /** + * As above, for an empty list. + * + * @param c the list instance to test, must be empty + */ + private static void testEmptyListMutatorsAlwaysThrow(List c) { + if (! c.isEmpty()) { + fail("list is not empty"); + } + testEmptyCollMutatorsAlwaysThrow(c); + THROWS(UnsupportedOperationException.class, + () -> c.replaceAll(x -> x), + () -> c.sort(null)); + } + + /** + * As above, for a map. + * + * @param m the map instance to test + */ + private static void testMapMutatorsAlwaysThrow(Map m) { + THROWS(UnsupportedOperationException.class, + () -> m.compute(ABSENT_VALUE, (k, v) -> null), + () -> m.computeIfAbsent(ABSENT_VALUE, k -> null), + () -> m.computeIfPresent(ABSENT_VALUE, (k, v) -> null), + () -> m.merge(ABSENT_VALUE, 0, (k, v) -> null), + () -> m.putAll(Collections.emptyMap()), + () -> m.remove(ABSENT_VALUE), + () -> m.remove(ABSENT_VALUE, 0), + () -> m.replace(ABSENT_VALUE, 0), + () -> m.replace(ABSENT_VALUE, 0, 1)); + } + + /** + * As above, for an empty map. + * + * @param map the map instance to test, must be empty + */ + private static void testEmptyMapMutatorsAlwaysThrow(Map m) { + if (! m.isEmpty()) { + fail("map is not empty"); + } + THROWS(UnsupportedOperationException.class, + () -> m.clear(), + () -> m.replaceAll((k, v) -> v)); + } + private static void clear(Collection c) { try { c.clear(); } catch (Throwable t) { unexpected(t); } From b7edd5f9aa22b54d827c0bf1c03f31c3b5399e5b Mon Sep 17 00:00:00 2001 From: Ivan Gerasimov Date: Wed, 7 Sep 2016 10:14:48 +0300 Subject: [PATCH 03/38] 8165413: Typos in javadoc: extra period, wrong number, misspelled word Reviewed-by: weijun, mullan --- .../share/classes/java/security/DigestInputStream.java | 2 +- .../share/classes/java/security/KeyPairGenerator.java | 4 ++-- .../java.base/share/classes/java/security/SignatureSpi.java | 2 +- .../org/objectweb/asm/commons/SerialVersionUIDAdder.java | 2 +- .../share/classes/sun/security/ssl/ClientHandshaker.java | 2 +- .../share/classes/com/sun/media/sound/DLSInfo.java | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/security/DigestInputStream.java b/jdk/src/java.base/share/classes/java/security/DigestInputStream.java index a1bf55ac9e7..747537df253 100644 --- a/jdk/src/java.base/share/classes/java/security/DigestInputStream.java +++ b/jdk/src/java.base/share/classes/java/security/DigestInputStream.java @@ -52,7 +52,7 @@ import java.io.ByteArrayInputStream; * {@link MessageDigest}), * so that in order to compute intermediate digests, a caller should * retain a handle onto the digest object, and clone it for each - * digest to be computed, leaving the orginal digest untouched. + * digest to be computed, leaving the original digest untouched. * * @see MessageDigest * diff --git a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java index 46686b522a1..3a241787329 100644 --- a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java +++ b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java @@ -76,7 +76,7 @@ import sun.security.util.Debug; * {@code g} parameters. If the modulus size is not one of the above * values, the Sun provider creates a new set of parameters. Other * providers might have precomputed parameter sets for more than just the - * three modulus sizes mentioned above. Still others might not have a list of + * modulus sizes mentioned above. Still others might not have a list of * precomputed parameters at all and instead always create new parameter sets. * *
      • Algorithm-Specific Initialization @@ -393,7 +393,7 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * of randomness. * (If none of the installed providers supply an implementation of * {@code SecureRandom}, a system-provided source of randomness is - * used.). + * used.) * *

        This concrete method has been added to this previously-defined * abstract class. diff --git a/jdk/src/java.base/share/classes/java/security/SignatureSpi.java b/jdk/src/java.base/share/classes/java/security/SignatureSpi.java index 7e78726f3b8..9be7701a2fa 100644 --- a/jdk/src/java.base/share/classes/java/security/SignatureSpi.java +++ b/jdk/src/java.base/share/classes/java/security/SignatureSpi.java @@ -38,7 +38,7 @@ import sun.security.jca.JCAUtil; * for the {@code Signature} class, which is used to provide the * functionality of a digital signature algorithm. Digital signatures are used * for authentication and integrity assurance of digital data. - *. + * *

        All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a particular signature algorithm. diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java index 0486710dd47..e70bb1de5d5 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java @@ -80,7 +80,7 @@ import jdk.internal.org.objectweb.asm.Opcodes; * ClassWriter cw = new ClassWriter(...); * ClassVisitor sv = new SerialVersionUIDAdder(cw); * ClassVisitor ca = new MyClassAdapter(sv); - * new ClassReader(orginalClass).accept(ca, false); + * new ClassReader(originalClass).accept(ca, false); * * * The SVUID algorithm can be found Date: Wed, 7 Sep 2016 18:35:21 +0530 Subject: [PATCH 04/38] 8165503: jlink exclude VM plugin's handling of jvmlibs is wrong Reviewed-by: jlaskey --- .../jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java index 549b6abfd54..20e7ef26b1f 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java @@ -103,7 +103,9 @@ public final class ExcludeVMPlugin implements Plugin { List ret = javaBase.entries().filter((t) -> { String path = t.path(); for (String jvmlib : jvmlibs) { - return t.path().endsWith("/" + jvmlib); + if (t.path().endsWith("/" + jvmlib)) { + return true; + } } return false; }).collect(Collectors.toList()); From 44b189f55a49c38f2499ef947780e00c8e02527a Mon Sep 17 00:00:00 2001 From: Sergei Kovalev Date: Wed, 7 Sep 2016 10:04:46 -0700 Subject: [PATCH 05/38] 8165604: Fix module dependencies for sun/util/* tests Reviewed-by: rriggs, naoto --- .../sun/util/locale/provider/Bug8038436.java | 20 ++++++++++++++----- .../sun/util/locale/provider/Bug8152817.java | 1 + .../util/resources/Calendar/Bug4518811.java | 9 +++++---- .../util/resources/Calendar/Bug4527203.java | 3 ++- .../sun/util/resources/Locale/Bug4429024.java | 15 +++++++------- .../sun/util/resources/Locale/Bug4965260.java | 13 ++++++------ .../sun/util/resources/Locale/Bug6275682.java | 11 +++++----- .../util/resources/TimeZone/Bug4938846.java | 11 +++++----- .../util/resources/TimeZone/Bug6271396.java | 11 +++++----- .../util/resources/TimeZone/Bug6317929.java | 11 +++++----- .../util/resources/TimeZone/Bug6377794.java | 11 +++++----- .../util/resources/TimeZone/Bug6442006.java | 11 +++++----- .../sun/util/resources/cldr/Bug8134250.java | 16 ++++++++++----- .../sun/util/resources/cldr/Bug8145136.java | 1 + 14 files changed, 86 insertions(+), 58 deletions(-) diff --git a/jdk/test/sun/util/locale/provider/Bug8038436.java b/jdk/test/sun/util/locale/provider/Bug8038436.java index e112ed51804..96287fca0ef 100644 --- a/jdk/test/sun/util/locale/provider/Bug8038436.java +++ b/jdk/test/sun/util/locale/provider/Bug8038436.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -27,15 +27,25 @@ * @summary Test for changes in 8038436 * @modules java.base/sun.util.locale.provider * java.base/sun.util.spi + * jdk.localedata * @compile -XDignore.symbol.file Bug8038436.java * @run main/othervm --limit-modules java.base Bug8038436 security * @run main/othervm -Djava.locale.providers=COMPAT Bug8038436 availlocs */ -import java.security.*; -import java.util.*; -import java.util.stream.*; -import sun.util.locale.provider.*; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.Formatter; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; +import sun.util.locale.provider.LocaleProviderAdapter; public class Bug8038436 { public static void main(String[] args) { diff --git a/jdk/test/sun/util/locale/provider/Bug8152817.java b/jdk/test/sun/util/locale/provider/Bug8152817.java index bd0c5a0e55a..7bbcc0f2433 100644 --- a/jdk/test/sun/util/locale/provider/Bug8152817.java +++ b/jdk/test/sun/util/locale/provider/Bug8152817.java @@ -28,6 +28,7 @@ * @bug 8152817 * @summary Make sure that resource bundles in the jdk.localedata module are * loaded under a security manager. + * @modules jdk.localedata * @run main/othervm -Djava.locale.providers=COMPAT * -Djava.security.debug=access,failure,codebase=jrt:/jdk.localedata Bug8152817 */ diff --git a/jdk/test/sun/util/resources/Calendar/Bug4518811.java b/jdk/test/sun/util/resources/Calendar/Bug4518811.java index 05d246269c3..3c14d7c1e21 100644 --- a/jdk/test/sun/util/resources/Calendar/Bug4518811.java +++ b/jdk/test/sun/util/resources/Calendar/Bug4518811.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,9 +22,10 @@ */ /* - *@test - *@bug 4518811 - *@summary Verifies the minimum days of the week for euro locales + * @test + * @bug 4518811 + * @modules jdk.localedata + * @summary Verifies the minimum days of the week for euro locales */ // this code is a bit brute-force, but I've been coding in nothing but Shell for the last year, so I'm rusty. diff --git a/jdk/test/sun/util/resources/Calendar/Bug4527203.java b/jdk/test/sun/util/resources/Calendar/Bug4527203.java index f55e252dced..7692bef1120 100644 --- a/jdk/test/sun/util/resources/Calendar/Bug4527203.java +++ b/jdk/test/sun/util/resources/Calendar/Bug4527203.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test 1.1 11/02/01 * @bug 4527203 + * @modules jdk.localedata * @summary In Hungary and Ukraine first day of week is Monday not Sunday */ diff --git a/jdk/test/sun/util/resources/Locale/Bug4429024.java b/jdk/test/sun/util/resources/Locale/Bug4429024.java index 9b06ccba3bc..e01ac99215c 100644 --- a/jdk/test/sun/util/resources/Locale/Bug4429024.java +++ b/jdk/test/sun/util/resources/Locale/Bug4429024.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -20,12 +20,13 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/** - @test - @summary checking localised language/country names in finnish - @bug 4429024 4964035 6558856 8008577 - @run main/othervm -Djava.locale.providers=JRE,SPI Bug4429024 -*/ +/* + * @test + * @summary checking localised language/country names in finnish + * @modules jdk.localedata + * @bug 4429024 4964035 6558856 8008577 + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4429024 + */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/Locale/Bug4965260.java b/jdk/test/sun/util/resources/Locale/Bug4965260.java index 4f46870a17c..1280fe974dd 100644 --- a/jdk/test/sun/util/resources/Locale/Bug4965260.java +++ b/jdk/test/sun/util/resources/Locale/Bug4965260.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -20,11 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/** - *@test - *@bug 4965260 8008577 - *@summary Verifies the language name of "nl" for supported locales - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug4965260 +/* + * @test + * @bug 4965260 8008577 + * @modules jdk.localedata + * @summary Verifies the language name of "nl" for supported locales + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4965260 */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/Locale/Bug6275682.java b/jdk/test/sun/util/resources/Locale/Bug6275682.java index 41d2b3c85d0..cfc89d44660 100644 --- a/jdk/test/sun/util/resources/Locale/Bug6275682.java +++ b/jdk/test/sun/util/resources/Locale/Bug6275682.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,10 +21,11 @@ * questions. */ -/** - @test - @summary Verifying that the language names starts with lowercase in spanish - @bug 6275682 +/* + * @test + * @summary Verifying that the language names starts with lowercase in spanish + * @modules jdk.localedata + * @bug 6275682 */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/TimeZone/Bug4938846.java b/jdk/test/sun/util/resources/TimeZone/Bug4938846.java index cbcaa008e37..4776ac642aa 100644 --- a/jdk/test/sun/util/resources/TimeZone/Bug4938846.java +++ b/jdk/test/sun/util/resources/TimeZone/Bug4938846.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,11 @@ */ /* - *@test - *@bug 4938846 8008577 - *@summary Test case for en_IE TimeZone info - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug4938846 + * @test + * @bug 4938846 8008577 + * @modules jdk.localedata + * @summary Test case for en_IE TimeZone info + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4938846 */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/TimeZone/Bug6271396.java b/jdk/test/sun/util/resources/TimeZone/Bug6271396.java index fd6fb80bddc..0fc42870533 100644 --- a/jdk/test/sun/util/resources/TimeZone/Bug6271396.java +++ b/jdk/test/sun/util/resources/TimeZone/Bug6271396.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,11 @@ */ /* - *@test - *@bug 6271396 8008577 - *@summary Test case for verifying typo of timezone display name Australia/Lord_Howe - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug6271396 + * @test + * @bug 6271396 8008577 + * @modules jdk.localedata + * @summary Test case for verifying typo of timezone display name Australia/Lord_Howe + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug6271396 */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/TimeZone/Bug6317929.java b/jdk/test/sun/util/resources/TimeZone/Bug6317929.java index 55b5ead55a6..101e13805a4 100644 --- a/jdk/test/sun/util/resources/TimeZone/Bug6317929.java +++ b/jdk/test/sun/util/resources/TimeZone/Bug6317929.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,11 @@ */ /* - *@test - *@bug 6317929 6409419 8008577 - *@summary Test case for tzdata2005m support for 9 locales - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug6317929 + * @test + * @bug 6317929 6409419 8008577 + * @modules jdk.localedata + * @summary Test case for tzdata2005m support for 9 locales + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug6317929 */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/TimeZone/Bug6377794.java b/jdk/test/sun/util/resources/TimeZone/Bug6377794.java index 6ca10735c93..47b00aca1d4 100644 --- a/jdk/test/sun/util/resources/TimeZone/Bug6377794.java +++ b/jdk/test/sun/util/resources/TimeZone/Bug6377794.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,11 @@ */ /* - *@test - *@bug 6377794 - *@summary Test case for tzdata2005r support for 9 locales - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug6377794 + * @test + * @bug 6377794 + * @modules jdk.localedata + * @summary Test case for tzdata2005r support for 9 locales + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug6377794 */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/TimeZone/Bug6442006.java b/jdk/test/sun/util/resources/TimeZone/Bug6442006.java index 7202e444112..81cc40e29bc 100644 --- a/jdk/test/sun/util/resources/TimeZone/Bug6442006.java +++ b/jdk/test/sun/util/resources/TimeZone/Bug6442006.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,11 @@ */ /* - *@test - *@bug 6442006 8008577 - *@summary Test case for verifying timezone display name for Asia/Taipei - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug6442006 + * @test + * @bug 6442006 8008577 + * @modules jdk.localedata + * @summary Test case for verifying timezone display name for Asia/Taipei + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug6442006 */ import java.util.Locale; diff --git a/jdk/test/sun/util/resources/cldr/Bug8134250.java b/jdk/test/sun/util/resources/cldr/Bug8134250.java index 95f827b75f5..d38fce53352 100644 --- a/jdk/test/sun/util/resources/cldr/Bug8134250.java +++ b/jdk/test/sun/util/resources/cldr/Bug8134250.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 8134250 8134520 + * @modules jdk.localedata * @summary Tests CLDR/LDML features are correctly reflected in JDK. * @run main/othervm -Djava.locale.providers=CLDR Bug8134250 */ @@ -31,10 +32,15 @@ // Note this test highly depends on a particular version of CLDR. Results // may vary in the future. -import java.time.*; -import java.time.chrono.*; -import java.time.format.*; -import java.util.*; +import java.time.LocalDate; +import java.time.Month; +import java.time.ZoneId; +import java.time.chrono.Chronology; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.FormatStyle; +import java.time.format.TextStyle; +import java.util.Locale; public class Bug8134250 { public static void main(String [] args) { diff --git a/jdk/test/sun/util/resources/cldr/Bug8145136.java b/jdk/test/sun/util/resources/cldr/Bug8145136.java index 8a9f34e6f24..b158c5ac905 100644 --- a/jdk/test/sun/util/resources/cldr/Bug8145136.java +++ b/jdk/test/sun/util/resources/cldr/Bug8145136.java @@ -25,6 +25,7 @@ /* * @test * @bug 8145136 + * @modules jdk.localedata * @summary Tests CLDR 28/29 newly added feature LikelySubtags is correctly reflected in JDK. * @run main/othervm -Djava.locale.providers=CLDR Bug8145136 */ From 45e7a1faa81a8231bca2d807e3e1748f29d2950d Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Wed, 7 Sep 2016 10:58:22 -0700 Subject: [PATCH 06/38] 8151901: test/tools/pack200/Pack200Test fails on verifying native unpacked JAR Reviewed-by: jrose --- .../com/sun/java/util/jar/pack/Package.java | 5 +-- .../sun/java/util/jar/pack/PackageReader.java | 29 +++++++----------- jdk/test/ProblemList.txt | 2 -- jdk/test/tools/pack200/Pack200Test.java | 28 +++++++++-------- .../pack200/pack200-verifier/data/golden.jar | Bin 433984 -> 448228 bytes 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java index 12baf44fe58..1d1a273ef7d 100644 --- a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java +++ b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/Package.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -476,7 +476,8 @@ class Package { } else if (localICs.isEmpty()) { // It was a non-empty diff, but the local ICs were absent. actualICs = null; - changed = 0; // [] => null, no tuple change + // [] => null, no tuple change, but attribute deletion. + changed = -1; } else { // Non-trivial diff was transmitted. actualICs = computeICdiff(); diff --git a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java index 1a60f9e1047..bcb6cb1eb4d 100644 --- a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java +++ b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -1193,18 +1193,21 @@ class PackageReader extends BandStructure { cls.visitRefs(VRM_CLASSIC, cpRefs); ArrayList bsms = new ArrayList<>(); - /* - * BootstrapMethod(BSMs) are added here before InnerClasses(ICs), - * so as to ensure the order. Noting that the BSMs may be - * removed if they are not found in the CP, after the ICs expansion. - */ - cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance()); - // flesh out the local constant pool ConstantPool.completeReferencesIn(cpRefs, true, bsms); + // add the bsm and references as required + if (!bsms.isEmpty()) { + cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance()); + cpRefs.add(Package.getRefString("BootstrapMethods")); + Collections.sort(bsms); + cls.setBootstrapMethods(bsms); + } + // Now that we know all our local class references, // compute the InnerClasses attribute. + // An InnerClasses attribute usually gets added here, + // although it might already have been present. int changed = cls.expandLocalICs(); if (changed != 0) { @@ -1221,16 +1224,6 @@ class PackageReader extends BandStructure { ConstantPool.completeReferencesIn(cpRefs, true, bsms); } - // remove the attr previously set, otherwise add the bsm and - // references as required - if (bsms.isEmpty()) { - cls.attributes.remove(Package.attrBootstrapMethodsEmpty.canonicalInstance()); - } else { - cpRefs.add(Package.getRefString("BootstrapMethods")); - Collections.sort(bsms); - cls.setBootstrapMethods(bsms); - } - // construct a local constant pool int numDoubles = 0; for (Entry e : cpRefs) { diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 38f2392ea0f..83515fad418 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -310,8 +310,6 @@ sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8157338 generic- tools/pack200/CommandLineTests.java 7143279,8059906 generic-all -tools/pack200/Pack200Test.java 8059906,8151901 generic-all - tools/launcher/FXLauncherTest.java 8068049 linux-all,macosx-all tools/pack200/Pack200Props.java 8155857 generic-all diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java index fb6d9b1f83d..5c50da1e503 100644 --- a/jdk/test/tools/pack200/Pack200Test.java +++ b/jdk/test/tools/pack200/Pack200Test.java @@ -21,6 +21,14 @@ * questions. */ + /* + * @test + * @bug 6521334 6712743 8007902 8151901 + * @summary test general packer/unpacker functionality + * using native and java unpackers + * @compile -XDignore.symbol.file Utils.java Pack200Test.java + * @run main/othervm/timeout=1200 -Xmx1280m -Xshare:off Pack200Test + */ import java.util.*; import java.io.*; @@ -28,17 +36,6 @@ import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.util.jar.*; - /* - * @test - * @bug 6521334 6712743 8007902 - * @key intermittent - * @summary check for memory leaks, test general packer/unpacker functionality\ - * using native and java unpackers - * @compile -XDignore.symbol.file Utils.java Pack200Test.java - * @run main/othervm/timeout=1200 -Xmx1280m -Xshare:off Pack200Test - * @author ksrini - */ - /** * Tests the packing/unpacking via the APIs. */ @@ -48,6 +45,9 @@ public class Pack200Test { static final MemoryMXBean mmxbean = ManagementFactory.getMemoryMXBean(); static final long m0 = getUsedMemory(); static final int LEAK_TOLERANCE = 21000; // OS and GC related variations. + // enable leak checks only if required, GC charecteristics vary on + // platforms and this may not yield consistent results + static final boolean LEAK_CHECK = Boolean.getBoolean("Pack200Test.enableLeakCheck"); /** Creates a new instance of Pack200Test */ private Pack200Test() {} @@ -60,9 +60,11 @@ public class Pack200Test { } private static void leakCheck() throws Exception { + if (!LEAK_CHECK) + return; long diff = getUsedMemory() - m0; System.out.println(" Info: memory diff = " + diff + "K"); - if ( diff > LEAK_TOLERANCE) { + if (diff > LEAK_TOLERANCE) { throw new Exception("memory leak detected " + diff); } } @@ -126,7 +128,7 @@ public class Pack200Test { /** * @param args the command line arguments */ - public static void main(String[] args) throws IOException { + public static void main(String[] args) throws Exception { // select the jars carefully, adding more jars will increase the // testing time, especially for jprt. jarList.add(Utils.createRtJar()); diff --git a/jdk/test/tools/pack200/pack200-verifier/data/golden.jar b/jdk/test/tools/pack200/pack200-verifier/data/golden.jar index 511cc0f43ab044021c1ed5ff60b76f4da4472e0f..a80ea6621a6a1cfc79337de68898596e8d3fd20b 100644 GIT binary patch delta 15078 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 J71$D{e*vx`CIbKf From b5f85932d69fa09b8fb57390736600dbf71fe306 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Wed, 7 Sep 2016 14:59:55 -0700 Subject: [PATCH 07/38] 8165636: add removal text to Runtime.traceInstructions/MethodCalls deprecation text Reviewed-by: iris, darcy, mchung --- jdk/src/java.base/share/classes/java/lang/Runtime.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index 43d4ef6aae0..84a599a4285 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -733,6 +733,7 @@ public class Runtime { * @deprecated * This method was intended to control instruction tracing. * It has been superseded by JVM-specific tracing mechanisms. + * This method is subject to removal in a future version of Java SE. * * @param on ignored */ @@ -745,6 +746,7 @@ public class Runtime { * @deprecated * This method was intended to control method call tracing. * It has been superseded by JVM-specific tracing mechanisms. + * This method is subject to removal in a future version of Java SE. * * @param on ignored */ From d689bc25f61e6466363269d4f3d4690e59555b40 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Thu, 8 Sep 2016 20:21:42 +0530 Subject: [PATCH 08/38] 8165697: jlink running on Mac with Windows jmods produces non-runnable image Reviewed-by: jlaskey, redestad --- .../jdk/tools/jlink/builder/DefaultImageBuilder.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java index aaccb4269a0..850147aff31 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java @@ -189,12 +189,12 @@ public final class DefaultImageBuilder implements ImageBuilder { storeFiles(modules, release); if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) { - // launchers in the bin directory need execute permission + // launchers in the bin directory need execute permission. + // On Windows, "bin" also subdirectories containing jvm.dll. if (Files.isDirectory(bin)) { - Files.list(bin) - .filter(f -> !f.toString().endsWith(".diz")) - .filter(f -> Files.isRegularFile(f)) - .forEach(this::setExecutable); + Files.find(bin, 2, (path, attrs) -> { + return attrs.isRegularFile() && !path.toString().endsWith(".diz"); + }).forEach(this::setExecutable); } // jspawnhelper is in lib or lib/ From 6784a0986ebc6df2f4c53be2759e8efd255dddbd Mon Sep 17 00:00:00 2001 From: Sean Coffey Date: Thu, 8 Sep 2016 16:16:44 +0100 Subject: [PATCH 09/38] 8165711: java/net/SetFactoryPermission/SetFactoryPermission.java needs to run in ovm mode Reviewed-by: chegar --- .../java/net/SetFactoryPermission/SetFactoryPermission.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java b/jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java index 64c9af0192e..0b65c506a6f 100644 --- a/jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java +++ b/jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java @@ -27,7 +27,7 @@ * @bug 8048052 * @summary Test a series of methods which requires "setFactory" runtime permission * @modules java.rmi - * @run main SetFactoryPermission success + * @run main/othervm SetFactoryPermission success * @run main/othervm/policy=policy.fail SetFactoryPermission fail * @run main/othervm/policy=policy.success SetFactoryPermission success */ From 37ff205c8a464becd64524c78425b2283a9a173c Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 8 Sep 2016 09:45:50 -0700 Subject: [PATCH 10/38] 8165563: ClassLoader::getSystemClassLoader will never be null Reviewed-by: alanb, dholmes, psandoz --- .../share/classes/java/lang/ClassLoader.java | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index d8b2dee337d..47b9e1c8be5 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1167,17 +1167,7 @@ public abstract class ClassLoader { protected final Class findSystemClass(String name) throws ClassNotFoundException { - ClassLoader system = getSystemClassLoader(); - if (system == null) { - if (!checkName(name)) - throw new ClassNotFoundException(name); - Class cls = findBootstrapClass(name); - if (cls == null) { - throw new ClassNotFoundException(name); - } - return cls; - } - return system.loadClass(name); + return getSystemClassLoader().loadClass(name); } /** @@ -1437,11 +1427,7 @@ public abstract class ClassLoader { * @since 1.1 */ public static URL getSystemResource(String name) { - ClassLoader system = getSystemClassLoader(); - if (system == null) { - return BootLoader.findResource(name); - } - return system.getResource(name); + return getSystemClassLoader().getResource(name); } /** @@ -1464,17 +1450,13 @@ public abstract class ClassLoader { * * @throws IOException * If I/O errors occur - + * * @since 1.2 */ public static Enumeration getSystemResources(String name) throws IOException { - ClassLoader system = getSystemClassLoader(); - if (system == null) { - return BootLoader.findResources(name); - } - return system.getResources(name); + return getSystemClassLoader().getResources(name); } /** @@ -1631,8 +1613,7 @@ public abstract class ClassLoader { * this method during startup should take care not to cache the return * value until the system is fully initialized. * - * @return The system ClassLoader for delegation, or - * null if none + * @return The system ClassLoader for delegation * * @throws SecurityException * If a security manager is present, and the caller's class loader From d0474e029b930de73eca232871c76e004cfffd3e Mon Sep 17 00:00:00 2001 From: Sergei Kovalev Date: Thu, 8 Sep 2016 09:59:54 -0700 Subject: [PATCH 11/38] 8165583: Fix module dependencies for jdk/java/util/* tests Reviewed-by: alanb --- jdk/test/java/util/Calendar/Bug4302966.java | 1 + jdk/test/java/util/Date/Bug8135055.java | 1 + jdk/test/java/util/Formatter/FormatLocale.java | 1 + .../util/ResourceBundle/modules/security/TestPermission.java | 1 + jdk/test/java/util/ServiceLoader/modules/ServicesTest.java | 4 +++- jdk/test/java/util/TimeZone/HongKong.java | 1 + jdk/test/java/util/logging/modules/GetResourceBundleTest.java | 1 + 7 files changed, 9 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/util/Calendar/Bug4302966.java b/jdk/test/java/util/Calendar/Bug4302966.java index 6c3b9c3d60e..0dce8e2b367 100644 --- a/jdk/test/java/util/Calendar/Bug4302966.java +++ b/jdk/test/java/util/Calendar/Bug4302966.java @@ -24,6 +24,7 @@ /* * @test * @bug 4302966 + * @modules jdk.localedata * @summary In Czech Republic first day of week is Monday not Sunday */ diff --git a/jdk/test/java/util/Date/Bug8135055.java b/jdk/test/java/util/Date/Bug8135055.java index b0d1c144caa..55bfd606141 100644 --- a/jdk/test/java/util/Date/Bug8135055.java +++ b/jdk/test/java/util/Date/Bug8135055.java @@ -24,6 +24,7 @@ /* * @test * @bug 8135055 + * @modules java.sql * @summary Test java.sql.TimeStamp instance should come after java.util.Date * if Nanos component of TimeStamp is not equal to 0 milliseconds. */ diff --git a/jdk/test/java/util/Formatter/FormatLocale.java b/jdk/test/java/util/Formatter/FormatLocale.java index 55aae027c6c..79aac6349a0 100644 --- a/jdk/test/java/util/Formatter/FormatLocale.java +++ b/jdk/test/java/util/Formatter/FormatLocale.java @@ -24,6 +24,7 @@ /** * @test * @bug 8146156 8159548 + * @modules jdk.localedata * @summary test whether uppercasing follows Locale.Category.FORMAT locale. * @run main/othervm FormatLocale */ diff --git a/jdk/test/java/util/ResourceBundle/modules/security/TestPermission.java b/jdk/test/java/util/ResourceBundle/modules/security/TestPermission.java index 4e68a347af8..14db7ad2113 100644 --- a/jdk/test/java/util/ResourceBundle/modules/security/TestPermission.java +++ b/jdk/test/java/util/ResourceBundle/modules/security/TestPermission.java @@ -69,6 +69,7 @@ public class TestPermission { @Test public void runTest() throws Exception { int exitValue = executeTestJava("--module-path", MODS_DIR.toString(), + "--add-modules", "m1", "-m", "test/jdk.test.Main") .outputTo(System.out) .errorTo(System.out) diff --git a/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java b/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java index a9084f3437b..ff6d1bc1726 100644 --- a/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java +++ b/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java @@ -42,7 +42,7 @@ import static org.testng.Assert.*; * @test * @library /lib/testlibrary * @modules java.scripting - jdk.compiler + * jdk.compiler * @build ServicesTest CompilerUtils jdk.testlibrary.* * @run testng ServicesTest * @summary Tests ServiceLoader to locate service providers on the module path @@ -112,6 +112,7 @@ public class ServicesTest { public void runWithModulePath() throws Exception { int exitValue = executeTestJava("--module-path", MODS_DIR.toString(), + "--add-modules", "bananascript", "-m", "test/test.Main", "BananaScriptEngine") .outputTo(System.out) @@ -131,6 +132,7 @@ public class ServicesTest { int exitValue = executeTestJava("--module-path", MODS_DIR.toString(), "-cp", CLASSES_DIR.toString(), + "--add-modules", "bananascript", "-m", "test/test.Main", "BananaScriptEngine", "PearScriptEngine") .outputTo(System.out) diff --git a/jdk/test/java/util/TimeZone/HongKong.java b/jdk/test/java/util/TimeZone/HongKong.java index ef9c3f923f5..ead08f37387 100644 --- a/jdk/test/java/util/TimeZone/HongKong.java +++ b/jdk/test/java/util/TimeZone/HongKong.java @@ -24,6 +24,7 @@ /* * @test * @bug 4487276 8008577 + * @modules jdk.localedata * @summary Verify that Hong Kong locale uses traditional Chinese names. * @run main/othervm -Djava.locale.providers=COMPAT,SPI HongKong */ diff --git a/jdk/test/java/util/logging/modules/GetResourceBundleTest.java b/jdk/test/java/util/logging/modules/GetResourceBundleTest.java index 8bf01eb654d..5c771b949e5 100644 --- a/jdk/test/java/util/logging/modules/GetResourceBundleTest.java +++ b/jdk/test/java/util/logging/modules/GetResourceBundleTest.java @@ -37,6 +37,7 @@ import static org.testng.Assert.*; * @bug 8129126 8136802 8137316 8137317 8136804 8139350 * @library /lib/testlibrary * @modules jdk.compiler + * java.logging * @build GetResourceBundleTest CompilerUtils jdk.testlibrary.ProcessTools * @run testng GetResourceBundleTest * @summary Tests Logger.getLogger + logger.getResourceBundle in an named/unnamed module, From f5321ccf862297175ef7469ff30806c225f076e1 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 8 Sep 2016 21:11:54 +0000 Subject: [PATCH 12/38] Added tag jdk-9+135 for changeset 6d7a656b1612 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 5a179a2c6bd..ff5e6944eca 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -377,3 +377,4 @@ c40c8739bcdc88892ff58ebee3fd8a3f287be94d jdk-9+123 d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132 3cdae27c90b5e41afe75eab904fda19fac076330 jdk-9+133 803adcd526d74ae0b64948d1f8260c2dbe514779 jdk-9+134 +021369229cfd0b5feb76834b2ea498f47f43c0f3 jdk-9+135 From d14725c1ad8aabf78b21775134eb79bf604831ef Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 8 Sep 2016 14:23:45 -0700 Subject: [PATCH 13/38] 8039854: Broken link in java.lang.RuntimePermission Reviewed-by: lancea --- .../share/classes/java/lang/RuntimePermission.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java b/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java index d014ddb3378..46d8ef23c08 100644 --- a/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java +++ b/jdk/src/java.base/share/classes/java/lang/RuntimePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -323,11 +323,9 @@ import java.util.StringTokenizer; * usePolicy * Granting this permission disables the Java Plug-In's default * security prompting behavior. - * For more information, refer to Java Plug-In's guides, - * Applet Security Basics and - * usePolicy Permission. + * For more information, refer to the deployment guide. + * * * * manageProcess From 97ed09e07567631369c7b915fec0204dc6e5f01a Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Wed, 7 Sep 2016 14:44:59 -0700 Subject: [PATCH 14/38] 8165643: SecureDirectoryStream doesn't work on linux non-x86 Reviewed-by: alanb --- .../unix/native/libnio/fs/UnixNativeDispatcher.c | 9 +++++---- jdk/test/java/nio/file/DirectoryStream/SecureDS.java | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index 81b37db572f..16166a5f83b 100644 --- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -52,6 +52,10 @@ #include #endif +#ifdef __linux__ +#include +#endif + #if defined(__linux__) || defined(_AIX) #include #endif @@ -157,14 +161,11 @@ static int fstatat64_wrapper(int dfd, const char *path, } #endif -#if defined(__linux__) && defined(__x86_64__) +#if defined(__linux__) && defined(_LP64) && defined(__NR_newfstatat) #define FSTATAT64_SYSCALL_AVAILABLE static int fstatat64_wrapper(int dfd, const char *path, struct stat64 *statbuf, int flag) { - #ifndef __NR_newfstatat - #define __NR_newfstatat 262 - #endif return syscall(__NR_newfstatat, dfd, path, statbuf, flag); } #endif diff --git a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java index 60ca72ec3e6..250e84763db 100644 --- a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java +++ b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java @@ -45,6 +45,9 @@ public class SecureDS { DirectoryStream stream = newDirectoryStream(dir); stream.close(); if (!(stream instanceof SecureDirectoryStream)) { + if (System.getProperty("os.name").equals("Linux")) + throw new AssertionError( + "SecureDirectoryStream not supported."); System.out.println("SecureDirectoryStream not supported."); return; } From 32ded5866af46756cca84c669e674a14775860a8 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Thu, 8 Sep 2016 14:35:02 +0530 Subject: [PATCH 15/38] 8165595: Main class should be set for nashorn modules Reviewed-by: jlaskey, erikj --- make/CreateJmods.gmk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index c452f1b9cf1..d8471a09aea 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -82,6 +82,14 @@ ifeq ($(MODULE), java.base) endif endif +ifeq ($(MODULE), jdk.scripting.nashorn.shell) + JMOD_FLAGS += --main-class jdk.nashorn.tools.jjs.Main +endif + +ifeq ($(MODULE), jdk.scripting.nashorn) + JMOD_FLAGS += --main-class jdk.nashorn.tools.Shell +endif + # Changes to the jmod tool itself should also trigger a rebuild of all jmods. # The variable JMOD_CMD could contain an environment variable assignment before # the actual command. Filter that out using wildcard before adding to DEPS. From 8d9bb1153845a7559ab4fc6bbc64c10ffbd37480 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 8 Sep 2016 21:11:52 +0000 Subject: [PATCH 16/38] Added tag jdk-9+135 for changeset c55ef7ed9aa0 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 0c614608939..c9694066072 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -377,3 +377,4 @@ d94d54a3192fea79234c3ac55cd0b4052d45e954 jdk-9+130 a24702d4d5ab0015a5c553ed57f66fce7d85155e jdk-9+132 be1218f792a450dfb5d4b1f82616b9d95a6a732e jdk-9+133 065724348690eda41fc69112278d8da6dcde548c jdk-9+134 +82b94cb5f342319d2cda77f9fa59703ad7fde576 jdk-9+135 From 9525f089b51b8e7d430cecf4630612cdb02f0318 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 8 Sep 2016 21:11:53 +0000 Subject: [PATCH 17/38] Added tag jdk-9+135 for changeset 967c7d5073aa --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 4cc7243b9ce..a52c2a2a2da 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -537,3 +537,4 @@ e96b34b76d863ed1fa04e0eeb3f297ac17b490fd jdk-9+129 713951c08aa26813375175c2ab6cc99ff2a56903 jdk-9+132 a25e0fb6033245ab075136e744d362ce765464cd jdk-9+133 b8b694c6b4d2ab0939aed7adaf0eec1ac321a085 jdk-9+134 +3b1c4562953db47e36b237a500f368d5c9746d47 jdk-9+135 From 05b653ef70ff2786cb560ce351cfaa28dc54e09a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 8 Sep 2016 21:11:53 +0000 Subject: [PATCH 18/38] Added tag jdk-9+135 for changeset e8d5d0486ea5 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index ee81ced5edd..3b09618de85 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -377,3 +377,4 @@ f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131 1ab4b9399c4cba584f66c1c088188f2f565fbf9c jdk-9+132 2021bfedf1c478a4808a7711a6090682a12f4c0e jdk-9+133 1a497f5ca0cfd88115cc7daa8af8a62b8741caf2 jdk-9+134 +094d0db606db976045f594dba47d4593b715cc81 jdk-9+135 From 44d69dd31b88625886e431c8378a8c5f9a18052b Mon Sep 17 00:00:00 2001 From: Sergei Kovalev Date: Fri, 9 Sep 2016 10:58:05 -0700 Subject: [PATCH 19/38] 8165592: Fix module dependencies for sun/text/* tests Reviewed-by: naoto --- .../text/resources/Collator/Bug4248694.java | 8 ++++--- .../text/resources/Collator/Bug4804273.java | 8 ++++--- .../text/resources/Collator/Bug6755060.java | 8 ++++--- .../sun/text/resources/Format/Bug4395196.java | 21 +++++++++++-------- .../sun/text/resources/Format/Bug4442855.java | 16 +++++++------- .../sun/text/resources/Format/Bug4621320.java | 8 ++++--- .../sun/text/resources/Format/Bug4651568.java | 11 +++++----- .../sun/text/resources/Format/Bug4762201.java | 18 +++++++++------- .../sun/text/resources/Format/Bug4807540.java | 3 ++- .../sun/text/resources/Format/Bug4810032.java | 14 +++++++------ .../sun/text/resources/Format/Bug4994312.java | 9 ++++---- .../sun/text/resources/Format/Bug5096553.java | 3 ++- .../sun/text/resources/Format/Bug8037343.java | 3 ++- .../sun/text/resources/Format/Bug8074791.java | 5 +++-- .../sun/text/resources/LocaleDataTest.java | 17 +++++++++++---- 15 files changed, 92 insertions(+), 60 deletions(-) diff --git a/jdk/test/sun/text/resources/Collator/Bug4248694.java b/jdk/test/sun/text/resources/Collator/Bug4248694.java index b9339744f7e..a22ffa2ae3c 100644 --- a/jdk/test/sun/text/resources/Collator/Bug4248694.java +++ b/jdk/test/sun/text/resources/Collator/Bug4248694.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,11 +24,13 @@ /* * @test * @bug 4248694 + * @modules jdk.localedata * @summary updating collation tables for icelandic */ -import java.text.*; -import java.util.*; +import java.text.Collator; +import java.util.Arrays; +import java.util.Locale; public class Bug4248694 { diff --git a/jdk/test/sun/text/resources/Collator/Bug4804273.java b/jdk/test/sun/text/resources/Collator/Bug4804273.java index 0d60f3062e7..200280b3dab 100644 --- a/jdk/test/sun/text/resources/Collator/Bug4804273.java +++ b/jdk/test/sun/text/resources/Collator/Bug4804273.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,11 +24,13 @@ /* * @test * @bug 4804273 + * @modules jdk.localedata * @summary updating collation tables for swedish */ -import java.text.*; -import java.util.*; +import java.text.Collator; +import java.util.Arrays; +import java.util.Locale; public class Bug4804273 { diff --git a/jdk/test/sun/text/resources/Collator/Bug6755060.java b/jdk/test/sun/text/resources/Collator/Bug6755060.java index ee23487d44b..88b3d849a02 100644 --- a/jdk/test/sun/text/resources/Collator/Bug6755060.java +++ b/jdk/test/sun/text/resources/Collator/Bug6755060.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,11 +24,13 @@ /* * @test * @bug 6755060 + * @modules jdk.localedata * @summary updating collation tables for thai to make it consistent with CLDR 1.9 */ -import java.text.*; -import java.util.*; +import java.text.Collator; +import java.util.Arrays; +import java.util.Locale; public class Bug6755060 { diff --git a/jdk/test/sun/text/resources/Format/Bug4395196.java b/jdk/test/sun/text/resources/Format/Bug4395196.java index a36a140aa02..f73f7f17a88 100644 --- a/jdk/test/sun/text/resources/Format/Bug4395196.java +++ b/jdk/test/sun/text/resources/Format/Bug4395196.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,15 +22,18 @@ */ /* - *@test - *@bug 4395196 4930708 4900884 4890240 8008577 - *@summary verify the ko DateFormat - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug4395196 -*/ + * @test + * @bug 4395196 4930708 4900884 4890240 8008577 + * @modules jdk.localedata + * @summary verify the ko DateFormat + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4395196 + */ -import java.io.*; -import java.text.*; -import java.util.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; public class Bug4395196 { diff --git a/jdk/test/sun/text/resources/Format/Bug4442855.java b/jdk/test/sun/text/resources/Format/Bug4442855.java index 6b3c1954bb8..fbc344ec050 100644 --- a/jdk/test/sun/text/resources/Format/Bug4442855.java +++ b/jdk/test/sun/text/resources/Format/Bug4442855.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,14 +22,16 @@ */ /* - *@test - *@bug 4442855 - *@summary verify the era's translation for tradition chinese + * @test + * @bug 4442855 + * @modules jdk.localedata + * @summary verify the era's translation for tradition chinese */ -import java.io.*; -import java.util.*; -import java.text.*; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; public class Bug4442855 { diff --git a/jdk/test/sun/text/resources/Format/Bug4621320.java b/jdk/test/sun/text/resources/Format/Bug4621320.java index 2555dbfffbb..1331fb72616 100644 --- a/jdk/test/sun/text/resources/Format/Bug4621320.java +++ b/jdk/test/sun/text/resources/Format/Bug4621320.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,12 @@ /* * @test * @bug 4621320 + * @modules jdk.localedata * @summary Verify that Ukrainian month name is correct. */ -import java.text.*; -import java.util.*; + +import java.text.DateFormatSymbols; +import java.util.Locale; public class Bug4621320 { diff --git a/jdk/test/sun/text/resources/Format/Bug4651568.java b/jdk/test/sun/text/resources/Format/Bug4651568.java index c5b4ababa6f..354e3926e28 100644 --- a/jdk/test/sun/text/resources/Format/Bug4651568.java +++ b/jdk/test/sun/text/resources/Format/Bug4651568.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,11 @@ */ /* - *@test - *@bug 4651568 8008577 - *@summary Verifies the currency pattern for pt_BR locale - *@run main/othervm -Djava.locale.providers=JRE,SPI Bug4651568 + * @test + * @bug 4651568 8008577 + * @modules jdk.localedata + * @summary Verifies the currency pattern for pt_BR locale + * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4651568 */ import java.text.DecimalFormat; diff --git a/jdk/test/sun/text/resources/Format/Bug4762201.java b/jdk/test/sun/text/resources/Format/Bug4762201.java index 78dfce9e42c..83863d25894 100644 --- a/jdk/test/sun/text/resources/Format/Bug4762201.java +++ b/jdk/test/sun/text/resources/Format/Bug4762201.java @@ -22,15 +22,17 @@ */ /* - *@test - *@bug 4762201 - *@summary verify the zh_CN full time pattern (and other time patterns) - *@run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4762201 -*/ + * @test + * @bug 4762201 + * @modules jdk.localedata + * @summary verify the zh_CN full time pattern (and other time patterns) + * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4762201 + */ -import java.io.*; -import java.text.*; -import java.util.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; public class Bug4762201 { diff --git a/jdk/test/sun/text/resources/Format/Bug4807540.java b/jdk/test/sun/text/resources/Format/Bug4807540.java index fc6a4922faa..972b8fc5b63 100644 --- a/jdk/test/sun/text/resources/Format/Bug4807540.java +++ b/jdk/test/sun/text/resources/Format/Bug4807540.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test %i% * @bug 4807540 8008577 + * @modules jdk.localedata * @summary updating dateformat for sl_SI * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4807540 */ diff --git a/jdk/test/sun/text/resources/Format/Bug4810032.java b/jdk/test/sun/text/resources/Format/Bug4810032.java index ccfe357f552..2da7742abc8 100644 --- a/jdk/test/sun/text/resources/Format/Bug4810032.java +++ b/jdk/test/sun/text/resources/Format/Bug4810032.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,14 +22,16 @@ */ /* - *@test - *@bug 4810032 8008577 - *@summary verify the ja full time pattern parsing + * @test + * @bug 4810032 8008577 + * @modules jdk.localedata + * @summary verify the ja full time pattern parsing * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4810032 */ -import java.text.*; -import java.util.*; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Locale; public class Bug4810032 { diff --git a/jdk/test/sun/text/resources/Format/Bug4994312.java b/jdk/test/sun/text/resources/Format/Bug4994312.java index 401dde809e8..691923e914b 100644 --- a/jdk/test/sun/text/resources/Format/Bug4994312.java +++ b/jdk/test/sun/text/resources/Format/Bug4994312.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,9 +22,10 @@ */ /* - *@test - *@bug 4994312 8008577 - *@summary verify the German locale will accept localized pattern chars 't' and 'u'. + * @test + * @bug 4994312 8008577 + * @modules jdk.localedata + * @summary verify the German locale will accept localized pattern chars 't' and 'u'. * @run main/othervm -Djava.locale.providers=JRE,SPI Bug4994312 */ diff --git a/jdk/test/sun/text/resources/Format/Bug5096553.java b/jdk/test/sun/text/resources/Format/Bug5096553.java index 661a38e24b1..a3f377feaff 100644 --- a/jdk/test/sun/text/resources/Format/Bug5096553.java +++ b/jdk/test/sun/text/resources/Format/Bug5096553.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 5096553 8008577 + * @modules jdk.localedata * @summary updating dateformat for da_DK * following resources: * http://oss.software.ibm.com/cvs/icu/~checkout~/locale/common/main/da.xml diff --git a/jdk/test/sun/text/resources/Format/Bug8037343.java b/jdk/test/sun/text/resources/Format/Bug8037343.java index 6884193fd25..fa13c9d2887 100644 --- a/jdk/test/sun/text/resources/Format/Bug8037343.java +++ b/jdk/test/sun/text/resources/Format/Bug8037343.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 8008577 8037343 + * @modules jdk.localedata * @summary updating dateformat for es_DO * @run main/othervm -Djava.locale.providers=JRE,SPI Bug8037343 */ diff --git a/jdk/test/sun/text/resources/Format/Bug8074791.java b/jdk/test/sun/text/resources/Format/Bug8074791.java index 138158ca090..de23f738216 100644 --- a/jdk/test/sun/text/resources/Format/Bug8074791.java +++ b/jdk/test/sun/text/resources/Format/Bug8074791.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 8074791 + * @modules jdk.localedata * @summary Make sure that Finnish month names are correct in formatted text. */ @@ -32,7 +33,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; -import static java.text.DateFormat.*; +import static java.text.DateFormat.LONG; import static java.util.Calendar.JANUARY; public class Bug8074791 { diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 6f1dca3e0d0..b428fa6a422 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -40,6 +40,7 @@ * 8145136 * @summary Verify locale data * @modules java.base/sun.util.resources + * @modules jdk.localedata * @run main LocaleDataTest * @run main LocaleDataTest -cldr * @@ -145,12 +146,20 @@ * this test against the new version of the data. */ -import java.io.*; -import java.text.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FilterReader; +import java.io.FilterWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; import java.util.Locale; -import java.util.ResourceBundle; -import java.util.ResourceBundle.Control; import java.util.MissingResourceException; +import java.util.ResourceBundle; import sun.util.resources.LocaleData; public class LocaleDataTest From e249470c72515cbd49466eeb759e0e949fe46ecc Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Fri, 9 Sep 2016 12:07:49 -0700 Subject: [PATCH 20/38] 4285505: deprecate java.lang.Compiler Reviewed-by: shade, forax, kmo, tellison, mchung, alanb, rriggs --- .../share/classes/java/lang/Compiler.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Compiler.java b/jdk/src/java.base/share/classes/java/lang/Compiler.java index fd4f3045d48..1726b693219 100644 --- a/jdk/src/java.base/share/classes/java/lang/Compiler.java +++ b/jdk/src/java.base/share/classes/java/lang/Compiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,21 +29,18 @@ package java.lang; * The {@code Compiler} class is provided to support Java-to-native-code * compilers and related services. By design, the {@code Compiler} class does * nothing; it serves as a placeholder for a JIT compiler implementation. + * If no compiler is available, these methods do nothing. * - *

        When the Java Virtual Machine first starts, it determines if the system - * property {@code java.compiler} exists. (System properties are accessible - * through {@link System#getProperty(String)} and {@link - * System#getProperty(String, String)}. If so, it is assumed to be the name of - * a library (with a platform-dependent exact location and type); {@link - * System#loadLibrary} is called to load that library. If this loading - * succeeds, the function named {@code java_lang_Compiler_start()} in that - * library is called. - * - *

        If no compiler is available, these methods do nothing. + * @deprecated JIT compilers and their technologies vary too widely to + * be controlled effectively by a standardized interface. As such, many + * JIT compiler implementations ignore this interface, and are instead + * controllable by implementation-specific mechanisms such as command-line + * options. This class is subject to removal in a future version of Java SE. * * @author Frank Yellin * @since 1.0 */ +@Deprecated(since="9", forRemoval=true) public final class Compiler { private Compiler() {} // don't make instances From 4f08176bb5ec74791d84454083ff178d3e08f5da Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Fri, 9 Sep 2016 16:24:24 -0400 Subject: [PATCH 21/38] 8165393: bad merge in java/lang/ref/package-info.java Added the missing change. Reviewed-by: rriggs --- .../java.base/share/classes/java/lang/ref/package-info.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ref/package-info.java b/jdk/src/java.base/share/classes/java/lang/ref/package-info.java index 1ee769d16cc..58600cba1b8 100644 --- a/jdk/src/java.base/share/classes/java/lang/ref/package-info.java +++ b/jdk/src/java.base/share/classes/java/lang/ref/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,7 @@ * implementing memory-sensitive caches, weak references are for * implementing canonicalizing mappings that do not prevent their keys * (or values) from being reclaimed, and phantom references are for - * scheduling pre-mortem cleanup actions in a more flexible way than - * is possible with the Java finalization mechanism. + * scheduling post-mortem cleanup actions. * Post-mortem cleanup actions can be registered and managed by a * {@link java.lang.ref.Cleaner}. * From 397525a2d450ca242f671e2efceeceacee15a845 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 9 Sep 2016 13:44:48 -0700 Subject: [PATCH 22/38] 8165346: j.l.ClassLoader.getDefinedPackage(String) throws NPE Reviewed-by: alanb, lancea, shade --- .../share/classes/java/lang/ClassLoader.java | 8 +++ .../share/classes/java/lang/Package.java | 3 + .../lang/ClassLoader/GetDefinedPackage.java | 57 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 jdk/test/java/lang/ClassLoader/GetDefinedPackage.java diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 47b9e1c8be5..fcd21f3058b 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1922,9 +1922,14 @@ public abstract class ClassLoader { * @return The {@code Package} of the given name defined by this class loader, * or {@code null} if not found * + * @throws NullPointerException + * if {@code name} is {@code null}. + * * @since 9 */ public final Package getDefinedPackage(String name) { + Objects.requireNonNull(name, "name cannot be null"); + NamedPackage p = packages.get(name); if (p == null) return null; @@ -1962,6 +1967,9 @@ public abstract class ClassLoader { * @return The {@code Package} corresponding to the given name defined by * this class loader or its ancestors, or {@code null} if not found. * + * @throws NullPointerException + * if {@code name} is {@code null}. + * * @deprecated * If multiple class loaders delegate to each other and define classes * with the same package name, and one such loader relies on the lookup diff --git a/jdk/src/java.base/share/classes/java/lang/Package.java b/jdk/src/java.base/share/classes/java/lang/Package.java index 1aa9e98fbf2..b4ba45b8f35 100644 --- a/jdk/src/java.base/share/classes/java/lang/Package.java +++ b/jdk/src/java.base/share/classes/java/lang/Package.java @@ -317,6 +317,9 @@ public class Package extends NamedPackage implements java.lang.reflect.Annotated * @return The {@code Package} of the given name defined by the caller's * class loader or its ancestors, or {@code null} if not found. * + * @throws NullPointerException + * if {@code name} is {@code null}. + * * @deprecated * If multiple class loaders delegate to each other and define classes * with the same package name, and one such loader relies on the lookup diff --git a/jdk/test/java/lang/ClassLoader/GetDefinedPackage.java b/jdk/test/java/lang/ClassLoader/GetDefinedPackage.java new file mode 100644 index 00000000000..c20ca101c0f --- /dev/null +++ b/jdk/test/java/lang/ClassLoader/GetDefinedPackage.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, 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 8165346 + * @summary Basic test for ClassLoader::getDefinedPackage + */ + +public class GetDefinedPackage { + public static void main(String... args) { + TestClassLoader loader = new TestClassLoader(); + Package pkg = loader.getDefinedPackage(TestClassLoader.PKG_NAME); + if (pkg == null) { + throw new RuntimeException("package foo not found"); + } + + try { + loader.getDefinedPackage(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException e) { + } + } + + static class TestClassLoader extends ClassLoader { + public static final String PKG_NAME = "foo"; + + public TestClassLoader() { + super(); + definePackage(PKG_NAME); + } + + public Package definePackage(String name) { + return definePackage(name, null, null, null, null, null, null, null); + } + } +} From caa7db449639ca45fb0a2f5c16f48526be09bb48 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Fri, 9 Sep 2016 14:54:24 -0700 Subject: [PATCH 23/38] 8165731: Reference to removed method in VarHandle JavaDoc Reviewed-by: shade, bpb --- jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 50e81913c16..167de41e98b 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -152,7 +152,6 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError; * {@link #getAndAdd getAndAdd}, * {@link #getAndAddAcquire getAndAddAcquire}, * {@link #getAndAddRelease getAndAddRelease}, - * {@link #addAndGet addAndGet}. *

      • bitwise atomic update access modes that, for example, atomically get and * bitwise OR the value of a variable under specified memory ordering * effects. From a7dd7b59dac29f20dcdabf646dcab34981a2a677 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Fri, 9 Sep 2016 14:54:29 -0700 Subject: [PATCH 24/38] 8164691: Stream specification clarifications for iterate and collect Reviewed-by: briangoetz, smarks, tvaleev --- .../java/util/stream/DoubleStream.java | 79 +++++++++++-------- .../classes/java/util/stream/IntStream.java | 79 +++++++++++-------- .../classes/java/util/stream/LongStream.java | 79 +++++++++++-------- .../classes/java/util/stream/Stream.java | 77 +++++++++++------- 4 files changed, 191 insertions(+), 123 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java index 59f669baf67..2bc146c8d5f 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java @@ -567,19 +567,23 @@ public interface DoubleStream extends BaseStream { *

        This is a terminal * operation. * - * @param type of the result - * @param supplier a function that creates a new result container. For a - * parallel execution, this function may be called + * @param the type of the mutable result container + * @param supplier a function that creates a new mutable result container. + * For a parallel execution, this function may be called * multiple times and must return a fresh value each time. * @param accumulator an associative, * non-interfering, * stateless - * function for incorporating an additional element into a result + * function that must fold an element into a result + * container. * @param combiner an associative, * non-interfering, * stateless - * function for combining two values, which must be - * compatible with the accumulator function + * function that accepts two partial result containers + * and merges them, which must be compatible with the + * accumulator function. The combiner function must fold + * the elements from the second result container into the + * first result container. * @return the result of the reduction * @see Stream#collect(Supplier, BiConsumer, BiConsumer) */ @@ -947,6 +951,12 @@ public interface DoubleStream extends BaseStream { * position {@code n}, will be the result of applying the function {@code f} * to the element at position {@code n - 1}. * + *

        The action of applying {@code f} for one element + * happens-before + * the action of applying {@code f} for subsequent elements. For any given + * element the action may be performed in whatever thread the library + * chooses. + * * @param seed the initial element * @param f a function to be applied to the previous element to produce * a new element @@ -978,37 +988,44 @@ public interface DoubleStream extends BaseStream { /** * Returns a sequential ordered {@code DoubleStream} produced by iterative - * application of a function to an initial element, conditioned on - * satisfying the supplied predicate. The stream terminates as soon as - * the predicate returns false. + * application of the given {@code next} function to an initial element, + * conditioned on satisfying the given {@code hasNext} predicate. The + * stream terminates as soon as the {@code hasNext} predicate returns false. * - *

        - * {@code DoubleStream.iterate} should produce the same sequence of - * elements as produced by the corresponding for-loop: + *

        {@code DoubleStream.iterate} should produce the same sequence of elements as + * produced by the corresponding for-loop: *

        {@code
        -     *     for (double index=seed; predicate.test(index); index = f.applyAsDouble(index)) {
        +     *     for (double index=seed; hasNext.test(index); index = next.applyAsDouble(index)) {
              *         ...
              *     }
              * }
        * - *

        - * The resulting sequence may be empty if the predicate does not hold on - * the seed value. Otherwise the first element will be the supplied seed - * value, the next element (if present) will be the result of applying the - * function f to the seed value, and so on iteratively until the predicate - * indicates that the stream should terminate. + *

        The resulting sequence may be empty if the {@code hasNext} predicate + * does not hold on the seed value. Otherwise the first element will be the + * supplied {@code seed} value, the next element (if present) will be the + * result of applying the {@code next} function to the {@code seed} value, + * and so on iteratively until the {@code hasNext} predicate indicates that + * the stream should terminate. + * + *

        The action of applying the {@code hasNext} predicate to an element + * happens-before + * the action of applying the {@code next} function to that element. The + * action of applying the {@code next} function for one element + * happens-before the action of applying the {@code hasNext} + * predicate for subsequent elements. For any given element an action may + * be performed in whatever thread the library chooses. * * @param seed the initial element - * @param predicate a predicate to apply to elements to determine when the - * stream must terminate. - * @param f a function to be applied to the previous element to produce - * a new element + * @param hasNext a predicate to apply to elements to determine when the + * stream must terminate. + * @param next a function to be applied to the previous element to produce + * a new element * @return a new sequential {@code DoubleStream} * @since 9 */ - public static DoubleStream iterate(double seed, DoublePredicate predicate, DoubleUnaryOperator f) { - Objects.requireNonNull(f); - Objects.requireNonNull(predicate); + public static DoubleStream iterate(double seed, DoublePredicate hasNext, DoubleUnaryOperator next) { + Objects.requireNonNull(next); + Objects.requireNonNull(hasNext); Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { double prev; @@ -1021,12 +1038,12 @@ public interface DoubleStream extends BaseStream { return false; double t; if (started) - t = f.applyAsDouble(prev); + t = next.applyAsDouble(prev); else { t = seed; started = true; } - if (!predicate.test(t)) { + if (!hasNext.test(t)) { finished = true; return false; } @@ -1040,10 +1057,10 @@ public interface DoubleStream extends BaseStream { if (finished) return; finished = true; - double t = started ? f.applyAsDouble(prev) : seed; - while (predicate.test(t)) { + double t = started ? next.applyAsDouble(prev) : seed; + while (hasNext.test(t)) { action.accept(t); - t = f.applyAsDouble(t); + t = next.applyAsDouble(t); } } }; diff --git a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java index daeac3ab140..c051a12bec7 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java @@ -562,19 +562,23 @@ public interface IntStream extends BaseStream { *

        This is a terminal * operation. * - * @param type of the result - * @param supplier a function that creates a new result container. For a - * parallel execution, this function may be called + * @param the type of the mutable result container + * @param supplier a function that creates a new mutable result container. + * For a parallel execution, this function may be called * multiple times and must return a fresh value each time. * @param accumulator an associative, * non-interfering, * stateless - * function for incorporating an additional element into a result + * function that must fold an element into a result + * container. * @param combiner an associative, * non-interfering, * stateless - * function for combining two values, which must be - * compatible with the accumulator function + * function that accepts two partial result containers + * and merges them, which must be compatible with the + * accumulator function. The combiner function must fold + * the elements from the second result container into the + * first result container. * @return the result of the reduction * @see Stream#collect(Supplier, BiConsumer, BiConsumer) */ @@ -887,6 +891,12 @@ public interface IntStream extends BaseStream { * {@code n}, will be the result of applying the function {@code f} to the * element at position {@code n - 1}. * + *

        The action of applying {@code f} for one element + * happens-before + * the action of applying {@code f} for subsequent elements. For any given + * element the action may be performed in whatever thread the library + * chooses. + * * @param seed the initial element * @param f a function to be applied to the previous element to produce * a new element @@ -918,37 +928,44 @@ public interface IntStream extends BaseStream { /** * Returns a sequential ordered {@code IntStream} produced by iterative - * application of a function to an initial element, conditioned on - * satisfying the supplied predicate. The stream terminates as soon as - * the predicate returns false. + * application of the given {@code next} function to an initial element, + * conditioned on satisfying the given {@code hasNext} predicate. The + * stream terminates as soon as the {@code hasNext} predicate returns false. * - *

        - * {@code IntStream.iterate} should produce the same sequence of elements - * as produced by the corresponding for-loop: + *

        {@code IntStream.iterate} should produce the same sequence of elements as + * produced by the corresponding for-loop: *

        {@code
        -     *     for (int index=seed; predicate.test(index); index = f.applyAsInt(index)) {
        +     *     for (int index=seed; hasNext.test(index); index = next.applyAsInt(index)) {
              *         ...
              *     }
              * }
        * - *

        - * The resulting sequence may be empty if the predicate does not hold on - * the seed value. Otherwise the first element will be the supplied seed - * value, the next element (if present) will be the result of applying the - * function f to the seed value, and so on iteratively until the predicate - * indicates that the stream should terminate. + *

        The resulting sequence may be empty if the {@code hasNext} predicate + * does not hold on the seed value. Otherwise the first element will be the + * supplied {@code seed} value, the next element (if present) will be the + * result of applying the {@code next} function to the {@code seed} value, + * and so on iteratively until the {@code hasNext} predicate indicates that + * the stream should terminate. + * + *

        The action of applying the {@code hasNext} predicate to an element + * happens-before + * the action of applying the {@code next} function to that element. The + * action of applying the {@code next} function for one element + * happens-before the action of applying the {@code hasNext} + * predicate for subsequent elements. For any given element an action may + * be performed in whatever thread the library chooses. * * @param seed the initial element - * @param predicate a predicate to apply to elements to determine when the - * stream must terminate. - * @param f a function to be applied to the previous element to produce - * a new element + * @param hasNext a predicate to apply to elements to determine when the + * stream must terminate. + * @param next a function to be applied to the previous element to produce + * a new element * @return a new sequential {@code IntStream} * @since 9 */ - public static IntStream iterate(int seed, IntPredicate predicate, IntUnaryOperator f) { - Objects.requireNonNull(f); - Objects.requireNonNull(predicate); + public static IntStream iterate(int seed, IntPredicate hasNext, IntUnaryOperator next) { + Objects.requireNonNull(next); + Objects.requireNonNull(hasNext); Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { int prev; @@ -961,12 +978,12 @@ public interface IntStream extends BaseStream { return false; int t; if (started) - t = f.applyAsInt(prev); + t = next.applyAsInt(prev); else { t = seed; started = true; } - if (!predicate.test(t)) { + if (!hasNext.test(t)) { finished = true; return false; } @@ -980,10 +997,10 @@ public interface IntStream extends BaseStream { if (finished) return; finished = true; - int t = started ? f.applyAsInt(prev) : seed; - while (predicate.test(t)) { + int t = started ? next.applyAsInt(prev) : seed; + while (hasNext.test(t)) { action.accept(t); - t = f.applyAsInt(t); + t = next.applyAsInt(t); } } }; diff --git a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java index d6428d55df5..bbdc1d00e0c 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java @@ -564,19 +564,23 @@ public interface LongStream extends BaseStream { *

        This is a terminal * operation. * - * @param type of the result - * @param supplier a function that creates a new result container. For a - * parallel execution, this function may be called + * @param the type of the mutable result container + * @param supplier a function that creates a new mutable result container. + * For a parallel execution, this function may be called * multiple times and must return a fresh value each time. * @param accumulator an associative, * non-interfering, * stateless - * function for incorporating an additional element into a result + * function that must fold an element into a result + * container. * @param combiner an associative, * non-interfering, * stateless - * function for combining two values, which must be - * compatible with the accumulator function + * function that accepts two partial result containers + * and merges them, which must be compatible with the + * accumulator function. The combiner function must fold + * the elements from the second result container into the + * first result container. * @return the result of the reduction * @see Stream#collect(Supplier, BiConsumer, BiConsumer) */ @@ -877,6 +881,12 @@ public interface LongStream extends BaseStream { * {@code n}, will be the result of applying the function {@code f} to the * element at position {@code n - 1}. * + *

        The action of applying {@code f} for one element + * happens-before + * the action of applying {@code f} for subsequent elements. For any given + * element the action may be performed in whatever thread the library + * chooses. + * * @param seed the initial element * @param f a function to be applied to the previous element to produce * a new element @@ -908,37 +918,44 @@ public interface LongStream extends BaseStream { /** * Returns a sequential ordered {@code LongStream} produced by iterative - * application of a function to an initial element, conditioned on - * satisfying the supplied predicate. The stream terminates as soon as - * the predicate returns false. + * application of the given {@code next} function to an initial element, + * conditioned on satisfying the given {@code hasNext} predicate. The + * stream terminates as soon as the {@code hasNext} predicate returns false. * - *

        - * {@code LongStream.iterate} should produce the same sequence of elements - * as produced by the corresponding for-loop: + *

        {@code LongStream.iterate} should produce the same sequence of elements as + * produced by the corresponding for-loop: *

        {@code
        -     *     for (long index=seed; predicate.test(index); index = f.applyAsLong(index)) {
        +     *     for (long index=seed; hasNext.test(index); index = next.applyAsLong(index)) {
              *         ...
              *     }
              * }
        * - *

        - * The resulting sequence may be empty if the predicate does not hold on - * the seed value. Otherwise the first element will be the supplied seed - * value, the next element (if present) will be the result of applying the - * function f to the seed value, and so on iteratively until the predicate - * indicates that the stream should terminate. + *

        The resulting sequence may be empty if the {@code hasNext} predicate + * does not hold on the seed value. Otherwise the first element will be the + * supplied {@code seed} value, the next element (if present) will be the + * result of applying the {@code next} function to the {@code seed} value, + * and so on iteratively until the {@code hasNext} predicate indicates that + * the stream should terminate. + * + *

        The action of applying the {@code hasNext} predicate to an element + * happens-before + * the action of applying the {@code next} function to that element. The + * action of applying the {@code next} function for one element + * happens-before the action of applying the {@code hasNext} + * predicate for subsequent elements. For any given element an action may + * be performed in whatever thread the library chooses. * * @param seed the initial element - * @param predicate a predicate to apply to elements to determine when the - * stream must terminate. - * @param f a function to be applied to the previous element to produce - * a new element + * @param hasNext a predicate to apply to elements to determine when the + * stream must terminate. + * @param next a function to be applied to the previous element to produce + * a new element * @return a new sequential {@code LongStream} * @since 9 */ - public static LongStream iterate(long seed, LongPredicate predicate, LongUnaryOperator f) { - Objects.requireNonNull(f); - Objects.requireNonNull(predicate); + public static LongStream iterate(long seed, LongPredicate hasNext, LongUnaryOperator next) { + Objects.requireNonNull(next); + Objects.requireNonNull(hasNext); Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { long prev; @@ -951,12 +968,12 @@ public interface LongStream extends BaseStream { return false; long t; if (started) - t = f.applyAsLong(prev); + t = next.applyAsLong(prev); else { t = seed; started = true; } - if (!predicate.test(t)) { + if (!hasNext.test(t)) { finished = true; return false; } @@ -970,10 +987,10 @@ public interface LongStream extends BaseStream { if (finished) return; finished = true; - long t = started ? f.applyAsLong(prev) : seed; - while (predicate.test(t)) { + long t = started ? next.applyAsLong(prev) : seed; + while (hasNext.test(t)) { action.accept(t); - t = f.applyAsLong(t); + t = next.applyAsLong(t); } } }; diff --git a/jdk/src/java.base/share/classes/java/util/stream/Stream.java b/jdk/src/java.base/share/classes/java/util/stream/Stream.java index 7ab71a50aee..1ec21ed2b57 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java @@ -882,19 +882,23 @@ public interface Stream extends BaseStream> { * .toString(); * } * - * @param type of the result - * @param supplier a function that creates a new result container. For a - * parallel execution, this function may be called + * @param the type of the mutable result container + * @param supplier a function that creates a new mutable result container. + * For a parallel execution, this function may be called * multiple times and must return a fresh value each time. * @param accumulator an associative, * non-interfering, * stateless - * function for incorporating an additional element into a result + * function that must fold an element into a result + * container. * @param combiner an associative, * non-interfering, * stateless - * function for combining two values, which must be - * compatible with the accumulator function + * function that accepts two partial result containers + * and merges them, which must be compatible with the + * accumulator function. The combiner function must fold + * the elements from the second result container into the + * first result container. * @return the result of the reduction */ R collect(Supplier supplier, @@ -1194,6 +1198,12 @@ public interface Stream extends BaseStream> { * {@code n}, will be the result of applying the function {@code f} to the * element at position {@code n - 1}. * + *

        The action of applying {@code f} for one element + * happens-before + * the action of applying {@code f} for subsequent elements. For any given + * element the action may be performed in whatever thread the library + * chooses. + * * @param the type of stream elements * @param seed the initial element * @param f a function to be applied to the previous element to produce @@ -1226,38 +1236,45 @@ public interface Stream extends BaseStream> { /** * Returns a sequential ordered {@code Stream} produced by iterative - * application of a function to an initial element, conditioned on - * satisfying the supplied predicate. The stream terminates as soon as - * the predicate returns false. + * application of the given {@code next} function to an initial element, + * conditioned on satisfying the given {@code hasNext} predicate. The + * stream terminates as soon as the {@code hasNext} predicate returns false. * - *

        - * {@code Stream.iterate} should produce the same sequence of elements as + *

        {@code Stream.iterate} should produce the same sequence of elements as * produced by the corresponding for-loop: *

        {@code
        -     *     for (T index=seed; predicate.test(index); index = f.apply(index)) {
        +     *     for (T index=seed; hasNext.test(index); index = next.apply(index)) {
              *         ...
              *     }
              * }
        * - *

        - * The resulting sequence may be empty if the predicate does not hold on - * the seed value. Otherwise the first element will be the supplied seed - * value, the next element (if present) will be the result of applying the - * function f to the seed value, and so on iteratively until the predicate - * indicates that the stream should terminate. + *

        The resulting sequence may be empty if the {@code hasNext} predicate + * does not hold on the seed value. Otherwise the first element will be the + * supplied {@code seed} value, the next element (if present) will be the + * result of applying the {@code next} function to the {@code seed} value, + * and so on iteratively until the {@code hasNext} predicate indicates that + * the stream should terminate. + * + *

        The action of applying the {@code hasNext} predicate to an element + * happens-before + * the action of applying the {@code next} function to that element. The + * action of applying the {@code next} function for one element + * happens-before the action of applying the {@code hasNext} + * predicate for subsequent elements. For any given element an action may + * be performed in whatever thread the library chooses. * * @param the type of stream elements * @param seed the initial element - * @param predicate a predicate to apply to elements to determine when the - * stream must terminate. - * @param f a function to be applied to the previous element to produce - * a new element + * @param hasNext a predicate to apply to elements to determine when the + * stream must terminate. + * @param next a function to be applied to the previous element to produce + * a new element * @return a new sequential {@code Stream} * @since 9 */ - public static Stream iterate(T seed, Predicate predicate, UnaryOperator f) { - Objects.requireNonNull(f); - Objects.requireNonNull(predicate); + public static Stream iterate(T seed, Predicate hasNext, UnaryOperator next) { + Objects.requireNonNull(next); + Objects.requireNonNull(hasNext); Spliterator spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE) { T prev; @@ -1270,12 +1287,12 @@ public interface Stream extends BaseStream> { return false; T t; if (started) - t = f.apply(prev); + t = next.apply(prev); else { t = seed; started = true; } - if (!predicate.test(t)) { + if (!hasNext.test(t)) { prev = null; finished = true; return false; @@ -1290,11 +1307,11 @@ public interface Stream extends BaseStream> { if (finished) return; finished = true; - T t = started ? f.apply(prev) : seed; + T t = started ? next.apply(prev) : seed; prev = null; - while (predicate.test(t)) { + while (hasNext.test(t)) { action.accept(t); - t = f.apply(t); + t = next.apply(t); } } }; From 5deb28b6a15e2de0654d07a5a8efb9e405d821b3 Mon Sep 17 00:00:00 2001 From: Patrick Reinhart Date: Fri, 9 Sep 2016 14:54:41 -0700 Subject: [PATCH 25/38] 8161230: ClassLoader: add resource methods returning java.util.stream.Stream Reviewed-by: psandoz, alanb, mchung, tvaleev --- .../share/classes/java/lang/ClassLoader.java | 56 ++++++++++++ .../lang/ClassLoader/ResourcesStreamTest.java | 90 +++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 jdk/test/java/lang/ClassLoader/ResourcesStreamTest.java diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index fcd21f3058b..f011aa8b47e 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -27,6 +27,7 @@ package java.lang; import java.io.InputStream; import java.io.IOException; +import java.io.UncheckedIOException; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -46,12 +47,16 @@ import java.util.Hashtable; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.Stack; import java.util.NoSuchElementException; import java.util.Vector; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; import java.util.stream.Stream; +import java.util.stream.StreamSupport; import jdk.internal.perf.PerfCounter; import jdk.internal.module.ServicesCatalog; @@ -1343,6 +1348,57 @@ public abstract class ClassLoader { return new CompoundEnumeration<>(tmp); } + /** + * Returns a stream whose elements are the URLs of all the resources with + * the given name. A resource is some data (images, audio, text, etc) that + * can be accessed by class code in a way that is independent of the + * location of the code. + * + * Resources in a named module are private to that module. This method does + * not find resources in named modules. + * + *

        The name of a resource is a {@code /}-separated path name that + * identifies the resource. + * + *

        The search order is described in the documentation for {@link + * #getResource(String)}. + * + *

        The resources will be located when the returned stream is evaluated. + * If the evaluation results in an {@code IOException} then the I/O + * exception is wrapped in an {@link UncheckedIOException} that is then + * thrown. + * + * @apiNote When overriding this method it is recommended that an + * implementation ensures that any delegation is consistent with the {@link + * #getResource(java.lang.String) getResource(String)} method. This should + * ensure that the first element returned by the stream is the same + * resource that the {@code getResource(String)} method would return. + * + * @param name + * The resource name + * + * @return A stream of resource {@link java.net.URL URL} objects. If no + * resources could be found, the stream will be empty. Resources + * that the class loader doesn't have access to will not be in the + * stream. + * + * @see #findResources(String) + * + * @since 9 + */ + public Stream resources(String name) { + int characteristics = Spliterator.NONNULL | Spliterator.IMMUTABLE; + Supplier> si = () -> { + try { + return Spliterators.spliteratorUnknownSize( + getResources(name).asIterator(), characteristics); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }; + return StreamSupport.stream(si, characteristics, false); + } + /** * Finds the resource with the given name. Class loader implementations * should override this method to specify where to find resources. diff --git a/jdk/test/java/lang/ClassLoader/ResourcesStreamTest.java b/jdk/test/java/lang/ClassLoader/ResourcesStreamTest.java new file mode 100644 index 00000000000..789e0660cdc --- /dev/null +++ b/jdk/test/java/lang/ClassLoader/ResourcesStreamTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/* + * @test + * @bug 8161230 + * @summary Test java.lang.ClassLoader.resources() method + * + * @build ResourcesStreamTest + * @run main ResourcesStreamTest + */ +public class ResourcesStreamTest { + + public static void main(String[] args) throws Exception { + testSuccess(); + testFailure(); + } + + public static void testSuccess() throws Exception { + // failing part first + try { + ClassLoader cl = new FailingClassLoader(); + // should create the stream pipe + Stream stream = cl.resources("the name"); + // expect function to throw an exception when calling the method + stream.forEach(System.out::println); + throw new Exception("expected UncheckedIOException not thrown"); + } catch (UncheckedIOException uio) { + String causeMessage = uio.getCause().getMessage(); + if (!"the name".equals(causeMessage)) + throw new Exception("unexpected cause message: " + causeMessage); + } + } + + public static void testFailure() throws Exception { + ClassLoader cl = new SuccessClassLoader(); + long count = cl.resources("the name").count(); + if (count != 1) + throw new Exception("expected resource is null or empty"); + + cl.resources("the name") + .filter(url -> "file:/somefile".equals(url.toExternalForm())) + .findFirst() + .orElseThrow(() -> new Exception("correct URL not found")); + } + + public static class SuccessClassLoader extends ClassLoader { + @Override + public Enumeration getResources(String name) throws IOException { + URL url = new URL("file:/somefile"); + return Collections.enumeration(Collections.singleton(url)); + } + } + + public static class FailingClassLoader extends ClassLoader { + @Override + public Enumeration getResources(String name) throws IOException { + throw new IOException(name); + } + } +} From 85eaf2d3d36c2408e2c8bfd6659a317f966059ca Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Sat, 10 Sep 2016 06:46:45 +0530 Subject: [PATCH 26/38] 8165726: fix for 8165595 revealed a bug in pack200 tool's handling of main class attribute of module-info classes Reviewed-by: ksrini --- .../classes/com/sun/java/util/jar/pack/intrinsic.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties index be1687076cc..fa9ba74f047 100644 --- a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties +++ b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties @@ -18,7 +18,7 @@ pack.class.attribute.CompilationID = RUH pack.class.attribute.Module = NH[RUHFH]NH[RUHNH[RUH]]NH[RCH]NH[RCHRCH] pack.class.attribute.ConcealedPackages = NH[RUH] pack.class.attribute.Version = RUH -pack.class.attribute.MainClass = RUH +pack.class.attribute.MainClass = RCH pack.class.attribute.TargetPlatform = RUHRUHRUH pack.class.attribute.Hashes = RUHNH[RUHRUH] From ed6ffa4c96f626114c98a26ef977925b3dddfb3b Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Sun, 11 Sep 2016 13:23:14 -0700 Subject: [PATCH 27/38] 8165810: Problem list VersionCheck.java until JDK-8165772 is fixed Reviewed-by: lancea, redestad --- jdk/test/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 83515fad418..14ce0b92332 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -314,6 +314,8 @@ tools/launcher/FXLauncherTest.java 8068049 linux-al tools/pack200/Pack200Props.java 8155857 generic-all +tools/launcher/VersionCheck.java 8165772 generic-all + ############################################################################ # jdk_jdi From 32f983128df9a726058107bd209d2da130f4eec9 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 12 Sep 2016 13:23:07 +0200 Subject: [PATCH 28/38] 8165492: Reduce number of lambda forms generated by MethodHandleInlineCopyStrategy Reviewed-by: mhaupt, vlivanov, psandoz, shade --- .../classes/java/lang/StringConcatHelper.java | 6 +- .../java/lang/invoke/LambdaFormEditor.java | 85 ++++++++++++- .../java/lang/invoke/MethodHandles.java | 48 ++++++++ .../java/lang/invoke/StringConcatFactory.java | 113 ++++++------------ 4 files changed, 173 insertions(+), 79 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java b/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java index 1504e6ff37d..f3f16088f7a 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java +++ b/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java @@ -334,11 +334,15 @@ final class StringConcatHelper { /** * Instantiates the String with given buffer and coder * @param buf buffer to use + * @param index remaining index * @param coder coder to use * @return String resulting string */ - static String newString(byte[] buf, byte coder) { + static String newString(byte[] buf, int index, byte coder) { // Use the private, non-copying constructor (unsafe!) + if (index != 0) { + throw new InternalError("Storage is not completely initialized, " + index + " bytes left"); + } return new String(buf, coder); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java index cec4ff1ea54..ddd60ca082f 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java @@ -83,7 +83,9 @@ class LambdaFormEditor { FOLD_ARGS = 11, FOLD_ARGS_TO_VOID = 12, PERMUTE_ARGS = 13, - LOCAL_TYPES = 14; + LOCAL_TYPES = 14, + FOLD_SELECT_ARGS = 15, + FOLD_SELECT_ARGS_TO_VOID = 16; private static final boolean STRESS_TEST = false; // turn on to disable most packing private static final int @@ -695,6 +697,72 @@ class LambdaFormEditor { return buf.endEdit(); } + private LambdaForm makeArgumentCombinationForm(int pos, + MethodType combinerType, + int[] argPositions, + boolean keepArguments, + boolean dropResult) { + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + int combinerArity = combinerType.parameterCount(); + assert(combinerArity == argPositions.length); + + int resultArity = (dropResult ? 0 : 1); + + assert(pos <= lambdaForm.arity); + assert(pos > 0); // cannot filter the MH arg itself + assert(combinerType == combinerType.basicType()); + assert(combinerType.returnType() != void.class || dropResult); + + BoundMethodHandle.SpeciesData oldData = oldSpeciesData(); + BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE); + + // The newly created LF will run with a different BMH. + // Switch over any pre-existing BMH field references to the new BMH class. + Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values + buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); + Name newBaseAddress = oldBaseAddress.withConstraint(newData); + buf.renameParameter(0, newBaseAddress); + + Name getCombiner = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress); + Object[] combinerArgs = new Object[1 + combinerArity]; + combinerArgs[0] = getCombiner; + Name[] newParams; + if (keepArguments) { + newParams = new Name[0]; + for (int i = 0; i < combinerArity; i++) { + combinerArgs[i + 1] = lambdaForm.parameter(1 + argPositions[i]); + assert (basicType(combinerType.parameterType(i)) == lambdaForm.parameterType(1 + argPositions[i])); + } + } else { + newParams = new Name[combinerArity]; + for (int i = 0; i < newParams.length; i++) { + newParams[i] = lambdaForm.parameter(1 + argPositions[i]); + assert (basicType(combinerType.parameterType(i)) == lambdaForm.parameterType(1 + argPositions[i])); + } + System.arraycopy(newParams, 0, + combinerArgs, 1, combinerArity); + } + Name callCombiner = new Name(combinerType, combinerArgs); + + // insert the two new expressions + int exprPos = lambdaForm.arity(); + buf.insertExpression(exprPos+0, getCombiner); + buf.insertExpression(exprPos+1, callCombiner); + + // insert new arguments, if needed + int argPos = pos + resultArity; // skip result parameter + for (Name newParam : newParams) { + buf.insertParameter(argPos++, newParam); + } + assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length); + if (!dropResult) { + buf.replaceParameterByCopy(pos, exprPos+1+newParams.length); + } + + return buf.endEdit(); + } + LambdaForm filterReturnForm(BasicType newType, boolean constantZero) { byte kind = (constantZero ? Transform.FILTER_RETURN_TO_ZERO : Transform.FILTER_RETURN); Transform key = Transform.of(kind, newType.ordinal()); @@ -759,6 +827,21 @@ class LambdaFormEditor { return putInCache(key, form); } + LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType, int ... argPositions) { + byte kind = (dropResult ? Transform.FOLD_SELECT_ARGS_TO_VOID + : Transform.FOLD_SELECT_ARGS); + int[] keyArgs = Arrays.copyOf(argPositions, argPositions.length + 1); + keyArgs[argPositions.length] = foldPos; + Transform key = Transform.of(kind, keyArgs); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - (kind == Transform.FOLD_SELECT_ARGS ? 1 : 0)); + return form; + } + form = makeArgumentCombinationForm(foldPos, combinerType, argPositions, true, dropResult); + return putInCache(key, form); + } + LambdaForm permuteArgumentsForm(int skip, int[] reorder) { assert(skip == 1); // skip only the leading MH argument, names[0] int length = lambdaForm.names.length; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index cec799ec1a3..86685b605de 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -3943,6 +3943,33 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); return rtype; } + private static Class foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType, int ... argPos) { + int foldArgs = combinerType.parameterCount(); + if (argPos.length != foldArgs) { + throw newIllegalArgumentException("combiner and argument map must be equal size", combinerType, argPos.length); + } + Class rtype = combinerType.returnType(); + int foldVals = rtype == void.class ? 0 : 1; + boolean ok = true; + for (int i = 0; i < foldArgs; i++) { + int arg = argPos[i]; + if (arg < 0 || arg > targetType.parameterCount()) { + throw newIllegalArgumentException("arg outside of target parameterRange", targetType, arg); + } + if (combinerType.parameterType(i) != targetType.parameterType(arg)) { + throw newIllegalArgumentException("target argument type at position " + arg + + " must match combiner argument type at index " + i + ": " + targetType + + " -> " + combinerType + ", map: " + Arrays.toString(argPos)); + } + } + if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos)) { + ok = false; + } + if (!ok) + throw misMatchedTypes("target and combiner types", targetType, combinerType); + return rtype; + } + /** * Makes a method handle which adapts a target method handle, * by guarding it with a test, a boolean-valued method handle. @@ -4949,6 +4976,27 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); return result; } + /** + * As {@see foldArguments(MethodHandle, int, MethodHandle)}, but with the + * added capability of selecting the arguments from the targets parameters + * to call the combiner with. This allows us to avoid some simple cases of + * permutations and padding the combiner with dropArguments to select the + * right argument, which may ultimately produce fewer intermediaries. + */ + static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner, int ... argPositions) { + MethodType targetType = target.type(); + MethodType combinerType = combiner.type(); + Class rtype = foldArgumentChecks(pos, targetType, combinerType, argPositions); + BoundMethodHandle result = target.rebind(); + boolean dropResult = rtype == void.class; + LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType(), argPositions); + MethodType newType = targetType; + if (!dropResult) { + newType = newType.dropParameterTypes(pos, pos + 1); + } + result = result.copyWithExtendL(newType, lform, combiner); + return result; + } private static void checkLoop0(MethodHandle[][] clauses) { if (clauses == null || clauses.length == 0) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index ed56faae579..4b336f4c6b1 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -563,9 +563,8 @@ public final class StringConcatFactory { } if ((lookup.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) { - throw new StringConcatException(String.format( - "Invalid caller: %s", - lookup.lookupClass().getName())); + throw new StringConcatException("Invalid caller: " + + lookup.lookupClass().getName()); } int cCount = 0; @@ -1494,51 +1493,41 @@ public final class StringConcatFactory { // Drop all remaining parameter types, leave only helper arguments: MethodHandle mh; - mh = MethodHandles.dropArguments(NEW_STRING, 2, ptypes); - mh = MethodHandles.dropArguments(mh, 0, int.class); + mh = MethodHandles.dropArguments(NEW_STRING, 3, ptypes); - // Safety: check that remaining index is zero -- that would mean the storage is completely - // overwritten, and no leakage of uninitialized data occurred. - mh = MethodHandles.filterArgument(mh, 0, CHECK_INDEX); - - // Mix in prependers. This happens when (int, byte[], byte) = (index, storage, coder) is already + // Mix in prependers. This happens when (byte[], int, byte) = (storage, index, coder) is already // known from the combinators below. We are assembling the string backwards, so "index" is the // *ending* index. for (RecipeElement el : recipe.getElements()) { - MethodHandle prepender; + // Do the prepend, and put "new" index at index 1 + mh = MethodHandles.dropArguments(mh, 2, int.class); switch (el.getTag()) { - case TAG_CONST: + case TAG_CONST: { Object cnst = el.getValue(); - prepender = MethodHandles.insertArguments(prepender(cnst.getClass()), 3, cnst); + MethodHandle prepender = MethodHandles.insertArguments(prepender(cnst.getClass()), 3, cnst); + mh = MethodHandles.foldArguments(mh, 1, prepender, + 2, 0, 3 // index, storage, coder + ); break; - case TAG_ARG: + } + case TAG_ARG: { int pos = el.getArgPos(); - prepender = selectArgument(prepender(ptypes[pos]), 3, ptypes, pos); + MethodHandle prepender = prepender(ptypes[pos]); + mh = MethodHandles.foldArguments(mh, 1, prepender, + 2, 0, 3, // index, storage, coder + 4 + pos // selected argument + ); break; + } default: throw new StringConcatException("Unhandled tag: " + el.getTag()); } - - // Remove "old" index from arguments - mh = MethodHandles.dropArguments(mh, 1, int.class); - - // Do the prepend, and put "new" index at index 0 - mh = MethodHandles.foldArguments(mh, prepender); } - // Prepare the argument list for prepending. The tree below would instantiate - // the storage byte[] into argument 0, so we need to swap "storage" and "index". - // The index at this point equals to "size", and resides at argument 1. - { - MethodType nmt = mh.type() - .changeParameterType(0, byte[].class) - .changeParameterType(1, int.class); - mh = MethodHandles.permuteArguments(mh, nmt, swap10(nmt.parameterCount())); - } - - // Fold in byte[] instantiation at argument 0. - MethodHandle combiner = MethodHandles.dropArguments(NEW_ARRAY, 2, ptypes); - mh = MethodHandles.foldArguments(mh, combiner); + // Fold in byte[] instantiation at argument 0 + mh = MethodHandles.foldArguments(mh, 0, NEW_ARRAY, + 1, 2 // index, coder + ); // Start combining length and coder mixers. // @@ -1567,12 +1556,8 @@ public final class StringConcatFactory { int ac = el.getArgPos(); Class argClass = ptypes[ac]; - MethodHandle lm = selectArgument(lengthMixer(argClass), 1, ptypes, ac); - lm = MethodHandles.dropArguments(lm, 0, byte.class); // (*) - lm = MethodHandles.dropArguments(lm, 2, byte.class); - - MethodHandle cm = selectArgument(coderMixer(argClass), 1, ptypes, ac); - cm = MethodHandles.dropArguments(cm, 0, int.class); // (**) + MethodHandle lm = lengthMixer(argClass); + MethodHandle cm = coderMixer(argClass); // Read this bottom up: @@ -1580,12 +1565,18 @@ public final class StringConcatFactory { mh = MethodHandles.dropArguments(mh, 2, int.class, byte.class); // 3. Compute "new-index", producing ("new-index", "new-coder", "old-index", "old-coder", ) - // Length mixer ignores both "new-coder" and "old-coder" due to dropArguments above (*) - mh = MethodHandles.foldArguments(mh, lm); + // Length mixer needs old index, plus the appropriate argument + mh = MethodHandles.foldArguments(mh, 0, lm, + 2, // old-index + 4 + ac // selected argument + ); // 2. Compute "new-coder", producing ("new-coder", "old-index", "old-coder", ) - // Coder mixer ignores the "old-index" arg due to dropArguments above (**) - mh = MethodHandles.foldArguments(mh, cm); + // Coder mixer needs old coder, plus the appropriate argument. + mh = MethodHandles.foldArguments(mh, 0, cm, + 2, // old-coder + 3 + ac // selected argument + ); // 1. The mh shape here is ("old-index", "old-coder", ) break; @@ -1606,41 +1597,11 @@ public final class StringConcatFactory { return mh; } - private static int[] swap10(int count) { - int[] perm = new int[count]; - perm[0] = 1; - perm[1] = 0; - for (int i = 2; i < count; i++) { - perm[i] = i; - } - return perm; - } - - // Adapts: (...prefix..., parameter[pos])R -> (...prefix..., ...parameters...)R - private static MethodHandle selectArgument(MethodHandle mh, int prefix, Class[] ptypes, int pos) { - if (pos == 0) { - return MethodHandles.dropArguments(mh, prefix + 1, Arrays.copyOfRange(ptypes, 1, ptypes.length)); - } else if (pos == ptypes.length - 1) { - return MethodHandles.dropArguments(mh, prefix, Arrays.copyOf(ptypes, ptypes.length - 1)); - } else { // 0 < pos < ptypes.size() - 1 - MethodHandle t = MethodHandles.dropArguments(mh, prefix, Arrays.copyOf(ptypes, pos)); - return MethodHandles.dropArguments(t, prefix + 1 + pos, Arrays.copyOfRange(ptypes, pos + 1, ptypes.length)); - } - } - @ForceInline private static byte[] newArray(int length, byte coder) { return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, length << coder); } - @ForceInline - private static int checkIndex(int index) { - if (index != 0) { - throw new IllegalStateException("Storage is not completely initialized, " + index + " bytes left"); - } - return index; - } - private static MethodHandle prepender(Class cl) { return PREPENDERS.computeIfAbsent(cl, PREPEND); } @@ -1678,7 +1639,6 @@ public final class StringConcatFactory { }; private static final MethodHandle NEW_STRING; - private static final MethodHandle CHECK_INDEX; private static final MethodHandle NEW_ARRAY; private static final ConcurrentMap, MethodHandle> PREPENDERS; private static final ConcurrentMap, MethodHandle> LENGTH_MIXERS; @@ -1699,9 +1659,8 @@ public final class StringConcatFactory { LENGTH_MIXERS = new ConcurrentHashMap<>(); CODER_MIXERS = new ConcurrentHashMap<>(); - NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, byte.class); + NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, int.class, byte.class); NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "newArray", byte[].class, int.class, byte.class); - CHECK_INDEX = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "checkIndex", int.class, int.class); } } From 13eeb8335fc62348c20255f9b71d5ab3daaa40ff Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Mon, 12 Sep 2016 18:25:49 +0530 Subject: [PATCH 29/38] 8165772: fix for 8165595 results in failure of jdk/test/tools/launcher/VersionCheck.java Reviewed-by: alanb, jlaskey --- make/CreateJmods.gmk | 8 -------- 1 file changed, 8 deletions(-) diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index d8471a09aea..c452f1b9cf1 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -82,14 +82,6 @@ ifeq ($(MODULE), java.base) endif endif -ifeq ($(MODULE), jdk.scripting.nashorn.shell) - JMOD_FLAGS += --main-class jdk.nashorn.tools.jjs.Main -endif - -ifeq ($(MODULE), jdk.scripting.nashorn) - JMOD_FLAGS += --main-class jdk.nashorn.tools.Shell -endif - # Changes to the jmod tool itself should also trigger a rebuild of all jmods. # The variable JMOD_CMD could contain an environment variable assignment before # the actual command. Filter that out using wildcard before adding to DEPS. From 253489ea9a360c2a1c952902ef1aa7fd73299178 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Mon, 12 Sep 2016 18:27:33 +0530 Subject: [PATCH 30/38] 8165772: fix for 8165595 results in failure of jdk/test/tools/launcher/VersionCheck.java Reviewed-by: alanb, jlaskey --- jdk/test/ProblemList.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 14ce0b92332..83515fad418 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -314,8 +314,6 @@ tools/launcher/FXLauncherTest.java 8068049 linux-al tools/pack200/Pack200Props.java 8155857 generic-all -tools/launcher/VersionCheck.java 8165772 generic-all - ############################################################################ # jdk_jdi From 2ac4d6a7d3b0d4c0e179ed00883b838bfcb12166 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 12 Sep 2016 17:45:55 +0200 Subject: [PATCH 31/38] 8165723: JarFile::isMultiRelease() method returns false when it should return true Reviewed-by: alanb --- .../share/classes/java/util/jar/JarFile.java | 31 ++++++++++---- .../jar/JarFile/mrjar/MultiReleaseJarAPI.java | 42 +++++++++++++++++-- .../util/jar/CreateMultiReleaseTestJars.java | 40 ++++++++---------- 3 files changed, 80 insertions(+), 33 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index 2c4500d169b..081fefd58ab 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -836,18 +836,25 @@ class JarFile extends ZipFile { private static final byte[] CLASSPATH_CHARS = {'C','L','A','S','S','-','P','A','T','H', ':', ' '}; - // The bad character shift for "class-path:" + // The bad character shift for "class-path: " private static final byte[] CLASSPATH_LASTOCC; + // The good suffix shift for "class-path: " + private static final byte[] CLASSPATH_OPTOSFT; + private static final byte[] MULTIRELEASE_CHARS = {'M','U','L','T','I','-','R','E','L','E', 'A', 'S', 'E', ':', ' ', 'T', 'R', 'U', 'E'}; - // The bad character shift for "multi-release: " + // The bad character shift for "multi-release: true" private static final byte[] MULTIRELEASE_LASTOCC; + // The good suffix shift for "multi-release: true" + private static final byte[] MULTIRELEASE_OPTOSFT; + static { CLASSPATH_LASTOCC = new byte[64]; + CLASSPATH_OPTOSFT = new byte[12]; CLASSPATH_LASTOCC[(int)'C' - 32] = 1; CLASSPATH_LASTOCC[(int)'L' - 32] = 2; CLASSPATH_LASTOCC[(int)'S' - 32] = 5; @@ -858,8 +865,13 @@ class JarFile extends ZipFile { CLASSPATH_LASTOCC[(int)'H' - 32] = 10; CLASSPATH_LASTOCC[(int)':' - 32] = 11; CLASSPATH_LASTOCC[(int)' ' - 32] = 12; + for (int i = 0; i < 11; i++) { + CLASSPATH_OPTOSFT[i] = 12; + } + CLASSPATH_OPTOSFT[11] = 1; MULTIRELEASE_LASTOCC = new byte[64]; + MULTIRELEASE_OPTOSFT = new byte[19]; MULTIRELEASE_LASTOCC[(int)'M' - 32] = 1; MULTIRELEASE_LASTOCC[(int)'I' - 32] = 5; MULTIRELEASE_LASTOCC[(int)'-' - 32] = 6; @@ -872,6 +884,11 @@ class JarFile extends ZipFile { MULTIRELEASE_LASTOCC[(int)'R' - 32] = 17; MULTIRELEASE_LASTOCC[(int)'U' - 32] = 18; MULTIRELEASE_LASTOCC[(int)'E' - 32] = 19; + for (int i = 0; i < 17; i++) { + MULTIRELEASE_OPTOSFT[i] = 19; + } + MULTIRELEASE_OPTOSFT[17] = 6; + MULTIRELEASE_OPTOSFT[18] = 1; } private JarEntry getManEntry() { @@ -913,7 +930,7 @@ class JarFile extends ZipFile { * Since there are no repeated substring in our search strings, * the good suffix shifts can be replaced with a comparison. */ - private int match(byte[] src, byte[] b, byte[] lastOcc) { + private int match(byte[] src, byte[] b, byte[] lastOcc, byte[] optoSft) { int len = src.length; int last = b.length - len; int i = 0; @@ -926,9 +943,8 @@ class JarFile extends ZipFile { if (c != src[j]) { // no match - int goodShift = (j < len - 1) ? len : 1; int badShift = lastOcc[c - 32]; - i += Math.max(j + 1 - badShift, goodShift); + i += Math.max(j + 1 - badShift, optoSft[j]); continue next; } } else { @@ -958,10 +974,11 @@ class JarFile extends ZipFile { if (manEntry != null) { byte[] b = getBytes(manEntry); hasClassPathAttribute = match(CLASSPATH_CHARS, b, - CLASSPATH_LASTOCC) != -1; + CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT) != -1; // is this a multi-release jar file if (MULTI_RELEASE_ENABLED) { - int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC); + int i = match(MULTIRELEASE_CHARS, b, MULTIRELEASE_LASTOCC, + MULTIRELEASE_OPTOSFT); if (i != -1) { i += MULTIRELEASE_CHARS.length; if (i < b.length) { diff --git a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java index 4ea94150844..b620e2316ee 100644 --- a/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java +++ b/jdk/test/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java @@ -23,23 +23,29 @@ /* * @test - * @bug 8132734 8144062 + * @bug 8132734 8144062 8165723 * @summary Test the extended API and the aliasing additions in JarFile that * support multi-release jar files - * @library /lib/testlibrary/java/util/jar + * @library /lib/testlibrary/java/util/jar /lib/testlibrary/ * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @build jdk.testlibrary.RandomFactory * @run testng MultiReleaseJarAPI */ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; +import java.util.Map; +import java.util.Random; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import jdk.testlibrary.RandomFactory; + import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -48,12 +54,15 @@ import org.testng.annotations.Test; public class MultiReleaseJarAPI { + private static final Random RANDOM = RandomFactory.getRandom(); + String userdir = System.getProperty("user.dir","."); CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); File unversioned = new File(userdir, "unversioned.jar"); File multirelease = new File(userdir, "multi-release.jar"); File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + @BeforeClass public void initialize() throws Exception { creator.compileEntries(); @@ -99,10 +108,35 @@ public class MultiReleaseJarAPI { testCustomMultiReleaseValue("true\r ", false); testCustomMultiReleaseValue("true\n true", false); testCustomMultiReleaseValue("true\r\n true", false); + + // generate "random" Strings to use as extra attributes, and + // verify that Multi-Release: true is always properly matched + for (int i = 0; i < 100; i++) { + byte[] keyBytes = new byte[RANDOM.nextInt(70) + 1]; + Arrays.fill(keyBytes, (byte)('a' + RANDOM.nextInt(24))); + byte[] valueBytes = new byte[RANDOM.nextInt(70) + 1]; + Arrays.fill(valueBytes, (byte)('a' + RANDOM.nextInt(24))); + + String key = new String(keyBytes, StandardCharsets.UTF_8); + String value = new String(valueBytes, StandardCharsets.UTF_8); + // test that Multi-Release: true anywhere in the manifest always + // return true + testCustomMultiReleaseValue("true", Map.of(key, value), true); + + // test that we don't get any false positives + testCustomMultiReleaseValue("false", Map.of(key, value), false); + } } - private void testCustomMultiReleaseValue(String value, boolean expected) throws Exception { - creator.buildCustomMultiReleaseJar("custom-mr.jar", value); + private void testCustomMultiReleaseValue(String value, boolean expected) + throws Exception { + testCustomMultiReleaseValue(value, Map.of(), expected); + } + + private void testCustomMultiReleaseValue(String value, + Map extraAttributes, boolean expected) + throws Exception { + creator.buildCustomMultiReleaseJar("custom-mr.jar", value, extraAttributes); File custom = new File(userdir, "custom-mr.jar"); try (JarFile jf = new JarFile(custom, true, ZipFile.OPEN_READ, Runtime.version())) { Assert.assertEquals(jf.isMultiRelease(), expected); diff --git a/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java b/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java index 672b7c2d205..c07c387faf9 100644 --- a/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java +++ b/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java @@ -88,12 +88,28 @@ public class CreateMultiReleaseTestJars { } public void buildMultiReleaseJar() throws IOException { - buildCustomMultiReleaseJar("multi-release.jar", "true"); + JarBuilder jb = customMultiReleaseJar("multi-release.jar", "true"); + addEntries(jb); + jb.build(); } - public void buildCustomMultiReleaseJar(String filename, String multiReleaseValue) throws IOException { + private JarBuilder customMultiReleaseJar(String filename, String multiReleaseValue) + throws IOException { JarBuilder jb = new JarBuilder(filename); jb.addAttribute("Multi-Release", multiReleaseValue); + return jb; + } + + public void buildCustomMultiReleaseJar(String filename, String multiReleaseValue, + Map extraAttributes) throws IOException { + JarBuilder jb = new JarBuilder(filename); + extraAttributes.entrySet() + .forEach(entry -> jb.addAttribute(entry.getKey(), entry.getValue())); + jb.addAttribute("Multi-Release", multiReleaseValue); + jb.build(); + } + + private void addEntries(JarBuilder jb) { jb.addEntry("README", readme8.getBytes()); jb.addEntry("version/Main.java", main.getBytes()); jb.addEntry("version/Main.class", rootClasses.get("version.Main")); @@ -107,26 +123,6 @@ public class CreateMultiReleaseTestJars { jb.addEntry("META-INF/versions/10/README", readme10.getBytes()); jb.addEntry("META-INF/versions/10/version/Version.java", java10.getBytes()); jb.addEntry("META-INF/versions/10/version/Version.class", version10Classes.get("version.Version")); - jb.build(); - } - - public void buildShortMultiReleaseJar() throws IOException { - JarBuilder jb = new JarBuilder("short-multi-release.jar"); - jb.addAttribute("Multi-Release", "true"); - jb.addEntry("README", readme8.getBytes()); - jb.addEntry("version/Main.java", main.getBytes()); - jb.addEntry("version/Main.class", rootClasses.get("version.Main")); - jb.addEntry("version/Version.java", java8.getBytes()); - jb.addEntry("version/Version.class", rootClasses.get("version.Version")); - jb.addEntry("META-INF/versions/9/README", readme9.getBytes()); - jb.addEntry("META-INF/versions/9/version/Version.java", java9.getBytes()); - jb.addEntry("META-INF/versions/9/version/PackagePrivate.java", ppjava9.getBytes()); - // no entry for META-INF/versions/9/version/Version.class - jb.addEntry("META-INF/versions/9/version/PackagePrivate.class", version9Classes.get("version.PackagePrivate")); - jb.addEntry("META-INF/versions/10/README", readme10.getBytes()); - jb.addEntry("META-INF/versions/10/version/Version.java", java10.getBytes()); - jb.addEntry("META-INF/versions/10/version/Version.class", version10Classes.get("version.Version")); - jb.build(); } public void buildSignedMultiReleaseJar() throws Exception { From ff4657f6a5335c10fe0491a178bdeee6f0a8f0f2 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Mon, 12 Sep 2016 09:38:26 -0700 Subject: [PATCH 32/38] 8165605: Thai resources in jdk.localedata cause split package issue with java.base Reviewed-by: mchung, erikj --- make/CompileJavaModules.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 9023aba0acc..75e7cc6a0bb 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -458,7 +458,7 @@ sun.charsets_COPY := .dat jdk.localedata_COPY := _dict _th # Exclude BreakIterator classes that are just used in compile process to generate # data files and shouldn't go in the product -jdk.localedata_EXCLUDE_FILES += sun/text/resources/th/BreakIteratorRules_th.java +jdk.localedata_EXCLUDE_FILES += sun/text/resources/ext/BreakIteratorRules_th.java ################################################################################ # Setup the compilation for the module From 4c95fceb14dd973f2c76195a3484be3272e22ddc Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Mon, 12 Sep 2016 09:38:32 -0700 Subject: [PATCH 33/38] 8165605: Thai resources in jdk.localedata cause split package issue with java.base Reviewed-by: mchung, erikj --- jdk/make/gendata/GendataBreakIterator.gmk | 2 +- .../resources/BreakIteratorRulesProvider.java | 35 ---------- .../util/locale/provider/BreakDictionary.java | 5 +- .../provider/RuleBasedBreakIterator.java | 5 +- .../plugins/IncludeLocalesPlugin.java | 4 +- .../sun/text/resources/{ => ext}/thai_dict | Bin .../plugins/IncludeLocalesPluginTest.java | 63 ++++++++---------- 7 files changed, 38 insertions(+), 76 deletions(-) delete mode 100644 jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorRulesProvider.java rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ => ext}/thai_dict (100%) diff --git a/jdk/make/gendata/GendataBreakIterator.gmk b/jdk/make/gendata/GendataBreakIterator.gmk index a68786a413b..2f7f5dff981 100644 --- a/jdk/make/gendata/GendataBreakIterator.gmk +++ b/jdk/make/gendata/GendataBreakIterator.gmk @@ -81,7 +81,7 @@ UNICODEDATA := $(JDK_TOPDIR)/make/data/unicodedata/UnicodeData.txt # output BASE_DATA_PKG_DIR := $(JDK_OUTPUTDIR)/modules/java.base/sun/text/resources -LD_DATA_PKG_DIR := $(JDK_OUTPUTDIR)/modules/jdk.localedata/sun/text/resources +LD_DATA_PKG_DIR := $(JDK_OUTPUTDIR)/modules/jdk.localedata/sun/text/resources/ext BIFILES := $(BASE_DATA_PKG_DIR)/CharacterBreakIteratorData \ $(BASE_DATA_PKG_DIR)/WordBreakIteratorData \ $(BASE_DATA_PKG_DIR)/LineBreakIteratorData \ diff --git a/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorRulesProvider.java b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorRulesProvider.java deleted file mode 100644 index 4bbb1cec212..00000000000 --- a/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorRulesProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.text.resources; - -import java.util.spi.ResourceBundleProvider; - -/** - * An interface for the internal locale data provider for which {@code ResourceBundle} - * searches. - */ -public interface BreakIteratorRulesProvider extends ResourceBundleProvider { -} diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java index ddb4bb53f2c..4be1363b58f 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java @@ -149,7 +149,10 @@ class BreakDictionary { BufferedInputStream in; try { PrivilegedExceptionAction pa = () -> { - InputStream is = module.getResourceAsStream("sun/text/resources/" + dictionaryName); + String pathName = "jdk.localedata".equals(module.getName()) ? + "sun/text/resources/ext/" : + "sun/text/resources/"; + InputStream is = module.getResourceAsStream(pathName + dictionaryName); if (is == null) { // Try to load the file with "java.base" module instance. Assumption // here is that the fall back data files to be read should reside in diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java index 7c00ee052f1..ebf6ba1956e 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java @@ -444,7 +444,10 @@ class RuleBasedBreakIterator extends BreakIterator { BufferedInputStream is; try { PrivilegedExceptionAction pa = () -> { - InputStream in = module.getResourceAsStream("sun/text/resources/" + datafile); + String pathName = "jdk.localedata".equals(module.getName()) ? + "sun/text/resources/ext/" : + "sun/text/resources/"; + InputStream in = module.getResourceAsStream(pathName + datafile); if (in == null) { // Try to load the file with "java.base" module instance. Assumption // here is that the fall back data files to be read should reside in diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java index b6e29bfccdc..a0b93962a8d 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java @@ -264,8 +264,8 @@ public final class IncludeLocalesPlugin implements Plugin, ResourcePrevisitor { // Add Thai BreakIterator related data files if (tag.equals("th")) { - files.add(".+sun/text/resources/thai_dict"); - files.add(".+sun/text/resources/[^_]+BreakIteratorData_th"); + files.add(".+sun/text/resources/ext/thai_dict"); + files.add(".+sun/text/resources/ext/[^_]+BreakIteratorData_th"); } // Add Taiwan resource bundles for Hong Kong diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/thai_dict b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/thai_dict similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/thai_dict rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/thai_dict diff --git a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java index deb65ca13f8..4298e48d84d 100644 --- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java +++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java @@ -126,11 +126,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_es_419.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_es_AR.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", @@ -165,11 +164,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_zh.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class", @@ -206,11 +204,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_150.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_AT.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", @@ -235,11 +232,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/util/resources/cldr/ext/CalendarData_kok_IN.class", "/jdk.localedata/sun/util/resources/cldr/ext/CalendarData_pa_Guru_IN.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", @@ -261,11 +257,10 @@ public class IncludeLocalesPluginTest { "--include-locales=th", "jdk.localedata", List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class"), List.of( "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", @@ -290,11 +285,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/text/resources/ext/FormatData_zh_TW.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", @@ -318,11 +312,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/text/resources/ext/FormatData_zh_SG.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", @@ -346,11 +339,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_nb.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_nn.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", @@ -376,11 +368,10 @@ public class IncludeLocalesPluginTest { "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_iw.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ji.class"), List.of( - "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", - "/jdk.localedata/sun/text/resources/thai_dict", - "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", + "/jdk.localedata/sun/text/resources/ext/thai_dict", + "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", - "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class", "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/ext/FormatData_th.class", From 3cb67af31ffc0fa7625ce651e3ec6616ad2cbc54 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 12 Sep 2016 20:12:26 +0200 Subject: [PATCH 34/38] 8165890: [TESTBUG] Compilation issue in MultiReleaseJarTest after 8165723 Reviewed-by: darcy --- .../java/util/jar/CreateMultiReleaseTestJars.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java b/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java index c07c387faf9..504472f1f7e 100644 --- a/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java +++ b/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java @@ -90,6 +90,13 @@ public class CreateMultiReleaseTestJars { public void buildMultiReleaseJar() throws IOException { JarBuilder jb = customMultiReleaseJar("multi-release.jar", "true"); addEntries(jb); + jb.addEntry("META-INF/versions/9/version/Version.class", version9Classes.get("version.Version")); + jb.build(); + } + + public void buildShortMultiReleaseJar() throws IOException { + JarBuilder jb = customMultiReleaseJar("short-multi-release.jar", "true"); + addEntries(jb); jb.build(); } @@ -118,7 +125,6 @@ public class CreateMultiReleaseTestJars { jb.addEntry("META-INF/versions/9/README", readme9.getBytes()); jb.addEntry("META-INF/versions/9/version/Version.java", java9.getBytes()); jb.addEntry("META-INF/versions/9/version/PackagePrivate.java", ppjava9.getBytes()); - jb.addEntry("META-INF/versions/9/version/Version.class", version9Classes.get("version.Version")); jb.addEntry("META-INF/versions/9/version/PackagePrivate.class", version9Classes.get("version.PackagePrivate")); jb.addEntry("META-INF/versions/10/README", readme10.getBytes()); jb.addEntry("META-INF/versions/10/version/Version.java", java10.getBytes()); From d7f3695a9093dcf6599a97f1d66f147628447942 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Mon, 12 Sep 2016 13:07:30 -0700 Subject: [PATCH 35/38] 8164983: Improve CountedCompleter code samples; add corresponding tests Reviewed-by: martin, psandoz, shade --- .../util/concurrent/CountedCompleter.java | 156 ++++++++++-------- .../concurrent/tck/CountedCompleterTest.java | 114 +++++++++++++ 2 files changed, 198 insertions(+), 72 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java index 1218c75de68..0c809df9cf6 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java @@ -120,102 +120,114 @@ import java.lang.invoke.VarHandle; * to complete for some elements than others, either because of * intrinsic variation (for example I/O) or auxiliary effects such as * garbage collection. Because CountedCompleters provide their own - * continuations, other threads need not block waiting to perform - * them. + * continuations, other tasks need not block waiting to perform them. * - *

        For example, here is an initial version of a class that uses - * divide-by-two recursive decomposition to divide work into single - * pieces (leaf tasks). Even when work is split into individual calls, - * tree-based techniques are usually preferable to directly forking - * leaf tasks, because they reduce inter-thread communication and - * improve load balancing. In the recursive case, the second of each - * pair of subtasks to finish triggers completion of its parent + *

        For example, here is an initial version of a utility method that + * uses divide-by-two recursive decomposition to divide work into + * single pieces (leaf tasks). Even when work is split into individual + * calls, tree-based techniques are usually preferable to directly + * forking leaf tasks, because they reduce inter-thread communication + * and improve load balancing. In the recursive case, the second of + * each pair of subtasks to finish triggers completion of their parent * (because no result combination is performed, the default no-op * implementation of method {@code onCompletion} is not overridden). - * A static utility method sets up the base task and invokes it - * (here, implicitly using the {@link ForkJoinPool#commonPool()}). + * The utility method sets up the root task and invokes it (here, + * implicitly using the {@link ForkJoinPool#commonPool()}). It is + * straightforward and reliable (but not optimal) to always set the + * pending count to the number of child tasks and call {@code + * tryComplete()} immediately before returning. * *

         {@code
        - * class MyOperation { void apply(E e) { ... }  }
        - *
        - * class ForEach extends CountedCompleter {
        - *
        - *   public static  void forEach(E[] array, MyOperation op) {
        - *     new ForEach(null, array, op, 0, array.length).invoke();
        - *   }
        - *
        - *   final E[] array; final MyOperation op; final int lo, hi;
        - *   ForEach(CountedCompleter p, E[] array, MyOperation op, int lo, int hi) {
        - *     super(p);
        - *     this.array = array; this.op = op; this.lo = lo; this.hi = hi;
        - *   }
        - *
        - *   public void compute() { // version 1
        - *     if (hi - lo >= 2) {
        - *       int mid = (lo + hi) >>> 1;
        - *       setPendingCount(2); // must set pending count before fork
        - *       new ForEach(this, array, op, mid, hi).fork(); // right child
        - *       new ForEach(this, array, op, lo, mid).fork(); // left child
        + * public static  void forEach(E[] array, Consumer action) {
        + *   class Task extends CountedCompleter {
        + *     final int lo, hi;
        + *     Task(Task parent, int lo, int hi) {
        + *       super(parent); this.lo = lo; this.hi = hi;
        + *     }
        + *
        + *     public void compute() {
        + *       if (hi - lo >= 2) {
        + *         int mid = (lo + hi) >>> 1;
        + *         // must set pending count before fork
        + *         setPendingCount(2);
        + *         new Task(this, mid, hi).fork(); // right child
        + *         new Task(this, lo, mid).fork(); // left child
        + *       }
        + *       else if (hi > lo)
        + *         action.accept(array[lo]);
        + *       tryComplete();
          *     }
        - *     else if (hi > lo)
        - *       op.apply(array[lo]);
        - *     tryComplete();
          *   }
        + *   new Task(null, 0, array.length).invoke();
          * }}
        * * This design can be improved by noticing that in the recursive case, * the task has nothing to do after forking its right task, so can * directly invoke its left task before returning. (This is an analog - * of tail recursion removal.) Also, because the task returns upon - * executing its left task (rather than falling through to invoke - * {@code tryComplete}) the pending count is set to one: + * of tail recursion removal.) Also, when the last action in a task + * is to fork or invoke a subtask (a "tail call"), the call to {@code + * tryComplete()} can be optimized away, at the cost of making the + * pending count look "off by one". * *
         {@code
        - * class ForEach ... {
        - *   ...
        - *   public void compute() { // version 2
        - *     if (hi - lo >= 2) {
        - *       int mid = (lo + hi) >>> 1;
        - *       setPendingCount(1); // only one pending
        - *       new ForEach(this, array, op, mid, hi).fork(); // right child
        - *       new ForEach(this, array, op, lo, mid).compute(); // direct invoke
        - *     }
        - *     else {
        - *       if (hi > lo)
        - *         op.apply(array[lo]);
        - *       tryComplete();
        - *     }
        - *   }
        - * }}
        + * public void compute() { + * if (hi - lo >= 2) { + * int mid = (lo + hi) >>> 1; + * setPendingCount(1); // looks off by one, but correct! + * new Task(this, mid, hi).fork(); // right child + * new Task(this, lo, mid).compute(); // direct invoke + * } else { + * if (hi > lo) + * action.accept(array[lo]); + * tryComplete(); + * } + * }} * * As a further optimization, notice that the left task need not even exist. - * Instead of creating a new one, we can iterate using the original task, + * Instead of creating a new one, we can continue using the original task, * and add a pending count for each fork. Additionally, because no task * in this tree implements an {@link #onCompletion(CountedCompleter)} method, - * {@code tryComplete()} can be replaced with {@link #propagateCompletion}. + * {@code tryComplete} can be replaced with {@link #propagateCompletion}. * *
         {@code
        - * class ForEach ... {
        - *   ...
        - *   public void compute() { // version 3
        - *     int l = lo, h = hi;
        - *     while (h - l >= 2) {
        - *       int mid = (l + h) >>> 1;
        - *       addToPendingCount(1);
        - *       new ForEach(this, array, op, mid, h).fork(); // right child
        - *       h = mid;
        + *     public void compute() {
        + *       int n = hi - lo;
        + *       for (; n >= 2; n /= 2) {
        + *         addToPendingCount(1);
        + *         new Task(this, lo + n/2, lo + n).fork();
        + *       }
        + *       if (n > 0)
        + *         action.accept(array[lo]);
        + *       propagateCompletion();
        + *     }}
        + * + * When pending counts can be precomputed, they can be established in + * the constructor: + * + *
         {@code
        + * public static  void forEach(E[] array, Consumer action) {
        + *   class Task extends CountedCompleter {
        + *     final int lo, hi;
        + *     Task(Task parent, int lo, int hi) {
        + *       super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo));
        + *       this.lo = lo; this.hi = hi;
        + *     }
        + *
        + *     public void compute() {
        + *       for (int n = hi - lo; n >= 2; n /= 2)
        + *         new Task(this, lo + n/2, lo + n).fork();
        + *       action.accept(array[lo]);
        + *       propagateCompletion();
          *     }
        - *     if (h > l)
        - *       op.apply(array[l]);
        - *     propagateCompletion();
          *   }
        + *   if (array.length > 0)
        + *     new Task(null, 0, array.length).invoke();
          * }}
        * - * Additional optimizations of such classes might entail precomputing - * pending counts so that they can be established in constructors, - * specializing classes for leaf steps, subdividing by say, four, - * instead of two per iteration, and using an adaptive threshold - * instead of always subdividing down to single elements. + * Additional optimizations of such classes might entail specializing + * classes for leaf steps, subdividing by say, four, instead of two + * per iteration, and using an adaptive threshold instead of always + * subdividing down to single elements. * *

        Searching. A tree of CountedCompleters can search for a * value or property in different parts of a data structure, and diff --git a/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java b/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java index 8be66850920..88ff1f33a99 100644 --- a/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java +++ b/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java @@ -40,9 +40,12 @@ import java.util.concurrent.CountedCompleter; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import junit.framework.Test; import junit.framework.TestSuite; @@ -1869,4 +1872,115 @@ public class CountedCompleterTest extends JSR166TestCase { testInvokeOnPool(singletonPool(), a); } + /** CountedCompleter class javadoc code sample, version 1. */ + public static void forEach1(E[] array, Consumer action) { + class Task extends CountedCompleter { + final int lo, hi; + Task(Task parent, int lo, int hi) { + super(parent); this.lo = lo; this.hi = hi; + } + + public void compute() { + if (hi - lo >= 2) { + int mid = (lo + hi) >>> 1; + // must set pending count before fork + setPendingCount(2); + new Task(this, mid, hi).fork(); // right child + new Task(this, lo, mid).fork(); // left child + } + else if (hi > lo) + action.accept(array[lo]); + tryComplete(); + } + } + new Task(null, 0, array.length).invoke(); + } + + /** CountedCompleter class javadoc code sample, version 2. */ + public static void forEach2(E[] array, Consumer action) { + class Task extends CountedCompleter { + final int lo, hi; + Task(Task parent, int lo, int hi) { + super(parent); this.lo = lo; this.hi = hi; + } + + public void compute() { + if (hi - lo >= 2) { + int mid = (lo + hi) >>> 1; + setPendingCount(1); // looks off by one, but correct! + new Task(this, mid, hi).fork(); // right child + new Task(this, lo, mid).compute(); // direct invoke + } else { + if (hi > lo) + action.accept(array[lo]); + tryComplete(); + } + } + } + new Task(null, 0, array.length).invoke(); + } + + /** CountedCompleter class javadoc code sample, version 3. */ + public static void forEach3(E[] array, Consumer action) { + class Task extends CountedCompleter { + final int lo, hi; + Task(Task parent, int lo, int hi) { + super(parent); this.lo = lo; this.hi = hi; + } + + public void compute() { + int n = hi - lo; + for (; n >= 2; n /= 2) { + addToPendingCount(1); + new Task(this, lo + n/2, lo + n).fork(); + } + if (n > 0) + action.accept(array[lo]); + propagateCompletion(); + } + } + new Task(null, 0, array.length).invoke(); + } + + /** CountedCompleter class javadoc code sample, version 4. */ + public static void forEach4(E[] array, Consumer action) { + class Task extends CountedCompleter { + final int lo, hi; + Task(Task parent, int lo, int hi) { + super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo)); + this.lo = lo; this.hi = hi; + } + + public void compute() { + for (int n = hi - lo; n >= 2; n /= 2) + new Task(this, lo + n/2, lo + n).fork(); + action.accept(array[lo]); + propagateCompletion(); + } + } + if (array.length > 0) + new Task(null, 0, array.length).invoke(); + } + + void testRecursiveDecomposition( + BiConsumer> action) { + int n = ThreadLocalRandom.current().nextInt(8); + Integer[] a = new Integer[n]; + for (int i = 0; i < n; i++) a[i] = i + 1; + AtomicInteger ai = new AtomicInteger(0); + action.accept(a, (x) -> ai.addAndGet(x)); + assertEquals(n * (n + 1) / 2, ai.get()); + } + + /** + * Variants of divide-by-two recursive decomposition into leaf tasks, + * as described in the CountedCompleter class javadoc code samples + */ + public void testRecursiveDecomposition() { + testRecursiveDecomposition(CountedCompleterTest::forEach1); + testRecursiveDecomposition(CountedCompleterTest::forEach2); + testRecursiveDecomposition(CountedCompleterTest::forEach3); + testRecursiveDecomposition(CountedCompleterTest::forEach4); + } + } From 56cff174b69ca9621bdc9f50c21e47ccc60e52cf Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Mon, 12 Sep 2016 13:11:38 -0700 Subject: [PATCH 36/38] 8139237: java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java fails intermittently Reviewed-by: martin, psandoz, shade --- .../ThreadPoolExecutor/ConfigChanges.java | 104 ++++++++++-------- 1 file changed, 61 insertions(+), 43 deletions(-) diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java index a7ff015bc77..71862dc8935 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java @@ -28,13 +28,13 @@ * @library /lib/testlibrary/ * @build jdk.testlibrary.RandomFactory * @run main/othervm ConfigChanges - * @key randomness intermittent + * @key randomness * @author Martin Buchholz */ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import java.security.Permission; import java.util.Random; @@ -44,7 +44,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicInteger; import jdk.testlibrary.RandomFactory; public class ConfigChanges { @@ -95,10 +94,10 @@ public class ConfigChanges { check(tpe.getQueue().isEmpty()); check(tpe.isTerminated()); check(! tpe.isTerminating()); - equal(tpe.getActiveCount(), 0); - equal(tpe.getPoolSize(), 0); + equal(0, tpe.getActiveCount()); + equal(0, tpe.getPoolSize()); equal(tpe.getTaskCount(), tpe.getCompletedTaskCount()); - check(tpe.awaitTermination(0L, SECONDS)); + check(tpe.awaitTermination(0L, MINUTES)); } catch (Throwable t) { unexpected(t); } } @@ -110,6 +109,21 @@ public class ConfigChanges { static volatile Runnable runnableDuJour; + static void awaitIdleness(ThreadPoolExecutor tpe, long taskCount) { + restart: for (;;) { + // check twice to make chance of race vanishingly small + for (int i = 0; i < 2; i++) { + if (tpe.getQueue().size() != 0 || + tpe.getActiveCount() != 0 || + tpe.getCompletedTaskCount() != taskCount) { + Thread.yield(); + continue restart; + } + } + return; + } + } + private static void realMain(String[] args) throws Throwable { if (rnd.nextBoolean()) System.setSecurityManager(new PermissiveSecurityManger()); @@ -137,8 +151,9 @@ public class ConfigChanges { if (prestart) { tpe.prestartAllCoreThreads(); - equal(tg.activeCount(), n); - equal(tg.activeCount(), tpe.getCorePoolSize()); + equal(n, tg.activeCount()); + equal(n, tpe.getCorePoolSize()); + equal(n, tpe.getLargestPoolSize()); } final Runnable runRunnableDuJour = @@ -153,7 +168,7 @@ public class ConfigChanges { tpe.execute(runRunnableDuJour); // Wait for prestarted threads to dequeue their initial tasks. while (! tpe.getQueue().isEmpty()) - Thread.sleep(10); + Thread.sleep(1); for (int i = 0; i < 5*n; i++) tpe.execute(runRunnableDuJour); } else { @@ -163,73 +178,76 @@ public class ConfigChanges { //report("submitted", tpe); pumpedUp.await(); - equal(tg.activeCount(), 3*n); - equal(tg.activeCount(), tpe.getMaximumPoolSize()); - equal(tpe.getCorePoolSize(), n); + equal(3*n, tg.activeCount()); + equal(3*n, tpe.getMaximumPoolSize()); + equal(3*n, tpe.getLargestPoolSize()); + equal(n, tpe.getCorePoolSize()); + equal(3*n, tpe.getActiveCount()); + equal(6L*n, tpe.getTaskCount()); + equal(0L, tpe.getCompletedTaskCount()); + //report("pumped up", tpe); - equal(tpe.getMaximumPoolSize(), 3*n); tpe.setMaximumPoolSize(4*n); - equal(tpe.getMaximumPoolSize(), 4*n); + equal(4*n, tpe.getMaximumPoolSize()); //report("pumped up2", tpe); final CyclicBarrier pumpedUp2 = new CyclicBarrier(n + 1); runnableDuJour = waiter(pumpedUp2); for (int i = 0; i < 1*n; i++) tpe.execute(runRunnableDuJour); pumpedUp2.await(); - equal(tg.activeCount(), 4*n); - equal(tg.activeCount(), tpe.getMaximumPoolSize()); - equal(tpe.getCompletedTaskCount(), 0L); + equal(4*n, tg.activeCount()); + equal(4*n, tpe.getMaximumPoolSize()); + equal(4*n, tpe.getLargestPoolSize()); + equal(4*n, tpe.getActiveCount()); + equal(7L*n, tpe.getTaskCount()); + equal(0L, tpe.getCompletedTaskCount()); //report("pumped up2", tpe); runnableDuJour = new Runnable() { public void run() {}}; tpe.setMaximumPoolSize(2*n); - //report("after set", tpe); + //report("after setMaximumPoolSize", tpe); pumpedUp2.await(); pumpedUp.await(); -// while (tg.activeCount() != n && -// tg.activeCount() != n) -// Thread.sleep(10); -// equal(tg.activeCount(), n); -// equal(tg.activeCount(), tpe.getCorePoolSize()); - while (tg.activeCount() != 2*n && tg.activeCount() != 2*n) - Thread.sleep(10); - equal(tg.activeCount(), 2*n); - equal(tg.activeCount(), tpe.getMaximumPoolSize()); + Thread.yield(); + equal(2*n, tg.activeCount()); + equal(2*n, tpe.getMaximumPoolSize()); + equal(4*n, tpe.getLargestPoolSize()); + //report("draining", tpe); + awaitIdleness(tpe, 7L*n); -//report("draining", tpe); - while (tpe.getCompletedTaskCount() < 7*n && - tpe.getCompletedTaskCount() < 7*n) - Thread.sleep(10); + equal(2*n, tg.activeCount()); + equal(2*n, tpe.getMaximumPoolSize()); + equal(4*n, tpe.getLargestPoolSize()); - //equal(tg.activeCount(), n); - //equal(tg.activeCount(), tpe.getCorePoolSize()); - equal(tg.activeCount(), 2*n); - equal(tg.activeCount(), tpe.getMaximumPoolSize()); + equal(7L*n, tpe.getTaskCount()); + equal(7L*n, tpe.getCompletedTaskCount()); + equal(0, tpe.getActiveCount()); - equal(tpe.getTaskCount(), 7L*n); - equal(tpe.getCompletedTaskCount(), 7L*n); - - equal(tpe.getKeepAliveTime(MINUTES), 3L); + equal(3L, tpe.getKeepAliveTime(MINUTES)); + long t0 = System.nanoTime(); tpe.setKeepAliveTime(7L, MILLISECONDS); - equal(tpe.getKeepAliveTime(MILLISECONDS), 7L); + equal(7L, tpe.getKeepAliveTime(MILLISECONDS)); while (tg.activeCount() > n && tg.activeCount() > n) - Thread.sleep(10); - equal(tg.activeCount(), n); + Thread.sleep(4); + equal(n, tg.activeCount()); + check(System.nanoTime() - t0 >= tpe.getKeepAliveTime(NANOSECONDS)); //report("idle", tpe); check(! tpe.allowsCoreThreadTimeOut()); + t0 = System.nanoTime(); tpe.allowCoreThreadTimeOut(true); check(tpe.allowsCoreThreadTimeOut()); while (tg.activeCount() > 0 && tg.activeCount() > 0) - Thread.sleep(10); + Thread.sleep(4); equal(tg.activeCount(), 0); + check(System.nanoTime() - t0 >= tpe.getKeepAliveTime(NANOSECONDS)); //report("idle", tpe); From 60cd28abd7ac0cf61e367eb910ca59f16ce0416a Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Mon, 12 Sep 2016 13:14:49 -0700 Subject: [PATCH 37/38] 8164169: Miscellaneous changes imported from jsr166 CVS 2016-09 Reviewed-by: martin, psandoz, shade --- .../share/classes/java/util/ArrayDeque.java | 2 +- .../classes/java/util/PriorityQueue.java | 4 +- .../util/concurrent/CompletableFuture.java | 2 +- .../java/util/concurrent/CyclicBarrier.java | 2 +- .../classes/java/util/concurrent/Flow.java | 2 +- .../java/util/concurrent/ForkJoinPool.java | 8 +-- .../java/util/concurrent/Semaphore.java | 14 ++-- .../util/concurrent/SubmissionPublisher.java | 5 +- .../util/concurrent/ThreadPoolExecutor.java | 3 + .../util/concurrent/atomic/AtomicInteger.java | 4 +- .../util/concurrent/locks/StampedLock.java | 14 ++-- jdk/test/java/util/PriorityQueue/NoNulls.java | 2 - .../concurrent/BlockingQueue/LoopHelpers.java | 2 - .../BlockingQueue/OfferDrainToLoops.java | 1 - .../ConcurrentHashMap/LoopHelpers.java | 2 - .../ConcurrentQueues/LoopHelpers.java | 2 - .../ConcurrentQueues/OfferRemoveLoops.java | 1 - .../util/concurrent/DelayQueue/Stress.java | 1 - .../concurrent/Exchanger/LoopHelpers.java | 2 - .../LoopHelpers.java | 2 - .../concurrent/FutureTask/LoopHelpers.java | 2 - .../ZeroCorePoolSize.java | 1 - .../ZeroCoreThreads.java | 1 - .../ThreadPoolExecutor/ThreadRestarts.java | 1 - .../ThreadPoolExecutor/TimeOutShrink.java | 1 - .../atomic/AtomicReferenceTest.java | 1 - .../concurrent/forkjoin/SubmissionTest.java | 16 +++-- .../concurrent/locks/Lock/LoopHelpers.java | 2 - .../util/concurrent/locks/Lock/Mutex.java | 1 - .../locks/LockSupport/ParkLoops.java | 1 - .../locks/ReentrantLock/LoopHelpers.java | 2 - .../ReentrantReadWriteLock/LoopHelpers.java | 2 - .../ReadersUnlockAfterWriteUnlock.java | 65 +++++++++++-------- .../tck/AtomicIntegerArray9Test.java | 1 - .../concurrent/tck/AtomicLongArray9Test.java | 1 - .../tck/AtomicReferenceArray9Test.java | 1 - .../concurrent/tck/CompletableFutureTest.java | 1 - .../tck/ConcurrentHashMap8Test.java | 1 - .../tck/CopyOnWriteArrayListTest.java | 1 - .../tck/CopyOnWriteArraySetTest.java | 1 - .../tck/ExecutorCompletionService9Test.java | 1 - .../tck/ExecutorCompletionServiceTest.java | 1 - .../concurrent/tck/ForkJoinPool8Test.java | 20 ++---- .../concurrent/tck/ForkJoinTask8Test.java | 1 - .../util/concurrent/tck/ForkJoinTaskTest.java | 2 - .../util/concurrent/tck/JSR166TestCase.java | 2 +- .../concurrent/tck/RecursiveActionTest.java | 40 ++++-------- .../tck/ScheduledExecutorSubclassTest.java | 1 - .../concurrent/tck/ScheduledExecutorTest.java | 1 - .../util/concurrent/tck/StampedLockTest.java | 1 - .../tck/SubmissionPublisherTest.java | 10 --- .../tck/ThreadPoolExecutorSubclassTest.java | 1 - .../tck/ThreadPoolExecutorTest.java | 1 - 53 files changed, 104 insertions(+), 156 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java index ca3c66b6249..5a9b8312e30 100644 --- a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java +++ b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java @@ -81,8 +81,8 @@ import java.util.function.Consumer; * Java Collections Framework. * * @author Josh Bloch and Doug Lea - * @since 1.6 * @param the type of elements held in this deque + * @since 1.6 */ public class ArrayDeque extends AbstractCollection implements Deque, Cloneable, Serializable diff --git a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java index 440cbbe2c67..89bc2141e3d 100644 --- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java +++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java @@ -749,11 +749,11 @@ public class PriorityQueue extends AbstractQueue /** * Saves this queue to a stream (that is, serializes it). * + * @param s the stream + * @throws java.io.IOException if an I/O error occurs * @serialData The length of the array backing the instance is * emitted (int), followed by all of its elements * (each an {@code Object}) in the proper order. - * @param s the stream - * @throws java.io.IOException if an I/O error occurs */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index ea2ab9c4d24..5708af2653c 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -136,9 +136,9 @@ import java.util.function.Supplier; * }} * * @author Doug Lea - * @since 1.8 * @param The result type returned by this future's {@code join} * and {@code get} methods + * @since 1.8 */ public class CompletableFuture implements Future, CompletionStage { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java b/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java index 5e018f1c327..beae1cabb90 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java @@ -132,10 +132,10 @@ import java.util.concurrent.locks.ReentrantLock; * happen-before actions following a successful return from the * corresponding {@code await()} in other threads. * - * @since 1.5 * @see CountDownLatch * * @author Doug Lea + * @since 1.5 */ public class CyclicBarrier { /** diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java b/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java index fe137386d45..9b53a8a54f9 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java @@ -68,7 +68,7 @@ package java.util.concurrent; * private boolean subscribed; // true after first subscribe * public synchronized void subscribe(Subscriber subscriber) { * if (subscribed) - * subscriber.onError(new IllegalStateException()); // only one allowed + * subscriber.onError(new IllegalStateException()); // only one allowed * else { * subscribed = true; * subscriber.onSubscribe(new OneShotSubscription(subscriber, executor)); diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index 4169ec323e5..e8f7ac614df 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -130,7 +130,7 @@ import java.util.concurrent.locks.LockSupport; * * *

        The common pool is by default constructed with default - * parameters, but these may be controlled by setting three + * parameters, but these may be controlled by setting the following * {@linkplain System#getProperty system properties}: *

          *
        • {@code java.util.concurrent.ForkJoinPool.common.parallelism} @@ -3241,7 +3241,7 @@ public class ForkJoinPool extends AbstractExecutorService { * An ACC to restrict permissions for the factory itself. * The constructed workers have no permissions set. */ - private static final AccessControlContext innocuousAcc; + private static final AccessControlContext INNOCUOUS_ACC; static { Permissions innocuousPerms = new Permissions(); innocuousPerms.add(modifyThreadPermission); @@ -3249,7 +3249,7 @@ public class ForkJoinPool extends AbstractExecutorService { "enableContextClassLoaderOverride")); innocuousPerms.add(new RuntimePermission( "modifyThreadGroup")); - innocuousAcc = new AccessControlContext(new ProtectionDomain[] { + INNOCUOUS_ACC = new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, innocuousPerms) }); } @@ -3260,7 +3260,7 @@ public class ForkJoinPool extends AbstractExecutorService { public ForkJoinWorkerThread run() { return new ForkJoinWorkerThread. InnocuousForkJoinWorkerThread(pool); - }}, innocuousAcc); + }}, INNOCUOUS_ACC); } } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java b/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java index 1298a6ee30d..f73c7fe2d5a 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java @@ -72,8 +72,8 @@ import java.util.concurrent.locks.AbstractQueuedSynchronizer; * protected synchronized Object getNextAvailableItem() { * for (int i = 0; i < MAX_AVAILABLE; ++i) { * if (!used[i]) { - * used[i] = true; - * return items[i]; + * used[i] = true; + * return items[i]; * } * } * return null; // not reached @@ -82,11 +82,11 @@ import java.util.concurrent.locks.AbstractQueuedSynchronizer; * protected synchronized boolean markAsUnused(Object item) { * for (int i = 0; i < MAX_AVAILABLE; ++i) { * if (item == items[i]) { - * if (used[i]) { - * used[i] = false; - * return true; - * } else - * return false; + * if (used[i]) { + * used[i] = false; + * return true; + * } else + * return false; * } * } * return false; diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index b59887d415c..5d96cae3f82 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -554,8 +554,9 @@ public class SubmissionPublisher implements Flow.Publisher, while (r != null) { BufferedSubscription nextRetry = r.nextRetry; r.nextRetry = null; - int stat = (nanos > 0L) ? r.timedOffer(item, nanos) : - r.offer(item); + int stat = (nanos > 0L) + ? r.timedOffer(item, nanos) + : r.offer(item); if (stat == 0 && onDrop != null && onDrop.test(r.subscriber, item)) stat = r.offer(item); diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java index d947a87cbd5..0016bfffe87 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -617,6 +617,9 @@ public class ThreadPoolExecutor extends AbstractExecutorService { /** Per-thread task counter */ volatile long completedTasks; + // TODO: switch to AbstractQueuedLongSynchronizer and move + // completedTasks into the lock word. + /** * Creates with given first task and thread from ThreadFactory. * @param firstTask the first task (null if none) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java index c7fa1c66e52..4e4c51eb53a 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -193,7 +193,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { /** * Atomically increments the current value, - * with memory effects as specified by {@link VarHandle#addAndGet}. + * with memory effects as specified by {@link VarHandle#getAndAdd}. * *

          Equivalent to {@code addAndGet(1)}. * @@ -205,7 +205,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { /** * Atomically decrements the current value, - * with memory effects as specified by {@link VarHandle#addAndGet}. + * with memory effects as specified by {@link VarHandle#getAndAdd}. * *

          Equivalent to {@code addAndGet(-1)}. * diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java index 8b9d401ee10..18fac82b111 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java @@ -154,13 +154,13 @@ import jdk.internal.vm.annotation.ReservedStackAccess; * long stamp = sl.tryOptimisticRead(); * double currentX = x, currentY = y; * if (!sl.validate(stamp)) { - * stamp = sl.readLock(); - * try { - * currentX = x; - * currentY = y; - * } finally { - * sl.unlockRead(stamp); - * } + * stamp = sl.readLock(); + * try { + * currentX = x; + * currentY = y; + * } finally { + * sl.unlockRead(stamp); + * } * } * return Math.sqrt(currentX * currentX + currentY * currentY); * } diff --git a/jdk/test/java/util/PriorityQueue/NoNulls.java b/jdk/test/java/util/PriorityQueue/NoNulls.java index 5ef7c536c8a..f2e147a34b6 100644 --- a/jdk/test/java/util/PriorityQueue/NoNulls.java +++ b/jdk/test/java/util/PriorityQueue/NoNulls.java @@ -38,10 +38,8 @@ */ import java.util.ArrayList; -import java.util.Arrays; import java.util.Comparator; import java.util.Collection; -import java.util.Collections; import java.util.PriorityQueue; import java.util.SortedSet; import java.util.TreeSet; diff --git a/jdk/test/java/util/concurrent/BlockingQueue/LoopHelpers.java b/jdk/test/java/util/concurrent/BlockingQueue/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java index 9154683995d..9d6f289634a 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java @@ -43,7 +43,6 @@ import java.util.List; import java.util.SplittableRandom; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CyclicBarrier; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; diff --git a/jdk/test/java/util/concurrent/ConcurrentHashMap/LoopHelpers.java b/jdk/test/java/util/concurrent/ConcurrentHashMap/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/ConcurrentHashMap/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/LoopHelpers.java b/jdk/test/java/util/concurrent/ConcurrentQueues/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java b/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java index 96008fa67b2..bc6d7a99a72 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java @@ -43,7 +43,6 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.Semaphore; -import java.util.concurrent.ThreadLocalRandom; @SuppressWarnings({"unchecked", "rawtypes", "deprecation"}) public class OfferRemoveLoops { diff --git a/jdk/test/java/util/concurrent/DelayQueue/Stress.java b/jdk/test/java/util/concurrent/DelayQueue/Stress.java index 5a25b077521..44a20fff936 100644 --- a/jdk/test/java/util/concurrent/DelayQueue/Stress.java +++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java @@ -22,7 +22,6 @@ */ import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; diff --git a/jdk/test/java/util/concurrent/Exchanger/LoopHelpers.java b/jdk/test/java/util/concurrent/Exchanger/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/Exchanger/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/Exchanger/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/ExecutorCompletionService/LoopHelpers.java b/jdk/test/java/util/concurrent/ExecutorCompletionService/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/ExecutorCompletionService/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/FutureTask/LoopHelpers.java b/jdk/test/java/util/concurrent/FutureTask/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/FutureTask/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/FutureTask/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java index 4aff18e2a25..23ce8bb0e95 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java @@ -33,7 +33,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import jdk.testlibrary.Utils; /** diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java index f78c8d854d3..87dfd6ed4bd 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java @@ -40,7 +40,6 @@ import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.lang.reflect.Field; import java.util.concurrent.BlockingQueue; diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java index 5d10213dc99..1a51d583e20 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java @@ -40,7 +40,6 @@ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java index 463d388b5da..007c52c8cb1 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java @@ -34,7 +34,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import jdk.testlibrary.Utils; public class TimeOutShrink { diff --git a/jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java b/jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java index d1a4fddbcd0..008ac062afb 100644 --- a/jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java +++ b/jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java @@ -22,7 +22,6 @@ */ import java.util.concurrent.atomic.AtomicReference; -import java.util.function.UnaryOperator; import org.testng.annotations.Test; import static org.testng.Assert.*; diff --git a/jdk/test/java/util/concurrent/forkjoin/SubmissionTest.java b/jdk/test/java/util/concurrent/forkjoin/SubmissionTest.java index 5a3db577ddd..24ffd259217 100644 --- a/jdk/test/java/util/concurrent/forkjoin/SubmissionTest.java +++ b/jdk/test/java/util/concurrent/forkjoin/SubmissionTest.java @@ -22,27 +22,35 @@ */ import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import jdk.testlibrary.Utils; /* * @test * @bug 8078490 * @summary Test submission and execution of task without joining + * @library /lib/testlibrary/ */ public class SubmissionTest { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + + static long millisElapsedSince(long startTime) { + return (System.nanoTime() - startTime) / (1000L * 1000L); + } + public static void main(String[] args) throws Throwable { final ForkJoinPool e = new ForkJoinPool(1); final AtomicBoolean b = new AtomicBoolean(); final Runnable setFalse = () -> b.set(false); - for (int i = 0; i < 100000; i++) { + for (int i = 0; i < 30_000; i++) { b.set(true); e.execute(setFalse); - long st = System.nanoTime(); + long startTime = System.nanoTime(); while (b.get()) { - if (System.nanoTime() - st >= TimeUnit.SECONDS.toNanos(10)) { + if (millisElapsedSince(startTime) >= LONG_DELAY_MS) { throw new RuntimeException("Submitted task failed to execute"); } + Thread.yield(); } } } diff --git a/jdk/test/java/util/concurrent/locks/Lock/LoopHelpers.java b/jdk/test/java/util/concurrent/locks/Lock/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/locks/Lock/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/locks/Lock/Mutex.java b/jdk/test/java/util/concurrent/locks/Lock/Mutex.java index 40bb16064a8..1a118f18a36 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/Mutex.java +++ b/jdk/test/java/util/concurrent/locks/Lock/Mutex.java @@ -35,7 +35,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; -import java.util.concurrent.atomic.AtomicInteger; import java.io.IOException; import java.io.ObjectInputStream; diff --git a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java index 2d82c455574..dc204906551 100644 --- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java +++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java @@ -43,7 +43,6 @@ import java.util.SplittableRandom; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.LockSupport; diff --git a/jdk/test/java/util/concurrent/locks/ReentrantLock/LoopHelpers.java b/jdk/test/java/util/concurrent/locks/ReentrantLock/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantLock/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/LoopHelpers.java b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/LoopHelpers.java index ed3d8719dff..3f664d54570 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/LoopHelpers.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/LoopHelpers.java @@ -31,8 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.concurrent.atomic.AtomicLong; - /** * Misc utilities in JSR166 performance tests */ diff --git a/jdk/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java b/jdk/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java index 6d459372515..be721a7b128 100644 --- a/jdk/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java +++ b/jdk/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java @@ -22,7 +22,6 @@ /* * @test - * @run main/othervm/timeout=60 ReadersUnlockAfterWriteUnlock * @bug 8023234 * @summary StampedLock serializes readers on writer unlock * @author Dmitry Chyuko @@ -30,26 +29,23 @@ */ import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.StampedLock; public class ReadersUnlockAfterWriteUnlock { - static final int RNUM = 2; - static final StampedLock sl = new StampedLock(); - static volatile boolean isDone; + public static void main(String[] args) throws InterruptedException { + final int RNUM = 2; + final int REPS = 128; + final StampedLock sl = new StampedLock(); + final AtomicReference bad = new AtomicReference<>(); - static CyclicBarrier iterationStart = new CyclicBarrier(RNUM + 1); - static CyclicBarrier readersHaveLocks = new CyclicBarrier(RNUM); - static CyclicBarrier writerHasLock = new CyclicBarrier(RNUM + 1); + final CyclicBarrier iterationStart = new CyclicBarrier(RNUM + 1); + final CyclicBarrier readersHaveLocks = new CyclicBarrier(RNUM); + final CyclicBarrier writerHasLock = new CyclicBarrier(RNUM + 1); - static class Reader extends Thread { - final String name; - Reader(String name) { - super(); - this.name = name; - } - public void run() { - while (!isDone && !isInterrupted()) { - try { + Runnable reader = () -> { + try { + for (int i = 0; i < REPS; i++) { iterationStart.await(); writerHasLock.await(); long rs = sl.readLock(); @@ -59,30 +55,45 @@ public class ReadersUnlockAfterWriteUnlock { readersHaveLocks.await(); sl.unlockRead(rs); - } catch (Exception e) { - throw new IllegalStateException(e); } + } catch (Throwable ex) { + ex.printStackTrace(); + bad.set(ex); } - } - } + }; - public static void main(String[] args) throws InterruptedException { - for (int r = 0 ; r < RNUM; ++r) { - new Reader("r" + r).start(); + Thread[] threads = new Thread[RNUM]; + for (int i = 0 ; i < RNUM; i++) { + Thread thread = new Thread(reader, "Reader"); + threads[i] = thread; + thread.start(); } - int i; - for (i = 0; i < 1024; ++i) { + for (int i = 0; i < REPS; i++) { try { iterationStart.await(); long ws = sl.writeLock(); writerHasLock.await(); - Thread.sleep(10); + awaitWaitState(threads); sl.unlockWrite(ws); } catch (Exception e) { throw new IllegalStateException(e); } } - isDone = true; + for (Thread thread : threads) + thread.join(); + if (bad.get() != null) + throw new AssertionError(bad.get()); } + static void awaitWaitState(Thread[] threads) { + restart: for (;;) { + for (Thread thread : threads) { + if (thread.getState() != Thread.State.WAITING) { + Thread.yield(); + continue restart; + } + } + break; + } + } } diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java index d074b140ba2..b7b20bdf6b0 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java @@ -31,7 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.Arrays; import java.util.concurrent.atomic.AtomicIntegerArray; import junit.framework.Test; diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java b/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java index 488b195e014..2011c789b91 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java @@ -31,7 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.Arrays; import java.util.concurrent.atomic.AtomicLongArray; import junit.framework.Test; diff --git a/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java b/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java index 9ebec5b2ef6..44bcdbe281f 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java @@ -31,7 +31,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -import java.util.Arrays; import java.util.concurrent.atomic.AtomicReferenceArray; import junit.framework.Test; diff --git a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java index 203fd812ec5..a29f50e0a24 100644 --- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java +++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java @@ -59,7 +59,6 @@ import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeoutException; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java index 18695548129..fd62ada71cb 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java @@ -38,7 +38,6 @@ import static java.util.Spliterator.NONNULL; import java.util.AbstractMap; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java index e8be651d53d..c457f6b85f9 100644 --- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java @@ -36,7 +36,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java index 21f932e09a3..db7536856fe 100644 --- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java @@ -36,7 +36,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java index 8169d5fa5f6..d72d7dcc78f 100644 --- a/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java @@ -42,7 +42,6 @@ import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import junit.framework.Test; diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java index 6e4d00f3d0f..0ab6084b978 100644 --- a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java @@ -40,7 +40,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java b/jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java index ee991a21c80..b0fea9a0bfe 100644 --- a/jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java +++ b/jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java @@ -296,12 +296,11 @@ public class ForkJoinPool8Test extends JSR166TestCase { RecursiveAction a = new CheckedRecursiveAction() { protected void realCompute() { FibAction f = new FibAction(8); - final Thread myself = Thread.currentThread(); + final Thread currentThread = Thread.currentThread(); // test join() assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); assertNull(f.join()); Thread.interrupted(); assertEquals(21, f.result); @@ -310,8 +309,7 @@ public class ForkJoinPool8Test extends JSR166TestCase { f = new FibAction(8); f.cancel(true); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); try { f.join(); shouldThrow(); @@ -323,8 +321,7 @@ public class ForkJoinPool8Test extends JSR166TestCase { f = new FibAction(8); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); try { f.join(); shouldThrow(); @@ -336,8 +333,7 @@ public class ForkJoinPool8Test extends JSR166TestCase { // test quietlyJoin() f = new FibAction(8); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); Thread.interrupted(); assertEquals(21, f.result); @@ -346,8 +342,7 @@ public class ForkJoinPool8Test extends JSR166TestCase { f = new FibAction(8); f.cancel(true); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); Thread.interrupted(); checkCancelled(f); @@ -355,8 +350,7 @@ public class ForkJoinPool8Test extends JSR166TestCase { f = new FibAction(8); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); Thread.interrupted(); checkCompletedAbnormally(f, f.getException()); diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java b/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java index 54e944b54d0..c1063da31aa 100644 --- a/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java +++ b/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java @@ -35,7 +35,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.Arrays; -import java.util.Collections; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java b/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java index c3e1c1802a5..807785aced6 100644 --- a/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java +++ b/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java @@ -35,9 +35,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index f6c3e2a930c..aaa97d8abcb 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -1264,7 +1264,7 @@ public class JSR166TestCase extends TestCase { * Sleeps until the given time has elapsed. * Throws AssertionFailedError if interrupted. */ - void sleep(long millis) { + static void sleep(long millis) { try { delay(millis); } catch (InterruptedException fail) { diff --git a/jdk/test/java/util/concurrent/tck/RecursiveActionTest.java b/jdk/test/java/util/concurrent/tck/RecursiveActionTest.java index 9ce68c34166..01bd92770b7 100644 --- a/jdk/test/java/util/concurrent/tck/RecursiveActionTest.java +++ b/jdk/test/java/util/concurrent/tck/RecursiveActionTest.java @@ -285,12 +285,11 @@ public class RecursiveActionTest extends JSR166TestCase { RecursiveAction a = new CheckedRecursiveAction() { protected void realCompute() { FibAction f = new FibAction(8); - final Thread myself = Thread.currentThread(); + final Thread currentThread = Thread.currentThread(); // test join() assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); assertNull(f.join()); Thread.interrupted(); assertEquals(21, f.result); @@ -299,8 +298,7 @@ public class RecursiveActionTest extends JSR166TestCase { f = new FibAction(8); f.cancel(true); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); try { f.join(); shouldThrow(); @@ -312,8 +310,7 @@ public class RecursiveActionTest extends JSR166TestCase { f = new FibAction(8); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); try { f.join(); shouldThrow(); @@ -325,8 +322,7 @@ public class RecursiveActionTest extends JSR166TestCase { // test quietlyJoin() f = new FibAction(8); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); Thread.interrupted(); assertEquals(21, f.result); @@ -335,8 +331,7 @@ public class RecursiveActionTest extends JSR166TestCase { f = new FibAction(8); f.cancel(true); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); Thread.interrupted(); checkCancelled(f); @@ -344,8 +339,7 @@ public class RecursiveActionTest extends JSR166TestCase { f = new FibAction(8); f.completeExceptionally(new FJException()); assertSame(f, f.fork()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); Thread.interrupted(); checkCompletedAbnormally(f, f.getException()); @@ -385,22 +379,20 @@ public class RecursiveActionTest extends JSR166TestCase { public void realRun() throws InterruptedException { FibAction[] fibActions = sq.take(); FibAction f; - final Thread myself = Thread.currentThread(); + final Thread currentThread = Thread.currentThread(); // test join() ------------ f = fibActions[0]; assertFalse(ForkJoinTask.inForkJoinPool()); - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); assertNull(f.join()); assertTrue(Thread.interrupted()); assertEquals(21, f.result); checkCompletedNormally(f); f = fibActions[1]; - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); try { f.join(); shouldThrow(); @@ -410,8 +402,7 @@ public class RecursiveActionTest extends JSR166TestCase { } f = fibActions[2]; - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); try { f.join(); shouldThrow(); @@ -423,23 +414,20 @@ public class RecursiveActionTest extends JSR166TestCase { // test quietlyJoin() --------- f = fibActions[3]; - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); assertTrue(Thread.interrupted()); assertEquals(21, f.result); checkCompletedNormally(f); f = fibActions[4]; - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); assertTrue(Thread.interrupted()); checkCancelled(f); f = fibActions[5]; - myself.interrupt(); - assertTrue(myself.isInterrupted()); + currentThread.interrupt(); f.quietlyJoin(); assertTrue(Thread.interrupted()); assertTrue(f.getException() instanceof FJException); diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java index ead869ed648..30cf187a64b 100644 --- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java @@ -44,7 +44,6 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Delayed; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java index 53ebc5ea179..1cb2a472658 100644 --- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java @@ -45,7 +45,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; diff --git a/jdk/test/java/util/concurrent/tck/StampedLockTest.java b/jdk/test/java/util/concurrent/tck/StampedLockTest.java index 5ced6c93d4d..a03be993f88 100644 --- a/jdk/test/java/util/concurrent/tck/StampedLockTest.java +++ b/jdk/test/java/util/concurrent/tck/StampedLockTest.java @@ -44,7 +44,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.StampedLock; import java.util.function.BiConsumer; -import java.util.function.Consumer; import java.util.function.Function; import junit.framework.Test; diff --git a/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java index ab4c9e90438..d72f1af9f5c 100644 --- a/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java +++ b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java @@ -37,24 +37,14 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Flow; import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SubmissionPublisher; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.BiPredicate; -import java.util.stream.Stream; import junit.framework.Test; import junit.framework.TestSuite; -import static java.util.concurrent.Flow.Publisher; import static java.util.concurrent.Flow.Subscriber; import static java.util.concurrent.Flow.Subscription; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; public class SubmissionPublisherTest extends JSR166TestCase { diff --git a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java index 3959527af70..83a4f42412c 100644 --- a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java +++ b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java @@ -44,7 +44,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; diff --git a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java index 5df3c94b120..8a72586f3ae 100644 --- a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java +++ b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java @@ -55,7 +55,6 @@ import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.Test; From 02944f968ddf5d72329bafa820b8d1097f9f078d Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Mon, 12 Sep 2016 15:00:58 -0700 Subject: [PATCH 38/38] 8160950: Agent JAR added to app class loader rather than system class loader when running with -Djava.system.class.loader Add agent JAR to the custom system class loader Reviewed-by: alanb, mchung, dholmes --- .../classes/java/lang/instrument/package.html | 9 ++- .../native/libinstrument/InvocationAdapter.c | 64 +++++++-------- .../share/native/libinstrument/JPLISAgent.c | 1 + .../share/native/libinstrument/JPLISAgent.h | 1 + .../instrument/CustomSystemLoader/Agent.java | 55 +++++++++++++ .../instrument/CustomSystemLoader/App.java | 46 +++++++++++ .../CustomSystemLoader/CustomLoader.java | 81 +++++++++++++++++++ 7 files changed, 224 insertions(+), 33 deletions(-) create mode 100644 jdk/test/java/lang/instrument/CustomSystemLoader/Agent.java create mode 100644 jdk/test/java/lang/instrument/CustomSystemLoader/App.java create mode 100644 jdk/test/java/lang/instrument/CustomSystemLoader/CustomLoader.java diff --git a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html b/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html index 9b1b02ea06f..c1f6c852982 100644 --- a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html +++ b/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html @@ -105,6 +105,10 @@ method is not invoked. The agent class will be loaded by the system class loader (see {@link java.lang.ClassLoader#getSystemClassLoader ClassLoader.getSystemClassLoader}). This is the class loader which typically loads the class containing the application main method. +The system class loader must support a mechanism to add an agent JAR file to the system class path. +If it is a custom system class loader then it must define the +appendToClassPathForInstrumentation method as specified in +{@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}. The premain methods will be run under the same security and classloader rules as the application main method. There are no modeling restrictions on what the agent premain method may do. @@ -140,7 +144,10 @@ supports the starting of agents after the VM has started the following applies:

        • The system class loader ( {@link java.lang.ClassLoader#getSystemClassLoader ClassLoader.getSystemClassLoader}) must - support a mechanism to add an agent JAR file to the system class path.

        • + support a mechanism to add an agent JAR file to the system class path. + If it is a custom system class loader then it must define the + appendToClassPathForInstrumentation method as specified in + {@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}.

          diff --git a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c index a74b2b725ba..625ea1ad13d 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c +++ b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -190,10 +190,8 @@ DEF_Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) { return JNI_ERR; } - /* - * Add to the jarfile - */ - appendClassPath(agent, jarfile); + /* Save the jarfile name */ + agent->mJarfile = jarfile; /* * The value of the Premain-Class attribute becomes the agent @@ -241,7 +239,6 @@ DEF_Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) { /* * Clean-up */ - free(jarfile); if (options != NULL) free(options); freeAttributes(attributes); free(premainClass); @@ -459,7 +456,23 @@ eventHandlerVMInit( jvmtiEnv * jvmtienv, /* process the premain calls on the all the JPL agents */ if ( environment != NULL ) { - jthrowable outstandingException = preserveThrowable(jnienv); + jthrowable outstandingException = NULL; + /* + * Add the jarfile to the system class path + */ + JPLISAgent * agent = environment->mAgent; + if (appendClassPath(agent, agent->mJarfile)) { + fprintf(stderr, "Unable to add %s to system class path - " + "the system class loader does not define the " + "appendToClassPathForInstrumentation method or the method failed\n", + agent->mJarfile); + free((void *)agent->mJarfile); + abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART); + } + free((void *)agent->mJarfile); + agent->mJarfile = NULL; + + outstandingException = preserveThrowable(jnienv); success = processJavaStart( environment->mAgent, jnienv); restoreThrowable(jnienv, outstandingException); @@ -631,32 +644,19 @@ appendClassPath( JPLISAgent* agent, jvmtierr = (*jvmtienv)->AddToSystemClassLoaderSearch(jvmtienv, jarfile); check_phase_ret_1(jvmtierr); - if (jvmtierr == JVMTI_ERROR_NONE) { - return 0; - } else { - jvmtiPhase phase; - jvmtiError err; - - err = (*jvmtienv)->GetPhase(jvmtienv, &phase); - /* can be called from any phase */ - jplis_assert(err == JVMTI_ERROR_NONE); - - if (phase == JVMTI_PHASE_LIVE) { - switch (jvmtierr) { - case JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED : - fprintf(stderr, "System class loader does not support adding " - "JAR file to system class path during the live phase!\n"); - break; - default: - fprintf(stderr, "Unexpected error (%d) returned by " - "AddToSystemClassLoaderSearch\n", jvmtierr); - break; - } - return -1; - } - jplis_assert(0); + switch (jvmtierr) { + case JVMTI_ERROR_NONE : + return 0; + case JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED : + fprintf(stderr, "System class loader does not define " + "the appendToClassPathForInstrumentation method\n"); + break; + default: + fprintf(stderr, "Unexpected error (%d) returned by " + "AddToSystemClassLoaderSearch\n", jvmtierr); + break; } - return -2; + return -1; } diff --git a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c index 3017cca1f7a..12f2a451e49 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c +++ b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c @@ -272,6 +272,7 @@ initializeJPLISAgent( JPLISAgent * agent, agent->mNativeMethodPrefixAdded = JNI_FALSE; agent->mAgentClassName = NULL; agent->mOptionsString = NULL; + agent->mJarfile = NULL; /* make sure we can recover either handle in either direction. * the agent has a ref to the jvmti; make it mutual diff --git a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h index 6ecfde2d5c5..008b2fabc6a 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h +++ b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h @@ -107,6 +107,7 @@ struct _JPLISAgent { jboolean mNativeMethodPrefixAdded; /* indicates if can_set_native_method_prefix capability has been added */ char const * mAgentClassName; /* agent class name */ char const * mOptionsString; /* -javaagent options string */ + const char * mJarfile; /* agent jar file name */ }; /* diff --git a/jdk/test/java/lang/instrument/CustomSystemLoader/Agent.java b/jdk/test/java/lang/instrument/CustomSystemLoader/Agent.java new file mode 100644 index 00000000000..0432c2d9587 --- /dev/null +++ b/jdk/test/java/lang/instrument/CustomSystemLoader/Agent.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.PrintStream; +import java.lang.instrument.*; +import java.lang.reflect.Field; + +/** + * @test + * @bug 8160950 + * @summary test for custom system class loader + * + * @run build App Agent CustomLoader + * @run shell ../MakeJAR3.sh Agent 'Can-Retransform-Classes: true' + * @run main/othervm -javaagent:Agent.jar -Djava.system.class.loader=CustomLoader App + */ + +public class Agent { + private static PrintStream err = System.err; + private static PrintStream out = System.out; + public static boolean failed = false; + + public static void premain(String agentArgs, Instrumentation instrumentation) { + ClassLoader myClassLoader = Agent.class.getClassLoader(); + out.println("Agent: started; myClassLoader: " + myClassLoader); + try { + Field fld = myClassLoader.getClass().getField("agentClassLoader"); + fld.set(myClassLoader.getClass(), myClassLoader); + } catch (Exception ex) { + failed = true; + ex.printStackTrace(); + } + out.println("Agent: finished"); + } +} diff --git a/jdk/test/java/lang/instrument/CustomSystemLoader/App.java b/jdk/test/java/lang/instrument/CustomSystemLoader/App.java new file mode 100644 index 00000000000..a5eac03f14e --- /dev/null +++ b/jdk/test/java/lang/instrument/CustomSystemLoader/App.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.PrintStream; + +public class App { + + public static void main(String args[]) throws Exception { + (new App()).run(args, System.out); + } + + public void run(String args[], PrintStream out) throws Exception { + out.println("App: Test started"); + if (CustomLoader.agentClassLoader != CustomLoader.myself) { + System.out.println("App: agentClassLoader: " + CustomLoader.agentClassLoader); + System.out.println("App: CustomLoader.myself: " + CustomLoader.myself); + System.out.println("App: myClassLoader: " + App.class.getClassLoader()); + throw new Exception("App: Agent's system class loader is not CustomLoader"); + } else if (Agent.failed) { + throw new Exception("App: Agent failed"); + } else if (CustomLoader.failed) { + throw new Exception("App: CustomLoader failed"); + } + out.println("App: Test passed"); + } +} diff --git a/jdk/test/java/lang/instrument/CustomSystemLoader/CustomLoader.java b/jdk/test/java/lang/instrument/CustomSystemLoader/CustomLoader.java new file mode 100644 index 00000000000..f90e244b4a1 --- /dev/null +++ b/jdk/test/java/lang/instrument/CustomSystemLoader/CustomLoader.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; + +public class CustomLoader extends ClassLoader { + private static PrintStream out = System.out; + public static ClassLoader myself; + public static ClassLoader agentClassLoader; + public static boolean failed = true; + + public CustomLoader(ClassLoader classLoader) { + super(classLoader); + myself = this; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + out.println("CustomLoader: loading class: " + name); + if (name.equals("Agent")) { + Class c = null; + try { + byte[] buf = locateBytes(); + c = defineClass(name, buf, 0, buf.length); + } catch (IOException ex) { + throw new ClassNotFoundException(ex.getMessage()); + } + resolveClass(c); + out.println("CustomLoader.loadClass after resolveClass: " + name + + "; Class: " + c + "; ClassLoader: " + c.getClassLoader()); + return c; + } + return super.loadClass(name); + } + + private byte[] locateBytes() throws IOException { + try { + JarFile jar = new JarFile("Agent.jar"); + InputStream is = jar.getInputStream(jar.getEntry("Agent.class")); + int len = is.available(); + byte[] buf = new byte[len]; + DataInputStream in = new DataInputStream(is); + in.readFully(buf); + return buf; + } catch (IOException ioe) { + ioe.printStackTrace(); + throw new IOException("Test failed due to IOException!"); + } + } + + void appendToClassPathForInstrumentation(String path) { + out.println("CustomLoader.appendToClassPathForInstrumentation: " + + this + ", jar: " + path); + failed = false; + } +}