/* * Copyright (c) 2013-2014, Pierre Laporte * * 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 3 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 * for more details. * * You should have received a copy of the GNU General Public License * along with this work; if not, see <http://www.gnu.org/licenses/>. */ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.concurrent.CountDownLatch; public class SimpleTest { static class ClassWithLocks { final Object lock = new Object(); static class InternalException extends RuntimeException { InternalException(String message) { super(message); } } static synchronized long staticSynchronizedMethodWithDelegate() { return staticSynchronizedMethod(); } static synchronized long staticSynchronizedMethod() { return 1L; } synchronized long synchronizedMethodWithDelegate() { return synchronizedMethod(); } synchronized long synchronizedMethod() { return 2L; } long synchronizedBlockWithDelegate() { synchronized (lock) { return synchronizedBlock(); } } long synchronizedBlock() { synchronized (lock) { return 3L; } } synchronized static long staticSynchronizedMethodWithException() { throw new InternalException("From static method"); } synchronized long synchronizedMethodWithException() { throw new InternalException("From instance method"); } long synchronizedBlockWithException() { synchronized (lock) { throw new InternalException("From static block"); } } } public static void main(String... args) throws Exception { System.out.println("INFO - This test will create threads with the following behaviour :"); System.out.println("INFO - * staticSynchronizedMethodWithDelegate - accesses 2 synchronized static methods (reentrant) and returns normally"); System.out.println("INFO - * synchronizedMethodWithDelegate - accesses 2 synchronized instance methods (reentrant) and returns normally"); System.out.println("INFO - * synchronizedBlockWithDelegate - accesses 2 synchronized blocks (reentrant) and returns normally"); System.out.println("INFO - * staticSynchronizedMethodWithException - accesses 1 synchronized static method and throw an Exception"); System.out.println("INFO - * synchronizedMethodWithException - accesses 1 synchronized instance method and throw an Exception"); System.out.println("INFO - * synchronizedBlockWithException - accesses 1 synchronized block and throw an Exception"); System.out.println(""); PrintStream stdErr = System.err; try (ByteArrayOutputStream interceptedStdErrBuffer = new ByteArrayOutputStream(); PrintStream interceptedStdErr = new PrintStream(interceptedStdErrBuffer, true)) { System.setErr(interceptedStdErr); CountDownLatch countDownLatch = new CountDownLatch(6); startStaticSynchronizedNethodWithDelegate(countDownLatch); startSynchonizedMethodWithDelegate(countDownLatch); startSynchronizedBlockWithDelegate(countDownLatch); startStaticSynchronizedMethodWithException(countDownLatch); startSynchronizedMethodWithException(countDownLatch); startSynchronizedBlocksWithException(countDownLatch); countDownLatch.await(); Thread.sleep(1600); String errorMessages = interceptedStdErrBuffer.toString(); if (errorMessages.length() > 0) { System.err.println("ERROR - the test generated data on stderr, this should not happen"); System.err.println("ERROR - content of stderr :"); System.err.println(errorMessages); } else { System.out.println("Test completed. Now please check the output file."); } } finally { System.setErr(stdErr); } } private static void startStaticSynchronizedNethodWithDelegate(final CountDownLatch countDownLatch) { new Thread(new Runnable() { @Override public void run() { Thread.currentThread().setName("staticSynchronizedMethodWithDelegate"); ClassWithLocks.staticSynchronizedMethodWithDelegate(); countDownLatch.countDown(); } }).start(); } private static void startSynchonizedMethodWithDelegate(final CountDownLatch countDownLatch) { final ClassWithLocks classWithLocks = new ClassWithLocks(); new Thread(new Runnable() { @Override public void run() { Thread.currentThread().setName("synchronizedMethodWithDelegate"); classWithLocks.synchronizedMethodWithDelegate(); countDownLatch.countDown(); } }).start(); } private static void startSynchronizedBlockWithDelegate(final CountDownLatch countDownLatch) { final ClassWithLocks classWithLocks = new ClassWithLocks(); new Thread(new Runnable() { @Override public void run() { Thread.currentThread().setName("synchronizedBlockWithDelegate"); classWithLocks.synchronizedBlockWithDelegate(); countDownLatch.countDown(); } }).start(); } private static void startStaticSynchronizedMethodWithException(final CountDownLatch countDownLatch) { new Thread(new Runnable() { @Override public void run() { Thread.currentThread().setName("staticSynchronizedMethodWithException"); try { ClassWithLocks.staticSynchronizedMethodWithException(); } catch (ClassWithLocks.InternalException ignored) { } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } } }).start(); } private static void startSynchronizedMethodWithException(final CountDownLatch countDownLatch) { final ClassWithLocks classWithLocks = new ClassWithLocks(); new Thread(new Runnable() { @Override public void run() { Thread.currentThread().setName("synchronizedMethodWithException"); try { classWithLocks.synchronizedMethodWithException(); } catch (ClassWithLocks.InternalException ignored) { } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } } }).start(); } private static void startSynchronizedBlocksWithException(final CountDownLatch countDownLatch) { final ClassWithLocks classWithLocks = new ClassWithLocks(); new Thread(new Runnable() { @Override public void run() { Thread.currentThread().setName("synchronizedBlockWithException"); try { classWithLocks.synchronizedBlockWithException(); } catch (ClassWithLocks.InternalException ignored) { } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } } }).start(); } }