# HG changeset patch # User iklam # Date 1569197795 25200 # Node ID 704e4ff399a2ea0351a2566c17f0906195b21715 # Parent 14c1ff687621c18a5be3abd2b0a60d82c18b874c 8231125: Improve testing of parallel loading of shared classes by the boot class loader Reviewed-by: ccheung, coleenp, dholmes diff -r 14c1ff687621 -r 704e4ff399a2 src/hotspot/share/classfile/systemDictionary.cpp --- a/src/hotspot/share/classfile/systemDictionary.cpp Sat Sep 21 10:13:25 2019 -0400 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Sun Sep 22 17:16:35 2019 -0700 @@ -1270,6 +1270,7 @@ TRAPS) { if (ik != NULL) { + assert(!ik->is_unshareable_info_restored(), "shared class can be loaded only once"); Symbol* class_name = ik->name(); bool visible = is_shared_class_visible( diff -r 14c1ff687621 -r 704e4ff399a2 src/hotspot/share/oops/klass.hpp --- a/src/hotspot/share/oops/klass.hpp Sat Sep 21 10:13:25 2019 -0400 +++ b/src/hotspot/share/oops/klass.hpp Sun Sep 22 17:16:35 2019 -0700 @@ -524,6 +524,18 @@ virtual void remove_java_mirror(); virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS); + bool is_unshareable_info_restored() const { + assert(is_shared(), "use this for shared classes only"); + if (has_raw_archived_mirror()) { + // _java_mirror is not a valid OopHandle but rather an encoded reference in the shared heap + return false; + } else if (_java_mirror.ptr_raw() == NULL) { + return false; + } else { + return true; + } + } + public: // subclass accessor (here for convenience; undefined for non-klass objects) virtual bool is_leaf_class() const { fatal("not a class"); return false; } diff -r 14c1ff687621 -r 704e4ff399a2 test/hotspot/jtreg/runtime/cds/appcds/ParallelLoadTest.java --- a/test/hotspot/jtreg/runtime/cds/appcds/ParallelLoadTest.java Sat Sep 21 10:13:25 2019 -0400 +++ b/test/hotspot/jtreg/runtime/cds/appcds/ParallelLoadTest.java Sun Sep 22 17:16:35 2019 -0700 @@ -36,10 +36,34 @@ public class ParallelLoadTest { public static final int MAX_CLASSES = 40; + /* For easy stress testing, do this: + + i=0; while jtreg -DParallelLoadTest.app.loops=100 -DParallelLoadTest.boot.loops=100 \ + ParallelLoadTest.java; do i=$(expr $i + 1); echo =====$i; done + + */ + + private static final int APP_LOOPS = Integer.parseInt(System.getProperty("ParallelLoadTest.app.loops", "1")); + private static final int BOOT_LOOPS = Integer.parseInt(System.getProperty("ParallelLoadTest.boot.loops", "1")); + public static void main(String[] args) throws Exception { JarBuilder.build("parallel_load", getClassList(true)); - String appJar = TestCommon.getTestJar("parallel_load.jar"); - TestCommon.test(appJar, getClassList(false), "ParallelLoad"); + String testJar = TestCommon.getTestJar("parallel_load.jar"); + + // (1) Load the classes from app class loader + TestCommon.testDump(testJar, getClassList(false)); + for (int i = 0; i < APP_LOOPS; i++) { + TestCommon.run("-cp", testJar, "ParallelLoad").assertNormalExit(); + } + + // (2) Load the classes from boot class loader + String bootcp = "-Xbootclasspath/a:" + testJar; + TestCommon.testDump(null, getClassList(false), bootcp); + for (int i = 0; i < BOOT_LOOPS; i++) { + TestCommon.run(bootcp, + // "-Xlog:class+load=debug", + "ParallelLoad").assertNormalExit(); + } } private static String[] getClassList(boolean includeWatchdog) { @@ -47,7 +71,7 @@ String[] classList = new String[MAX_CLASSES + extra]; int i; - for (i=0; i