Path: blob/master/test/jdk/java/util/Hashtable/SerializationDeadlock.java
41149 views
/*1* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22* -------------------------------------------23*24* Portions Copyright (c) 2010, 2011 IBM Corporation25*/2627/*28* @test29* @bug 692748630* @summary Serializing Hashtable objects which refer to each other should not be able to deadlock.31* @author Neil Richards <[email protected]>, <[email protected]>32*/3334import java.io.ByteArrayOutputStream;35import java.io.IOException;36import java.io.ObjectOutputStream;37import java.io.PrintWriter;38import java.io.Serializable;39import java.io.StringWriter;40import java.util.ArrayList;41import java.util.Hashtable;42import java.util.List;43import java.util.concurrent.CyclicBarrier;4445public class SerializationDeadlock {46public static void main(final String[] args) throws Exception {47// Test for Hashtable serialization deadlock48final Hashtable<Object, Object> h1 = new Hashtable<>();49final Hashtable<Object, Object> h2 = new Hashtable<>();50final TestBarrier testStart = new TestBarrier(3);5152// Populate the hashtables so that they refer to each other53h1.put(testStart, h2);54h2.put(testStart, h1);5556final CyclicBarrier testEnd = new CyclicBarrier(3);57final TestThread t1 = new TestThread(h1, testEnd);58final TestThread t2 = new TestThread(h2, testEnd);5960t1.start();61t2.start();6263// Wait for both test threads to have initiated serialization64// of the 'testStart' object (and hence of both 'h1' and 'h2')65testStart.await();6667// Wait for both test threads to successfully finish serialization68// of 'h1' and 'h2'.69System.out.println("Waiting for Hashtable serialization to complete ...");70System.out.println("(This test will hang if serialization deadlocks)");71testEnd.await();72System.out.println("Test PASSED: serialization completed successfully");7374TestThread.handleExceptions();75}7677static final class TestBarrier extends CyclicBarrier78implements Serializable {79public TestBarrier(final int count) {80super(count);81}8283private void writeObject(final ObjectOutputStream oos)84throws IOException {85oos.defaultWriteObject();86// Wait until all test threads have started serializing data87try {88await();89} catch (final Exception e) {90throw new IOException("Test ERROR: Unexpected exception caught", e);91}92}93}9495static final class TestThread extends Thread {96private static final List<Exception> exceptions = new ArrayList<>();9798private final Hashtable<Object, Object> hashtable;99private final CyclicBarrier testEnd;100101public TestThread(final Hashtable<Object, Object> hashtable,102final CyclicBarrier testEnd) {103this.hashtable = hashtable;104this.testEnd = testEnd;105setDaemon(true);106}107108public void run() {109try {110final ByteArrayOutputStream baos = new ByteArrayOutputStream();111final ObjectOutputStream oos = new ObjectOutputStream(baos);112113oos.writeObject(hashtable);114oos.close();115} catch (final IOException ioe) {116addException(ioe);117} finally {118try {119testEnd.await();120} catch (Exception e) {121addException(e);122}123}124}125126private static synchronized void addException(final Exception exception) {127exceptions.add(exception);128}129130public static synchronized void handleExceptions() {131if (false == exceptions.isEmpty()) {132throw new RuntimeException(getErrorText(exceptions));133}134}135136private static String getErrorText(final List<Exception> exceptions) {137final StringWriter sw = new StringWriter();138final PrintWriter pw = new PrintWriter(sw);139140pw.println("Test ERROR: Unexpected exceptions thrown on test threads:");141for (Exception exception : exceptions) {142pw.print("\t");143pw.println(exception);144for (StackTraceElement element : exception.getStackTrace()) {145pw.print("\t\tat ");146pw.println(element);147}148}149150pw.close();151return sw.toString();152}153}154}155156157158