changeset 1714:1f0e2f569ca6

8174109: Better queuing priorities Reviewed-by: smarks
author robm
date Fri, 18 Aug 2017 00:47:21 +0100
parents 5d7b53da7f1b
children 80795118c4aa
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 test/java/io/Serializable/serialFilter/SerialFilterTest.java
diffstat 11 files changed, 101 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/io/ObjectInputStream.java	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/io/ObjectInputStream.java	Fri Aug 18 00:47:21 2017 +0100
@@ -254,6 +254,12 @@
             public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {
                 return stream.getInternalObjectInputFilter();
             }
+
+            public void checkArray(ObjectInputStream stream, Class<?> arrayType, int arrayLength)
+                throws InvalidClassException
+            {
+                stream.checkArray(arrayType, arrayLength);
+            }
         });
     }
 
@@ -1260,6 +1266,36 @@
     }
 
     /**
+     * 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 {
+        if (arrayType == null) {
+            throw new NullPointerException();
+        }
+
+        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	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/ArrayDeque.java	Fri Aug 18 00:47:21 2017 +0100
@@ -33,6 +33,8 @@
  */
 
 package java.util;
+import sun.misc.SharedSecrets;
+
 import java.io.*;
 
 /**
@@ -116,12 +118,7 @@
 
     // ******  Array allocation and resizing utilities ******
 
-    /**
-     * Allocate 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.
@@ -137,7 +134,16 @@
             if (initialCapacity < 0)   // Too many elements, must back off
                 initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
         }
-        elements = (E[]) 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 = (E[]) new Object[calculateSize(numElements)];
     }
 
     /**
@@ -855,6 +861,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	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/ArrayList.java	Fri Aug 18 00:47:21 2017 +0100
@@ -25,6 +25,8 @@
 
 package java.util;
 
+import sun.misc.SharedSecrets;
+
 /**
  * Resizable-array implementation of the <tt>List</tt> interface.  Implements
  * all optional list operations, and permits all elements, including
@@ -689,6 +691,7 @@
 
         // Read in array length and allocate array
         int arrayLength = s.readInt();
+        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, arrayLength);
         Object[] a = elementData = new Object[arrayLength];
 
         // Read in all elements in the proper order.
--- a/src/share/classes/java/util/HashMap.java	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/HashMap.java	Fri Aug 18 00:47:21 2017 +0100
@@ -24,6 +24,8 @@
  */
 
 package java.util;
+import sun.misc.SharedSecrets;
+
 import java.io.*;
 
 /**
@@ -1034,6 +1036,9 @@
 
         // Read in number of buckets and allocate the bucket array;
         int numBuckets = s.readInt();
+        // Check Map.Entry[].class since it's the nearest public type to
+        // what we're actually creating.
+        SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, numBuckets);
         table = new Entry[numBuckets];
 
         init();  // Give subclass a chance to do its thing.
--- a/src/share/classes/java/util/HashSet.java	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/HashSet.java	Fri Aug 18 00:47:21 2017 +0100
@@ -25,6 +25,8 @@
 
 package java.util;
 
+import sun.misc.SharedSecrets;
+
 /**
  * This class implements the <tt>Set</tt> interface, backed by a hash table
  * (actually a <tt>HashMap</tt> instance).  It makes no guarantees as to the
@@ -296,6 +298,18 @@
         // Read in HashMap capacity and load factor and create backing HashMap
         int capacity = s.readInt();
         float loadFactor = s.readFloat();
+
+        // Check Map.Entry[].class since it's the nearest public type to
+        // what is actually created.
+        //
+        // Find a power of 2 >= capacity
+        int cap = 1;
+        while (cap < capacity)
+            cap <<= 1;
+
+        SharedSecrets.getJavaOISAccess()
+                .checkArray(s, Map.Entry[].class, cap);
+
         map = (((HashSet)this) instanceof LinkedHashSet ?
                new LinkedHashMap<E,Object>(capacity, loadFactor) :
                new HashMap<E,Object>(capacity, loadFactor));
--- a/src/share/classes/java/util/Hashtable.java	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/Hashtable.java	Fri Aug 18 00:47:21 2017 +0100
@@ -24,6 +24,8 @@
  */
 
 package java.util;
+import sun.misc.SharedSecrets;
+
 import java.io.*;
 
 /**
@@ -867,6 +869,9 @@
         if (origlength > 0 && length > origlength)
             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);
         Entry[] table = new Entry[length];
         count = 0;
 
--- a/src/share/classes/java/util/IdentityHashMap.java	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/IdentityHashMap.java	Fri Aug 18 00:47:21 2017 +0100
@@ -24,6 +24,8 @@
  */
 
 package java.util;
+import sun.misc.SharedSecrets;
+
 import java.io.*;
 
 /**
@@ -1197,7 +1199,9 @@
         int size = s.readInt();
 
         // Allow for 33% growth (i.e., capacity is >= 2* size()).
-        init(capacity((size*4)/3));
+        int cap = capacity((size*4)/3);
+        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	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/PriorityQueue.java	Fri Aug 18 00:47:21 2017 +0100
@@ -25,6 +25,8 @@
 
 package java.util;
 
+import sun.misc.SharedSecrets;
+
 /**
  * An unbounded priority {@linkplain Queue queue} based on a priority heap.
  * The elements of the priority queue are ordered according to their
@@ -724,6 +726,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	Thu Dec 15 13:49:59 2016 +0300
+++ b/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri Aug 18 00:47:21 2017 +0100
@@ -36,6 +36,8 @@
 package java.util.concurrent;
 import java.util.*;
 import java.util.concurrent.locks.*;
+
+import sun.misc.SharedSecrets;
 import sun.misc.Unsafe;
 
 /**
@@ -870,6 +872,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	Thu Dec 15 13:49:59 2016 +0300
+++ 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/test/java/io/Serializable/serialFilter/SerialFilterTest.java	Thu Dec 15 13:49:59 2016 +0300
+++ b/test/java/io/Serializable/serialFilter/SerialFilterTest.java	Fri Aug 18 00:47:21 2017 +0100
@@ -32,12 +32,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import javax.lang.model.SourceVersion;
 
@@ -142,6 +137,10 @@
         Object[] objArray = new Object[7];
         objArray[objArray.length - 1] = objArray;
 
+        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
@@ -153,8 +152,9 @@
                         Arrays.asList(SerialFilterTest.class)},
                 { new byte[14], 2, 14, 2, 1, 27,
                         Arrays.asList(byteArray.getClass(), byteArray.getClass())},
-                { deepHashSet(10), 48, -1, 50, 11, 619,
-                        Arrays.asList(HashSet.class)},
+                // maxarray changed for Java 6 from "4" to "16"
+                // HashSet.readObject isn't optimal, see JDK-8016252
+                { deepHashSet(10), 69, 16, 50, 11, 619, classList },
         };
         return objects;
     }