Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
8295278: Add parallel class loading tests
Reviewed-by: vlivanov, ccheung
- Loading branch information
Showing
23 changed files
with
733 additions
and
2 deletions.
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
test/hotspot/jtreg/runtime/ParallelLoad/CallLoadClass/CallLoadClassTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright (c) 2022, 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 8295278 | ||
* @summary Call unlocked version loadClass directly, with another thread calling forName | ||
* One class goes through the ClassLoader path and the other goes through JVM path | ||
* @library /test/lib | ||
* @compile test-classes/A.java ../share/ThreadPrint.java | ||
* @run main/othervm CallLoadClassTest | ||
*/ | ||
|
||
import jdk.test.lib.classloader.ClassUnloadCommon; | ||
import java.util.concurrent.Semaphore; | ||
|
||
public class CallLoadClassTest { | ||
|
||
private static Semaphore mainSync = null; | ||
|
||
private static class MyLoader extends ClassLoader { | ||
|
||
ClassLoader parent; | ||
int count; | ||
|
||
MyLoader(ClassLoader parent) { | ||
this.parent = parent; | ||
this.count = 0; | ||
} | ||
|
||
public synchronized Class<?> loadClass(String name) throws ClassNotFoundException { | ||
Class<?> loadedClass = findLoadedClass(name); | ||
if (name.equals("A") && loadedClass == null) { | ||
ThreadPrint.println("Loading A"); | ||
if (count == 0) { | ||
count++; | ||
ThreadPrint.println("Waiting for A"); | ||
try { | ||
mainSync.release(); // Let t2 start | ||
wait(); // let the other thread load A instead. | ||
} catch (InterruptedException ie) { | ||
} | ||
} else { | ||
notify(); // notify any waiting threads. | ||
} | ||
byte[] classfile = ClassUnloadCommon.getClassData("A"); | ||
return defineClass(name, classfile, 0, classfile.length); | ||
} else { | ||
return parent.loadClass(name); | ||
} | ||
} | ||
} | ||
|
||
private static ClassLoadingThread[] threads = new ClassLoadingThread[2]; | ||
private static boolean success = true; | ||
|
||
private static boolean report_success() { | ||
for (int i = 0; i < 2; i++) { | ||
try { | ||
threads[i].join(); | ||
if (!threads[i].report_success()) success = false; | ||
} catch (InterruptedException e) {} | ||
} | ||
return success; | ||
} | ||
|
||
public static void main(java.lang.String[] unused) { | ||
mainSync = new Semaphore(0); | ||
|
||
// t1 does loadClass directly, t2 does class.ForName() | ||
ClassLoader appLoader = CallLoadClassTest.class.getClassLoader(); | ||
MyLoader ldr = new MyLoader(appLoader); | ||
for (int i = 0; i < 2; i++) { | ||
threads[i] = new ClassLoadingThread(ldr, i, mainSync); | ||
threads[i].setName("Loading Thread #" + (i + 1)); | ||
threads[i].start(); | ||
System.out.println("Thread " + (i + 1) + " was started..."); | ||
} | ||
if (report_success()) { | ||
System.out.println("PASSED"); | ||
} else { | ||
throw new RuntimeException("FAILED"); | ||
} | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
test/hotspot/jtreg/runtime/ParallelLoad/CallLoadClass/ClassLoadingThread.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright (c) 2022, 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. | ||
*/ | ||
|
||
import java.util.concurrent.Semaphore; | ||
|
||
class ClassLoadingThread extends Thread { | ||
|
||
private ClassLoader ldr = null; | ||
private int which; | ||
private Semaphore syncOrder; | ||
|
||
public ClassLoadingThread(ClassLoader loader, int i, Semaphore sem) { | ||
ldr = loader; | ||
which = i; | ||
syncOrder = sem; | ||
} | ||
|
||
private boolean success = true; | ||
public boolean report_success() { return success; } | ||
|
||
public void callForName() { | ||
try { | ||
ThreadPrint.println("Starting forName thread ..."); | ||
// Initiate class loading using specified type | ||
Class<?> a = Class.forName("A", true, ldr); | ||
Object obj = a.getConstructor().newInstance(); | ||
} catch (Throwable e) { | ||
ThreadPrint.println("Exception is caught: " + e); | ||
e.printStackTrace(); | ||
success = false; | ||
} | ||
} | ||
|
||
public void callLoadClass() { | ||
try { | ||
ThreadPrint.println("Starting loadClass thread ..."); | ||
Class<?> a = ldr.loadClass("A"); | ||
Object obj = a.getConstructor().newInstance(); | ||
success = false; // Should have thrown LinkageError | ||
} catch (Throwable e) { | ||
// If you call loadClass directly, this will result in LinkageError | ||
ThreadPrint.println("Exception is caught: " + e); | ||
e.printStackTrace(); | ||
success = (e instanceof LinkageError); | ||
} | ||
} | ||
|
||
public void run() { | ||
if (which == 0) { | ||
callLoadClass(); | ||
} else { | ||
try { | ||
syncOrder.acquire(); // wait until loadClass is waiting. | ||
} catch (InterruptedException idc) {} | ||
callForName(); | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
test/hotspot/jtreg/runtime/ParallelLoad/CallLoadClass/test-classes/A.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright (c) 2022, 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. | ||
*/ | ||
|
||
// This doesn't have to do anything | ||
public class A { | ||
static { System.out.println("A called"); } | ||
public A() { System.out.println("A.<init> called"); } | ||
} | ||
|
116 changes: 116 additions & 0 deletions
116
test/hotspot/jtreg/runtime/ParallelLoad/ParallelCircularity/ParallelCircularityTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
* Copyright (c) 2022, 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 4699981 8295278 | ||
* @summary This is a testcase for JDK-4699981. When 2 threads are loading the same class with | ||
* the same classloader, and somehow one of the 2 threads releases the | ||
* synchronization lock on the classloader, the JVM code | ||
* throws ClassCircularityError, mistakenly. | ||
* @library /test/lib | ||
* @compile test-classes/Base.java test-classes/Derived.java test-classes/Support.java | ||
* @run main/othervm ParallelCircularityTest | ||
*/ | ||
|
||
import java.net.URL; | ||
import java.net.URLClassLoader; | ||
|
||
public class ParallelCircularityTest { | ||
|
||
private Object lock = new Object(); | ||
|
||
private void test() throws Exception { | ||
URL location = getClass().getProtectionDomain().getCodeSource().getLocation(); | ||
URLLoader loader = new URLLoader(new URL[] {location}, getClass().getClassLoader().getParent()); | ||
|
||
Class cls = loader.loadClass("Support"); | ||
|
||
Thread t1 = new Thread(new Run1(cls)); | ||
t1.start(); | ||
|
||
Thread.sleep(1000); | ||
|
||
// Load Derived, will trigger a loadClassInternal for Base | ||
loader.loadClass("Derived"); | ||
} | ||
|
||
public static void main(String[] args) throws Exception { | ||
ParallelCircularityTest pct = new ParallelCircularityTest(); | ||
pct.test(); | ||
} | ||
|
||
public class URLLoader extends URLClassLoader { | ||
private boolean m_firstTime = true; | ||
|
||
public URLLoader(URL[] urls, ClassLoader parent) { | ||
super(urls, parent); | ||
} | ||
|
||
public Class loadClass(String name) throws ClassNotFoundException { | ||
if (name.equals("Base")) { | ||
if (m_firstTime) { | ||
m_firstTime = false; | ||
|
||
// Notify the other thread | ||
synchronized (lock) { | ||
lock.notifyAll(); | ||
} | ||
|
||
// Wait on the classloader to have the JVM throw ClassCircularityError | ||
try { | ||
synchronized (this) { | ||
wait(5000); | ||
} | ||
} | ||
catch (InterruptedException ignored) { } | ||
} | ||
} | ||
return super.loadClass(name); | ||
} | ||
} | ||
|
||
public class Run1 implements Runnable { | ||
private Class cls; | ||
|
||
public Run1(Class cls) { | ||
this.cls = cls; | ||
} | ||
|
||
public void run() { | ||
synchronized (lock) { | ||
try { | ||
lock.wait(); | ||
} | ||
catch (InterruptedException ignored) {} | ||
} | ||
|
||
// Trigger loadClassInternal for Base | ||
try { | ||
cls.newInstance(); | ||
} catch (Throwable x) { | ||
x.printStackTrace(); | ||
} | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
test/hotspot/jtreg/runtime/ParallelLoad/ParallelCircularity/test-classes/Base.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (c) 2022, 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. | ||
*/ | ||
|
||
public class Base {} |
24 changes: 24 additions & 0 deletions
24
test/hotspot/jtreg/runtime/ParallelLoad/ParallelCircularity/test-classes/Derived.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (c) 2022, 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. | ||
*/ | ||
|
||
public class Derived extends Base {} |
Oops, something went wrong.