# HG changeset patch # User bchristi # Date 1477425514 25200 # Node ID ffa31454ab0fabf330651702930cb562ed2dbd5a # Parent 0c5a98b2e56c4b83c40eb8a1d379d61775707003 8165793: Provide an API to query if a ClassLoader is parallel capable Reviewed-by: alanb, mchung diff -r 0c5a98b2e56c -r ffa31454ab0f jdk/src/java.base/share/classes/java/lang/ClassLoader.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. * *

Class loaders that support concurrent loading of classes are known as - * parallel capable class loaders and are required to register - * themselves at their class initialization time by invoking the - * {@link + * {@linkplain #isParallelCapable() parallel capable} class loaders and + * are required to register themselves at their class initialization time by + * invoking the {@link * #registerAsParallelCapable ClassLoader.registerAsParallelCapable} * method. Note that the ClassLoader 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: *

    @@ -1448,8 +1448,10 @@ *

    Note that once a class loader is registered as parallel capable, there * is no way to change it back.

    * - * @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()}). diff -r 0c5a98b2e56c -r ffa31454ab0f jdk/test/java/lang/ClassLoader/IsParallelCapable.java --- /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 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); + } + } +}