8215359: InnocuousForkJoinWorkerThread.setContextClassLoader needlessly throws
authordl
Fri, 15 Feb 2019 11:18:01 -0800
changeset 53779 709631caffa3
parent 53778 4f1040869d24
child 53780 d04f72c354e9
8215359: InnocuousForkJoinWorkerThread.setContextClassLoader needlessly throws Reviewed-by: martin, chegar, dholmes, reinhapa, alanb
src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
test/jdk/java/util/concurrent/tck/ForkJoinPool9Test.java
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Fri Feb 15 11:18:01 2019 -0800
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Fri Feb 15 11:18:01 2019 -0800
@@ -236,7 +236,8 @@
 
         @Override // paranoically
         public void setContextClassLoader(ClassLoader cl) {
-            throw new SecurityException("setContextClassLoader");
+            if (cl != null && ClassLoader.getSystemClassLoader() != cl)
+                throw new SecurityException("setContextClassLoader");
         }
     }
 }
--- a/test/jdk/java/util/concurrent/tck/ForkJoinPool9Test.java	Fri Feb 15 11:18:01 2019 -0800
+++ b/test/jdk/java/util/concurrent/tck/ForkJoinPool9Test.java	Fri Feb 15 11:18:01 2019 -0800
@@ -38,6 +38,8 @@
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.ForkJoinTask;
 import java.util.concurrent.Future;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Stream;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -67,21 +69,33 @@
             .findVarHandle(Thread.class, "contextClassLoader", ClassLoader.class);
         ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
         boolean haveSecurityManager = (System.getSecurityManager() != null);
-        CountDownLatch taskStarted = new CountDownLatch(1);
+        CountDownLatch runInCommonPoolStarted = new CountDownLatch(1);
+        ClassLoader classLoaderDistinctFromSystemClassLoader
+            = ClassLoader.getPlatformClassLoader();
+        assertNotSame(classLoaderDistinctFromSystemClassLoader,
+                      systemClassLoader);
         Runnable runInCommonPool = () -> {
-            taskStarted.countDown();
+            runInCommonPoolStarted.countDown();
             assertTrue(ForkJoinTask.inForkJoinPool());
-            assertSame(ForkJoinPool.commonPool(),
-                       ForkJoinTask.getPool());
-            assertSame(systemClassLoader,
-                       Thread.currentThread().getContextClassLoader());
-            assertSame(systemClassLoader,
-                       CCL.get(Thread.currentThread()));
+            assertSame(ForkJoinPool.commonPool(), ForkJoinTask.getPool());
+            Thread currentThread = Thread.currentThread();
+
+            Stream.of(systemClassLoader, null).forEach(cl -> {
+                if (ThreadLocalRandom.current().nextBoolean())
+                    // should always be permitted, without effect
+                    currentThread.setContextClassLoader(cl);
+                });
+
+            Stream.of(currentThread.getContextClassLoader(),
+                      (ClassLoader) CCL.get(currentThread))
+            .forEach(cl -> assertTrue(cl == systemClassLoader || cl == null));
+
             if (haveSecurityManager)
                 assertThrows(
                     SecurityException.class,
                     () -> System.getProperty("foo"),
-                    () -> Thread.currentThread().setContextClassLoader(null));
+                    () -> currentThread.setContextClassLoader(
+                        classLoaderDistinctFromSystemClassLoader));
             // TODO ?
 //          if (haveSecurityManager
 //              && Thread.currentThread().getClass().getSimpleName()
@@ -91,7 +105,7 @@
         Future<?> f = ForkJoinPool.commonPool().submit(runInCommonPool);
         // Ensure runInCommonPool is truly running in the common pool,
         // by giving this thread no opportunity to "help" on get().
-        await(taskStarted);
+        await(runInCommonPoolStarted);
         assertNull(f.get());
     }