/* * Copyright (c) 2014, 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.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.Hashtable; /** * @test * @bug 8068427 * @summary Hashtable deserialization reconstitutes table with wrong capacity */ public class DeserializedLength { static boolean testDeserializedLength(int elements) throws Exception { // construct Hashtable float loadFactor = 0.75f; Hashtable ht1 = new Hashtable<>( (int) (elements / loadFactor) + 1, loadFactor ); for (int i = 0; i < elements; i++) { ht1.put(i, i); } // serialize it to byte[] array byte[] bytes; try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(ht1); oos.flush(); bytes = baos.toByteArray(); } // de-serialize it from byte[] array Hashtable ht2; try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais)) { ht2 = (Hashtable) ois.readObject(); } // compare lengths of internal tables Object[] table1 = (Object[]) hashtableTableField.get(ht1); Object[] table2 = (Object[]) hashtableTableField.get(ht2); System.out.println("Serialized Hashtable of size=" + ht1.size() + " has internal table.length=" + table1.length + " de-serialized table.length=" + table2.length); return table2.length >= table1.length; } private static final Field hashtableTableField; static { try { hashtableTableField = Hashtable.class.getDeclaredField("table"); hashtableTableField.setAccessible(true); } catch (NoSuchFieldException e) { throw new Error(e); } } public static void main(String[] args) throws Exception { boolean ok = true; ok &= testDeserializedLength(10); ok &= testDeserializedLength(50); ok &= testDeserializedLength(500); ok &= testDeserializedLength(5000); if (!ok) { throw new AssertionError("Test failed."); } } }