changeset 13543:8119ddcb3eec jdk8u222-b04

Merge
author andrew
date Thu, 23 May 2019 04:01:32 +0100
parents 933f6b06c1cb (current diff) 9fdbdce56577 (diff)
children 2d4edd21bb38
files
diffstat 8 files changed, 339 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/stream/AbstractTask.java	Fri May 17 18:53:33 2019 +0100
+++ b/src/share/classes/java/util/stream/AbstractTask.java	Thu May 23 04:01:32 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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,6 +27,7 @@
 import java.util.Spliterator;
 import java.util.concurrent.CountedCompleter;
 import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinWorkerThread;
 
 /**
  * Abstract base class for most fork-join tasks used to implement stream ops.
@@ -88,13 +89,7 @@
                             K extends AbstractTask<P_IN, P_OUT, R, K>>
         extends CountedCompleter<R> {
 
-    /**
-     * Default target factor of leaf tasks for parallel decomposition.
-     * To allow load balancing, we over-partition, currently to approximately
-     * four tasks per processor, which enables others to help out
-     * if leaf tasks are uneven or some processors are otherwise busy.
-     */
-    static final int LEAF_TARGET = ForkJoinPool.getCommonPoolParallelism() << 2;
+    private static final int LEAF_TARGET = ForkJoinPool.getCommonPoolParallelism() << 2;
 
     /** The pipeline helper, common to all tasks in a computation */
     protected final PipelineHelper<P_OUT> helper;
@@ -157,6 +152,22 @@
     }
 
     /**
+     * Default target of leaf tasks for parallel decomposition.
+     * To allow load balancing, we over-partition, currently to approximately
+     * four tasks per processor, which enables others to help out
+     * if leaf tasks are uneven or some processors are otherwise busy.
+     */
+    public static int getLeafTarget() {
+        Thread t = Thread.currentThread();
+        if (t instanceof ForkJoinWorkerThread) {
+            return ((ForkJoinWorkerThread) t).getPool().getParallelism() << 2;
+        }
+        else {
+            return LEAF_TARGET;
+        }
+    }
+
+    /**
      * Constructs a new node of type T whose parent is the receiver; must call
      * the AbstractTask(T, Spliterator) constructor with the receiver and the
      * provided Spliterator.
@@ -181,7 +192,7 @@
      * @return suggested target leaf size
      */
     public static long suggestTargetSize(long sizeEstimate) {
-        long est = sizeEstimate / LEAF_TARGET;
+        long est = sizeEstimate / getLeafTarget();
         return est > 0L ? est : 1L;
     }
 
--- a/src/share/classes/java/util/stream/ForEachOps.java	Fri May 17 18:53:33 2019 +0100
+++ b/src/share/classes/java/util/stream/ForEachOps.java	Thu May 23 04:01:32 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -28,7 +28,6 @@
 import java.util.Spliterator;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountedCompleter;
-import java.util.concurrent.ForkJoinTask;
 import java.util.function.Consumer;
 import java.util.function.DoubleConsumer;
 import java.util.function.IntConsumer;
@@ -378,7 +377,7 @@
             this.spliterator = spliterator;
             this.targetSize = AbstractTask.suggestTargetSize(spliterator.estimateSize());
             // Size map to avoid concurrent re-sizes
-            this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.LEAF_TARGET << 1));
+            this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.getLeafTarget() << 1));
             this.action = action;
             this.leftPredecessor = null;
         }
--- a/src/share/classes/java/util/stream/StreamSpliterators.java	Fri May 17 18:53:33 2019 +0100
+++ b/src/share/classes/java/util/stream/StreamSpliterators.java	Thu May 23 04:01:32 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -898,7 +898,7 @@
      * Note: The source spliterator may report {@code ORDERED} since that
      * spliterator be the result of a previous pipeline stage that was
      * collected to a {@code Node}. It is the order of the pipeline stage
-     * that governs whether the this slice spliterator is to be used or not.
+     * that governs whether this slice spliterator is to be used or not.
      */
     static abstract class UnorderedSliceSpliterator<T, T_SPLITR extends Spliterator<T>> {
         static final int CHUNK_SIZE = 1 << 7;
@@ -915,7 +915,7 @@
             this.unlimited = limit < 0;
             this.skipThreshold = limit >= 0 ? limit : 0;
             this.chunkSize = limit >= 0 ? (int)Math.min(CHUNK_SIZE,
-                ((skip + limit) / AbstractTask.LEAF_TARGET) + 1) : CHUNK_SIZE;
+                                                        ((skip + limit) / AbstractTask.getLeafTarget()) + 1) : CHUNK_SIZE;
             this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip);
         }
 
--- a/src/share/classes/sun/security/ssl/SessionId.java	Fri May 17 18:53:33 2019 +0100
+++ b/src/share/classes/sun/security/ssl/SessionId.java	Thu May 23 04:01:32 2019 +0100
@@ -27,6 +27,7 @@
 package sun.security.ssl;
 
 import java.security.SecureRandom;
+import java.util.Arrays;
 import javax.net.ssl.SSLProtocolException;
 
 /**
@@ -91,11 +92,7 @@
     @Override
     public int hashCode ()
     {
-        int     retval = 0;
-
-        for (int i = 0; i < sessionId.length; i++)
-            retval += sessionId [i];
-        return retval;
+        return Arrays.hashCode(sessionId);
     }
 
     /** Returns true if the parameter is the same session ID */
Binary file src/share/lib/security/cacerts has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CustomFJPoolTest.java	Thu May 23 04:01:32 2019 +0100
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.tests.java.util.stream;
+
+import org.testng.annotations.Test;
+
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Tests stream execution in a custom ForkJoinPool. See JDK-8190974.
+ */
+@Test
+public class CustomFJPoolTest {
+
+    // A Spliterator that counts the number of spliterators created
+    // including itself, thus the count starts at 1
+    static class SplitCountingSpliterator<T> implements Spliterator<T> {
+        final Spliterator<T> s;
+        final AtomicInteger nsplits;
+
+        // Top-level constructor
+        public SplitCountingSpliterator(Spliterator<T> s) {
+            this.s = s;
+            nsplits = new AtomicInteger(1);
+        }
+
+        // Splitting constructor
+        SplitCountingSpliterator(Spliterator<T> s, AtomicInteger nsplits) {
+            this.s = s;
+            this.nsplits = nsplits;
+        }
+
+        int splits() {
+            return nsplits.get();
+        }
+
+        @Override
+
+        public boolean tryAdvance(Consumer<? super T> action) {
+            return s.tryAdvance(action);
+        }
+
+        @Override
+        public void forEachRemaining(Consumer<? super T> action) {
+            s.forEachRemaining(action);
+        }
+
+        @Override
+        public Spliterator<T> trySplit() {
+            Spliterator<T> split = s.trySplit();
+            if (split != null) {
+                nsplits.incrementAndGet();
+                return new SplitCountingSpliterator<>(split, nsplits);
+            }
+            else {
+                return null;
+            }
+        }
+
+        @Override
+        public long estimateSize() {
+            return s.estimateSize();
+        }
+
+        @Override
+        public long getExactSizeIfKnown() {
+            return s.getExactSizeIfKnown();
+        }
+
+        @Override
+        public int characteristics() {
+            return s.characteristics();
+        }
+
+        @Override
+        public boolean hasCharacteristics(int characteristics) {
+            return s.hasCharacteristics(characteristics);
+        }
+
+        @Override
+        public Comparator<? super T> getComparator() {
+            return s.getComparator();
+        }
+    }
+
+    public void testCustomPools() throws Exception {
+        int splitsForP1 = countSplits(new ForkJoinPool(1));
+        int splitsForP2 = countSplits(new ForkJoinPool(2));
+        assertEquals(splitsForP2, splitsForP1 * 2);
+
+        int commonParallelism = ForkJoinPool.getCommonPoolParallelism();
+        if (commonParallelism > 1 && commonParallelism < 128) {
+            int splitsForPHalfC = countSplits(new ForkJoinPool(commonParallelism / 2));
+            int splitsForPC = countSplits(ForkJoinPool.commonPool());
+
+            assertTrue(splitsForPHalfC < splitsForPC);
+            assertEquals(splitsForPC / splitsForPHalfC,
+                         nearestPowerOfTwo(commonParallelism) / nearestPowerOfTwo(commonParallelism / 2));
+        }
+    }
+
+    static int countSplits(ForkJoinPool fjp) throws Exception {
+        // The number of splits will be equivalent to the number of leaf nodes
+        // and will be a power of 2
+        ForkJoinTask<Integer> fInteger = fjp.submit(() -> {
+            Spliterator<Integer> s = IntStream.range(0, 1024).boxed().parallel().spliterator();
+            SplitCountingSpliterator<Integer> cs = new SplitCountingSpliterator<>(s);
+            StreamSupport.stream(cs, true).forEach(e -> {});
+            return cs.splits();
+        });
+        return fInteger.get();
+    }
+
+    static int nearestPowerOfTwo(int i) {
+        return (i & (i - 1)) == 0
+               ? i
+               : 1 << (32 - Integer.numberOfLeadingZeros(i));
+    }
+}
--- a/test/sun/security/lib/cacerts/VerifyCACerts.java	Fri May 17 18:53:33 2019 +0100
+++ b/test/sun/security/lib/cacerts/VerifyCACerts.java	Thu May 23 04:01:32 2019 +0100
@@ -26,6 +26,7 @@
  * @test
  * @bug 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779
  *      8209452 8209506 8210432 8195793 8216577 8222089 8222133 8222137 8222136
+ *      8223499
  * @summary Check root CA entries in cacerts file
  */
 import java.io.File;
@@ -49,7 +50,7 @@
             + File.separator + "security" + File.separator + "cacerts";
 
     // The numbers of certs now.
-    private static final int COUNT = 90;
+    private static final int COUNT = 88;
 
     // map of cert alias to SHA-256 fingerprint
     @SuppressWarnings("serial")
@@ -144,10 +145,6 @@
                     "69:DD:D7:EA:90:BB:57:C9:3E:13:5D:C8:5E:A6:FC:D5:48:0B:60:32:39:BD:C4:54:FC:75:8B:2A:26:CF:7F:79");
             put("verisignclass3g5ca [jdk]",
                     "9A:CF:AB:7E:43:C8:D8:80:D0:6B:26:2A:94:DE:EE:E4:B4:65:99:89:C3:D0:CA:F1:9B:AF:64:05:E4:1A:B7:DF");
-            put("certplusclass2primaryca [jdk]",
-                    "0F:99:3C:8A:EF:97:BA:AF:56:87:14:0E:D5:9A:D1:82:1B:B4:AF:AC:F0:AA:9A:58:B5:D5:7A:33:8A:3A:FB:CB");
-            put("certplusclass3pprimaryca [jdk]",
-                    "CC:C8:94:89:37:1B:AD:11:1C:90:61:9B:EA:24:0A:2E:6D:AD:D9:9F:9F:6E:1D:4D:41:E5:8E:D6:DE:3D:02:85");
             put("keynectisrootca [jdk]",
                     "42:10:F1:99:49:9A:9A:C3:3C:8D:E0:2B:A6:DB:AA:14:40:8B:DD:8A:6E:32:46:89:C1:92:2D:06:97:15:A3:32");
             put("dtrustclass3ca2 [jdk]",
@@ -244,10 +241,6 @@
     @SuppressWarnings("serial")
     private static final HashSet<String> EXPIRY_EXC_ENTRIES = new HashSet<String>() {
         {
-            // Valid until: Sat Jul 06 19:59:59 EDT 2019
-            add("certplusclass2primaryca [jdk]");
-            // Valid until: Sat Jul 06 19:59:59 EDT 2019
-            add("certplusclass3pprimaryca [jdk]");
             // Valid until: Tue Jul 09 14:40:36 EDT 2019
             add("utnuserfirstobjectca [jdk]");
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/ssl/SessionIdCollisionTest.java	Thu May 23 04:01:32 2019 +0100
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.lang.reflect.Constructor;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @test
+ * @bug 8203190
+ * @summary Manual test to verify number of collisions in
+ *          sun.security.ssl.SessionId.hashCode()
+ * @run main/manual SessionIdCollisionTest 100 20480 10000000
+ */
+
+/**
+ *
+ * Notes:
+ * - This is a manual test, not run automatically.
+ * - New default value of javax.net.ssl.sessionCacheSize in JDK 12+ is 20480
+ * - According to JDK-8210985 24 hours expired cache may exceed several million
+ *   entries = > 10_000_000
+ *
+ * Example usage: java SessionIdCollissionTest 100 20480 10000000
+ *
+ * Expected outcome of running the test is to see fewer collisions and, more
+ * importantly fewer elements in buckets when there are collisions. See:
+ * http://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-May/009345.html
+ *
+ */
+public class SessionIdCollisionTest {
+
+    private List<Integer> prepareHashCodes(int total) throws Exception {
+        Class<?> sessionIdClass = Class.forName("sun.security.ssl.SessionId");
+        Constructor<?> c = sessionIdClass.getDeclaredConstructor(byte[].class);
+        c.setAccessible(true);
+        // case of rejoinable session ids generates 32 random bytes
+        byte[] sessionIdBytes = new byte[32];
+        List<Integer> hashCodes = new ArrayList<>();
+        for (int i = 0; i < total; i++) {
+            SecureRandom random = new SecureRandom();
+            random.nextBytes(sessionIdBytes);
+            Object sessionId = c.newInstance(sessionIdBytes);
+            int hashCode = sessionId.hashCode();
+            hashCodes.add(hashCode);
+        }
+        return hashCodes;
+    }
+
+    private void printSummary(boolean withDistribution,
+                              List<Integer> hashCodes) throws Exception {
+        final int bound = hashCodes.size();
+        Collections.sort(hashCodes);
+        int collisions = 0;
+        Map<Integer, List<Integer>> collCountsReverse = new HashMap<>();
+        for (int i = 0; i < bound - 1; i++) {
+            int oldval = hashCodes.get(i);
+            int nextval = hashCodes.get(i+1);
+            if (oldval == nextval) {
+                collisions++;
+                if (i == bound - 2) { // last elements
+                    updateCollCountsReverse(collisions, collCountsReverse, oldval);
+                }
+            } else {
+                updateCollCountsReverse(collisions, collCountsReverse, oldval);
+                collisions = 0;
+                if (i == bound - 2) { // last elements
+                    updateCollCountsReverse(collisions, collCountsReverse, nextval);
+                }
+            }
+        }
+        if (withDistribution) {
+            System.out.println("---- distribution ----");
+        }
+        int collCount = 0;
+        int maxLength = 0;
+        List<Integer> sorted = new ArrayList<>(collCountsReverse.size());
+        sorted.addAll(collCountsReverse.keySet());
+        Collections.sort(sorted);
+        for (Integer coll: sorted) {
+            List<Integer> hc = collCountsReverse.get(coll);
+            if (withDistribution) {
+                System.out.printf("Hashcodes with %02d collisions | " +
+                                  "hashCodes: %s\n", coll, hc.toString());
+            }
+            collCount += coll * hc.size();
+            if (coll > maxLength) {
+                maxLength = coll;
+            }
+        }
+        if (withDistribution) {
+            System.out.println("---- distribution ----");
+        }
+        System.out.println("Total number of collisions: " + collCount);
+        if (collCount > 0) {
+            System.out.println("Max length of collision list over all buckets: " +
+                                maxLength);
+        }
+    }
+
+    private void updateCollCountsReverse(int collisions,
+            Map<Integer, List<Integer>> reverse, int val) {
+        List<Integer> hc = reverse.get(collisions);
+        if (hc == null) {
+            hc = new ArrayList<>();
+            hc.add(val);
+            reverse.put(collisions, hc);
+        } else {
+            hc.add(val);
+        }
+    }
+
+    public void doCollissionTest(int total) throws Exception {
+        System.out.println("Collision test for " + total + " sessions:");
+        System.out.println("------------------------------------------------");
+        List<Integer> hashcodes = prepareHashCodes(total);
+        printSummary(false, hashcodes);
+        System.out.println();
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (args.length < 1) {
+            System.err.println("java " + SessionIdCollisionTest.class.getSimpleName() +
+                               "<num-sessions> [<num-sessions> ...]");
+            System.exit(1);
+        }
+        SessionIdCollisionTest collTest = new SessionIdCollisionTest();
+        for (int i = 0; i < args.length; i++) {
+            int total = Integer.parseInt(args[i]);
+            collTest.doCollissionTest(total);
+        }
+    }
+
+}