< prev index next >

src/java.base/share/classes/java/util/Hashtable.java

Print this page

        

*** 1135,1148 **** private void writeObject(java.io.ObjectOutputStream s) throws IOException { Entry<Object, Object> entryStack = null; synchronized (this) { ! // Write out the length, threshold, loadfactor s.defaultWriteObject(); ! // Write out length, count of elements s.writeInt(table.length); s.writeInt(count); // Stack copies of the entries in the table for (Entry<?, ?> entry : table) { --- 1135,1148 ---- private void writeObject(java.io.ObjectOutputStream s) throws IOException { Entry<Object, Object> entryStack = null; synchronized (this) { ! // Write out the threshold and loadFactor s.defaultWriteObject(); ! // Write out length and count of elements s.writeInt(table.length); s.writeInt(count); // Stack copies of the entries in the table for (Entry<?, ?> entry : table) {
*** 1167,1203 **** * Reconstitute the Hashtable from a stream (i.e., deserialize it). */ private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { ! // Read in the length, threshold, and loadfactor s.defaultReadObject(); // Read the original length of the array and number of elements int origlength = s.readInt(); int elements = s.readInt(); ! // Compute new size with a bit of room 5% to grow but ! // no larger than the original size. Make the length // odd if it's large enough, this helps distribute the entries. // Guard against the length ending up zero, that's not valid. ! int length = (int)(elements * loadFactor) + (elements / 20) + 3; if (length > elements && (length & 1) == 0) length--; ! if (origlength > 0 && length > origlength) ! length = origlength; table = new Entry<?,?>[length]; threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1); count = 0; // Read the number of elements and then all the key/value objects for (; elements > 0; elements--) { @SuppressWarnings("unchecked") K key = (K)s.readObject(); @SuppressWarnings("unchecked") V value = (V)s.readObject(); ! // synch could be eliminated for performance reconstitutionPut(table, key, value); } } /** --- 1167,1214 ---- * Reconstitute the Hashtable from a stream (i.e., deserialize it). */ private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { ! // Read in the threshold and loadFactor s.defaultReadObject(); + // Validate loadFactor (ignore threshold - it will be re-computed) + if (loadFactor <= 0 || Float.isNaN(loadFactor)) + throw new StreamCorruptedException("Illegal Load: " + loadFactor); + // Read the original length of the array and number of elements int origlength = s.readInt(); int elements = s.readInt(); ! // Validate # of elements ! if (elements < 0) ! throw new StreamCorruptedException("Illegal # of Elements: " + elements); ! ! // Clamp original length to be more than elements / loadFactor ! // (this is the invariant enforced with auto-growth) ! origlength = Math.max(origlength, (int)(elements / loadFactor) + 1); ! ! // Compute new length with a bit of room 5% + 3 to grow but ! // no larger than the clamped original length. Make the length // odd if it's large enough, this helps distribute the entries. // Guard against the length ending up zero, that's not valid. ! int length = (int)((elements + elements / 20) / loadFactor) + 3; if (length > elements && (length & 1) == 0) length--; ! length = Math.min(length, origlength); table = new Entry<?,?>[length]; threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1); count = 0; // Read the number of elements and then all the key/value objects for (; elements > 0; elements--) { @SuppressWarnings("unchecked") K key = (K)s.readObject(); @SuppressWarnings("unchecked") V value = (V)s.readObject(); ! // sync is eliminated for performance reconstitutionPut(table, key, value); } } /**
*** 1205,1217 **** * is overridable and should not be called in readObject since the * subclass will not yet be initialized. * * <p>This differs from the regular put method in several ways. No * checking for rehashing is necessary since the number of elements ! * initially in the table is known. The modCount is not incremented ! * because we are creating a new instance. Also, no return value ! * is needed. */ private void reconstitutionPut(Entry<?,?>[] tab, K key, V value) throws StreamCorruptedException { if (value == null) { --- 1216,1228 ---- * is overridable and should not be called in readObject since the * subclass will not yet be initialized. * * <p>This differs from the regular put method in several ways. No * checking for rehashing is necessary since the number of elements ! * initially in the table is known. The modCount is not incremented and ! * there's no synchronization because we are creating a new instance. ! * Also, no return value is needed. */ private void reconstitutionPut(Entry<?,?>[] tab, K key, V value) throws StreamCorruptedException { if (value == null) {
< prev index next >