@Test
public void utilityAppearsThreadSafe()
        throws Exception {

    int threads = 10;
    int iterations = 500;
    ExecutorService exec = Executors.newFixedThreadPool(threads);
    final Method defineClass1 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
    final Method defineClass2 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class);
    final CountDownLatch start = new CountDownLatch(1);
    final CountDownLatch done = new CountDownLatch(threads * iterations);
    final List<Class<?>> newClasses = Collections.synchronizedList(new ArrayList<Class<?>>(threads));
    for (int i = 0; i < threads * iterations; i++) {
        exec.submit(new Runnable() {
            public void run() {
                try {
                    String newName = makeNewName();
                    CtClass newClass = pool.makeClass(newName);
                    start.await();
                    // aggressively test isAccessible on the methods. they should only be accessible to
                    // one thread at a time, only within the toClass method, for a very brief time
                    assertFalse(defineClass1.isAccessible());
                    assertFalse(defineClass2.isAccessible());
                    Class<Object> theNewClass = ClassLoadingUtil.toClass(newClass);
                    assertFalse(defineClass1.isAccessible());
                    assertFalse(defineClass2.isAccessible());
                    newClasses.add(theNewClass);
                } catch (Exception e) {
                    // ignore
                } finally {
                    done.countDown();
                }
            }
        });
    }
    start.countDown();
    done.await();
    assertEquals("Bug in test", 0, exec.shutdownNow().size());
    assertEquals(threads * iterations, newClasses.size());
    assertFalse(defineClass1.isAccessible());
    assertFalse(defineClass2.isAccessible());
}