8165793: Provide an API to query if a ClassLoader is parallel capable
authorbchristi
Tue, 25 Oct 2016 12:58:34 -0700
changeset 41753 ffa31454ab0f
parent 41752 0c5a98b2e56c
child 41754 8b7c8d5e9a0d
8165793: Provide an API to query if a ClassLoader is parallel capable Reviewed-by: alanb, mchung
jdk/src/java.base/share/classes/java/lang/ClassLoader.java
jdk/test/java/lang/ClassLoader/IsParallelCapable.java
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Tue Oct 25 07:38:50 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Tue Oct 25 12:58:34 2016 -0700
@@ -104,9 +104,9 @@
  * class or resource itself.
  *
  * <p> Class loaders that support concurrent loading of classes are known as
- * <em>parallel capable</em> class loaders and are required to register
- * themselves at their class initialization time by invoking the
- * {@link
+ * <em>{@linkplain #isParallelCapable() parallel capable}</em> class loaders and
+ * are required to register themselves at their class initialization time by
+ * invoking the {@link
  * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
  * method. Note that the <tt>ClassLoader</tt> class is registered as parallel
  * capable by default. However, its subclasses still need to register themselves
@@ -1437,7 +1437,7 @@
     }
 
     /**
-     * Registers the caller as parallel capable.
+     * Registers the caller as {@linkplain #isParallelCapable() parallel capable}.
      * The registration succeeds if and only if all of the following
      * conditions are met:
      * <ol>
@@ -1448,8 +1448,10 @@
      * <p>Note that once a class loader is registered as parallel capable, there
      * is no way to change it back.</p>
      *
-     * @return  true if the caller is successfully registered as
-     *          parallel capable and false if otherwise.
+     * @return  {@code true} if the caller is successfully registered as
+     *          parallel capable and {@code false} if otherwise.
+     *
+     * @see #isParallelCapable()
      *
      * @since   1.7
      */
@@ -1461,6 +1463,22 @@
     }
 
     /**
+     * Returns {@code true} if this class loader is
+     * {@linkplain #registerAsParallelCapable parallel capable}, otherwise
+     * {@code false}.
+     *
+     * @return  {@code true} if this class loader is parallel capable,
+     *          otherwise {@code false}.
+     *
+     * @see #registerAsParallelCapable()
+     *
+     * @since   9
+     */
+    public final boolean isParallelCapable() {
+        return ParallelLoaders.isRegistered(this.getClass());
+    }
+
+    /**
      * Find a resource of the specified name from the search path used to load
      * classes.  This method locates the resource through the system class
      * loader (see {@link #getSystemClassLoader()}).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ClassLoader/IsParallelCapable.java	Tue Oct 25 12:58:34 2016 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @bug 8165793
+ * @summary Test ClassLoader.isParallelCapable() method
+ * @run main IsParallelCapable
+ */
+
+import java.util.stream.Stream;
+
+public class IsParallelCapable {
+    public abstract static class TestCL extends ClassLoader {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        public abstract boolean expectCapable();
+        public Class findClass(String name) throws ClassNotFoundException {
+            throw new ClassNotFoundException("Why are you using this?");
+        }
+    }
+
+    public static class ParaCL extends TestCL {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        @Override
+        public boolean expectCapable() { return true; }
+    }
+
+    public static class NonParaCL extends TestCL {
+        @Override
+        public boolean expectCapable() {
+            // Doesn't call registerAsParallelCapable()
+            return false;
+        }
+    }
+
+    public static class NonParaSubCL1 extends ParaCL {
+        @Override
+        public boolean expectCapable() {
+            // Doesn't call registerAsParallelCapable()
+            return false;
+        }
+    }
+
+    public static class NonParaSubCL2 extends NonParaCL {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        @Override
+        public boolean expectCapable() {
+            // Superclass is not parallel capable
+            return false;
+        }
+    }
+
+    public static class ParaSubCL extends ParaCL {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        @Override
+        public boolean expectCapable() { return true; }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!ClassLoader.getSystemClassLoader().isParallelCapable()) {
+            throw new RuntimeException("System classloader not parallel capable!?");
+        }
+
+        Stream.of(ParaCL.class,
+                  NonParaCL.class,
+                  NonParaSubCL1.class,
+                  NonParaSubCL2.class,
+                  ParaSubCL.class)
+                .forEach(IsParallelCapable::testClassLoaderClass);
+    }
+
+    private static void testClassLoaderClass(Class<? extends TestCL> klazz) {
+        try {
+            TestCL cl = (TestCL)klazz.newInstance();
+            if (cl.expectCapable() != cl.isParallelCapable()) {
+                throw new RuntimeException(klazz + " expectCapable: " +
+                        cl.expectCapable() + ", isParallelCapable: " +
+                        cl.isParallelCapable());
+            } else {
+                System.out.println(klazz + " passed");
+            }
+        } catch (InstantiationException |  IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}