changeset 12501:4b8d4f91a480

8174109: Better queuing priorities Reviewed-by: smarks
author robm
date Fri, 18 Aug 2017 00:47:21 +0100
parents 65f4af74c8b1
children 9cc9fbb9e7c5
files src/share/classes/java/io/ObjectInputStream.java src/share/classes/java/util/ArrayDeque.java src/share/classes/java/util/ArrayList.java src/share/classes/java/util/HashMap.java src/share/classes/java/util/HashSet.java src/share/classes/java/util/Hashtable.java src/share/classes/java/util/IdentityHashMap.java src/share/classes/java/util/PriorityQueue.java src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java src/share/classes/sun/misc/JavaOISAccess.java src/share/classes/sun/misc/JavaObjectInputStreamAccess.java src/share/classes/sun/misc/ObjectStreamClassValidator.java test/java/io/Serializable/serialFilter/SerialFilterTest.java
diffstat 13 files changed, 105 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/io/ObjectInputStream.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/io/ObjectInputStream.java	Fri Aug 18 00:47:21 2017 +0100
@@ -43,6 +43,7 @@
 
 import static java.io.ObjectStreamClass.processQueue;
 
+import sun.misc.SharedSecrets;
 import sun.misc.ObjectInputFilter;
 import sun.misc.ObjectStreamClassValidator;
 import sun.misc.SharedSecrets;
@@ -254,6 +255,12 @@
             public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {
                 return stream.getInternalObjectInputFilter();
             }
+
+            public void checkArray(ObjectInputStream stream, Class<?> arrayType, int arrayLength)
+                throws InvalidClassException
+            {
+                stream.checkArray(arrayType, arrayLength);
+            }
         });
     }
 
@@ -1257,6 +1264,33 @@
     }
 
     /**
+     * Checks the given array type and length to ensure that creation of such
+     * an array is permitted by this ObjectInputStream. The arrayType argument
+     * must represent an actual array type.
+     *
+     * This private method is called via SharedSecrets.
+     *
+     * @param arrayType the array type
+     * @param arrayLength the array length
+     * @throws NullPointerException if arrayType is null
+     * @throws IllegalArgumentException if arrayType isn't actually an array type
+     * @throws NegativeArraySizeException if arrayLength is negative
+     * @throws InvalidClassException if the filter rejects creation
+     */
+    private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {
+        Objects.requireNonNull(arrayType);
+        if (! arrayType.isArray()) {
+            throw new IllegalArgumentException("not an array type");
+        }
+
+        if (arrayLength < 0) {
+            throw new NegativeArraySizeException();
+        }
+
+        filterCheck(arrayType, arrayLength);
+    }
+
+    /**
      * Provide access to the persistent fields read from the input stream.
      */
     public static abstract class GetField {
--- a/src/share/classes/java/util/ArrayDeque.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/ArrayDeque.java	Fri Aug 18 00:47:21 2017 +0100
@@ -36,6 +36,7 @@
 
 import java.io.Serializable;
 import java.util.function.Consumer;
+import sun.misc.SharedSecrets;
 
 /**
  * Resizable-array implementation of the {@link Deque} interface.  Array
@@ -118,12 +119,7 @@
 
     // ******  Array allocation and resizing utilities ******
 
-    /**
-     * Allocates empty array to hold the given number of elements.
-     *
-     * @param numElements  the number of elements to hold
-     */
-    private void allocateElements(int numElements) {
+    private static int calculateSize(int numElements) {
         int initialCapacity = MIN_INITIAL_CAPACITY;
         // Find the best power of two to hold elements.
         // Tests "<=" because arrays aren't kept full.
@@ -139,7 +135,16 @@
             if (initialCapacity < 0)   // Too many elements, must back off
                 initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
         }
-        elements = new Object[initialCapacity];
+        return initialCapacity;
+    }
+
+    /**
+     * Allocates empty array to hold the given number of elements.
+     *
+     * @param numElements  the number of elements to hold
+     */
+    private void allocateElements(int numElements) {
+        elements = new Object[calculateSize(numElements)];
     }
 
     /**
@@ -879,6 +884,8 @@
 
         // Read in size and allocate array
         int size = s.readInt();
+        int capacity = calculateSize(size);
+        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
         allocateElements(size);
         head = 0;
         tail = size;
--- a/src/share/classes/java/util/ArrayList.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/ArrayList.java	Fri Aug 18 00:47:21 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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,6 +28,7 @@
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
+import sun.misc.SharedSecrets;
 
 /**
  * Resizable-array implementation of the <tt>List</tt> interface.  Implements
@@ -219,12 +220,15 @@
         }
     }
 
+    private static int calculateCapacity(Object[] elementData, int minCapacity) {
+        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
+            return Math.max(DEFAULT_CAPACITY, minCapacity);
+        }
+        return minCapacity;
+    }
+
     private void ensureCapacityInternal(int minCapacity) {
-        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
-            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
-        }
-
-        ensureExplicitCapacity(minCapacity);
+        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
     }
 
     private void ensureExplicitCapacity(int minCapacity) {
@@ -783,6 +787,8 @@
 
         if (size > 0) {
             // be like clone(), allocate array based upon size not capacity
+            int capacity = calculateCapacity(elementData, size);
+            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
             ensureCapacityInternal(size);
 
             Object[] a = elementData;
--- a/src/share/classes/java/util/HashMap.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/HashMap.java	Fri Aug 18 00:47:21 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -34,6 +34,7 @@
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import sun.misc.SharedSecrets;
 
 /**
  * Hash table based implementation of the <tt>Map</tt> interface.  This
@@ -1392,8 +1393,12 @@
             float ft = (float)cap * lf;
             threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
                          (int)ft : Integer.MAX_VALUE);
+
+            // Check Map.Entry[].class since it's the nearest public type to
+            // what we're actually creating.
+            SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, cap);
             @SuppressWarnings({"rawtypes","unchecked"})
-                Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
+            Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
             table = tab;
 
             // Read the keys and values, and put the mappings in the HashMap
--- a/src/share/classes/java/util/HashSet.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/HashSet.java	Fri Aug 18 00:47:21 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -26,6 +26,7 @@
 package java.util;
 
 import java.io.InvalidObjectException;
+import sun.misc.SharedSecrets;
 
 /**
  * This class implements the <tt>Set</tt> interface, backed by a hash table
@@ -316,12 +317,19 @@
             throw new InvalidObjectException("Illegal size: " +
                                              size);
         }
-
         // Set the capacity according to the size and load factor ensuring that
         // the HashMap is at least 25% full but clamping to maximum capacity.
         capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f),
                 HashMap.MAXIMUM_CAPACITY);
 
+        // Constructing the backing map will lazily create an array when the first element is
+        // added, so check it before construction. Call HashMap.tableSizeFor to compute the
+        // actual allocation size. Check Map.Entry[].class since it's the nearest public type to
+        // what is actually created.
+
+        SharedSecrets.getJavaOISAccess()
+                     .checkArray(s, Map.Entry[].class, HashMap.tableSizeFor(capacity));
+
         // Create backing HashMap
         map = (((HashSet<?>)this) instanceof LinkedHashSet ?
                new LinkedHashMap<E,Object>(capacity, loadFactor) :
--- a/src/share/classes/java/util/Hashtable.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/Hashtable.java	Fri Aug 18 00:47:21 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -30,6 +30,7 @@
 import java.util.function.BiConsumer;
 import java.util.function.Function;
 import java.util.function.BiFunction;
+import sun.misc.SharedSecrets;
 
 /**
  * This class implements a hash table, which maps keys to values. Any
@@ -1192,6 +1193,10 @@
         if (length > elements && (length & 1) == 0)
             length--;
         length = Math.min(length, origlength);
+
+        // Check Map.Entry[].class since it's the nearest public type to
+        // what we're actually creating.
+        SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, length);
         table = new Entry<?,?>[length];
         threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
         count = 0;
--- a/src/share/classes/java/util/IdentityHashMap.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/IdentityHashMap.java	Fri Aug 18 00:47:21 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -29,6 +29,7 @@
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
+import sun.misc.SharedSecrets;
 
 /**
  * This class implements the <tt>Map</tt> interface with a hash table, using
@@ -1304,7 +1305,9 @@
         if (size < 0)
             throw new java.io.StreamCorruptedException
                 ("Illegal mappings count: " + size);
-        init(capacity(size));
+        int cap = capacity(size);
+        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, cap);
+        init(cap);
 
         // Read the keys and values, and put the mappings in the table
         for (int i=0; i<size; i++) {
--- a/src/share/classes/java/util/PriorityQueue.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/PriorityQueue.java	Fri Aug 18 00:47:21 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,7 @@
 package java.util;
 
 import java.util.function.Consumer;
+import sun.misc.SharedSecrets;
 
 /**
  * An unbounded priority {@linkplain Queue queue} based on a priority heap.
@@ -784,6 +785,7 @@
         // Read in (and discard) array length
         s.readInt();
 
+        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, size);
         queue = new Object[size];
 
         // Read in all elements.
--- a/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri Aug 18 00:47:21 2017 +0100
@@ -50,6 +50,7 @@
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
+import sun.misc.SharedSecrets;
 
 /**
  * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
@@ -989,6 +990,7 @@
 
         // Read in array length and allocate array
         int len = s.readInt();
+        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, len);
         Object[] elements = new Object[len];
 
         // Read in all elements in the proper order.
--- a/src/share/classes/sun/misc/JavaOISAccess.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/src/share/classes/sun/misc/JavaOISAccess.java	Fri Aug 18 00:47:21 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -25,9 +25,12 @@
 
 package sun.misc;
 
+import java.io.InvalidClassException;
 import java.io.ObjectInputStream;
 
 public interface JavaOISAccess {
     void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter);
     ObjectInputFilter getObjectInputFilter(ObjectInputStream stream);
+    void checkArray(ObjectInputStream stream, Class<?> arrayType, int arrayLength)
+        throws InvalidClassException;
 }
--- a/src/share/classes/sun/misc/JavaObjectInputStreamAccess.java	Mon Aug 21 13:32:56 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * 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.  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.misc;
-
-import java.io.ObjectInputStream;
-
-/**
- * The interface to specify methods for accessing {@code ObjectInputStream}
- * @author sjiang
- */
-public interface JavaObjectInputStreamAccess {
-    /**
-     * Sets a descriptor validating.
-     * @param ois stream to have the descriptors validated
-     * @param validator validator used to validate a descriptor.
-     */
-    public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator);
-}
--- a/src/share/classes/sun/misc/ObjectStreamClassValidator.java	Mon Aug 21 13:32:56 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * 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.  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.misc;
-
-import java.io.ObjectStreamClass;
-
-/**
- * A callback used by {@code ObjectInputStream} to do descriptor validation.
- *
- * @author sjiang
- */
-public interface ObjectStreamClassValidator {
-    /**
-     * This method will be called by ObjectInputStream to
-     * check a descriptor just before creating an object described by this descriptor.
-     * The object will not be created if this method throws a {@code RuntimeException}.
-     * @param descriptor descriptor to be checked.
-     */
-    public void validateDescriptor(ObjectStreamClass descriptor);
-}
--- a/test/java/io/Serializable/serialFilter/SerialFilterTest.java	Mon Aug 21 13:32:56 2017 -0700
+++ b/test/java/io/Serializable/serialFilter/SerialFilterTest.java	Fri Aug 18 00:47:21 2017 +0100
@@ -35,9 +35,11 @@
 import java.lang.reflect.Proxy;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.LongAdder;
 
 import sun.misc.ObjectInputFilter;
@@ -154,6 +156,11 @@
                 interfaces, (p, m, args) -> p);
 
         Runnable runnable = (Runnable & Serializable) SerialFilterTest::noop;
+
+        List<Class<?>> classList = new ArrayList<>();
+        classList.add(HashSet.class);
+        classList.addAll(Collections.nCopies(21, Map.Entry[].class));
+
         Object[][] objects = {
                 { null, 0, -1, 0, 0, 0,
                         Arrays.asList()},        // no callback, no values
@@ -173,8 +180,7 @@
                                 objArray.getClass(),
                                 SerialFilterTest.class,
                                 java.lang.invoke.SerializedLambda.class)},
-                { deepHashSet(10), 48, -1, 50, 11, 619,
-                        Arrays.asList(HashSet.class)},
+                { deepHashSet(10), 69, 4, 50, 11, 619, classList },
                 { proxy.getClass(), 3, -1, 2, 2, 112,
                         Arrays.asList(Runnable.class,
                                 java.lang.reflect.Proxy.class,