undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
203
test/jdk/java/lang/ClassLoader/Assert.java
Normal file
203
test/jdk/java/lang/ClassLoader/Assert.java
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2023, 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 4290640 4785473
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib
|
||||
* @build package1.Class1 package2.Class2 package1.package3.Class3 Assert
|
||||
* @run main/othervm Assert
|
||||
* @summary Test the assertion facility
|
||||
* @author Mike McCloskey
|
||||
* @key randomness
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import package1.*;
|
||||
import package2.*;
|
||||
import package1.package3.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static jdk.test.lib.process.ProcessTools.*;
|
||||
|
||||
public class Assert {
|
||||
|
||||
private static Class1 testClass1;
|
||||
private static Class2 testClass2;
|
||||
private static Class3 testClass3;
|
||||
private static final boolean debug = false;
|
||||
private static Random generator = new Random();
|
||||
|
||||
/**
|
||||
* The first invocation of this test starts a loop which exhaustively tests
|
||||
* the object tree with all of its different settings.
|
||||
* There are 7 test objects in a tree that has 7 different places to set
|
||||
* assertions untouched/on/off so this tests 3^7 or 2187 different
|
||||
* configurations.
|
||||
*
|
||||
* This test spawns a new VM for each run because assertions are set on or
|
||||
* off at class load time. Once the class is loaded its assertion status
|
||||
* does not change.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
// Switch values: 0=don't touch, 1=off, 2 = on
|
||||
int[] switches = new int[7];
|
||||
|
||||
int switchSource = 0;
|
||||
if (args.length == 0) { // This is the controller
|
||||
|
||||
// This code is for an exhaustive test
|
||||
//while(switchSource < 2187) {
|
||||
// int temp = switchSource++;
|
||||
|
||||
// This code is for a weaker but faster test
|
||||
for(int x=0; x<100; x++) {
|
||||
int temp = generator.nextInt(2187);
|
||||
for(int i=0; i<7; i++) {
|
||||
switches[i] = temp % 3;
|
||||
temp = temp / 3;
|
||||
}
|
||||
|
||||
// Spawn new VM and load classes
|
||||
List<String> commands = new ArrayList<>();
|
||||
commands.add("Assert");
|
||||
for(int j=0; j<7; j++)
|
||||
commands.add(Integer.toString(switches[j]));
|
||||
OutputAnalyzer outputAnalyzer = executeCommand(createLimitedTestJavaProcessBuilder(commands));
|
||||
if (debug) { // See output of test VMs
|
||||
outputAnalyzer.asLines()
|
||||
.stream()
|
||||
.forEach(s -> System.out.println(s));
|
||||
}
|
||||
int result = outputAnalyzer.getExitValue();
|
||||
if (debug) { // See which switch configs failed
|
||||
if (result == 0) {
|
||||
for(int k=6; k>=0; k--)
|
||||
System.out.print(switches[k]);
|
||||
System.out.println();
|
||||
} else {
|
||||
System.out.print("Nonzero Exit: ");
|
||||
for(int k=6; k>=0; k--)
|
||||
System.out.print(switches[k]);
|
||||
System.out.println();
|
||||
}
|
||||
} else {
|
||||
if (result != 0) {
|
||||
System.err.print("Nonzero Exit: ");
|
||||
for(int k=6; k>=0; k--)
|
||||
System.err.print(switches[k]);
|
||||
System.err.println();
|
||||
throw new RuntimeException("Assertion test failure.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // This is a test spawn
|
||||
for(int i=0; i<7; i++)
|
||||
switches[i] = Integer.parseInt(args[i]);
|
||||
|
||||
SetAssertionSwitches(switches);
|
||||
ConstructClassTree();
|
||||
TestClassTree(switches);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Activate/Deactivate the assertions in the tree according to the
|
||||
* specified switches.
|
||||
*/
|
||||
private static void SetAssertionSwitches(int[] switches) {
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
|
||||
if (switches[0] != 0)
|
||||
loader.setDefaultAssertionStatus(switches[0]==2);
|
||||
if (switches[1] != 0)
|
||||
loader.setPackageAssertionStatus("package1", switches[1]==2);
|
||||
if (switches[2] != 0)
|
||||
loader.setPackageAssertionStatus("package2", switches[2]==2);
|
||||
if (switches[3] != 0)
|
||||
loader.setPackageAssertionStatus("package1.package3", switches[3]==2);
|
||||
if (switches[4] != 0)
|
||||
loader.setClassAssertionStatus("package1.Class1", switches[4]==2);
|
||||
if (switches[5] != 0)
|
||||
loader.setClassAssertionStatus("package2.Class2", switches[5]==2);
|
||||
if (switches[6] != 0)
|
||||
loader.setClassAssertionStatus("package1.package3.Class3", switches[6]==2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the assertions are activated or deactivated as specified
|
||||
* by the switches.
|
||||
*/
|
||||
private static void TestClassTree(int[] switches) {
|
||||
|
||||
// Class1 and anonymous inner class
|
||||
boolean assertsOn = (switches[4]==2) ? true : (switches[4]==1) ? false :
|
||||
(switches[1]==2) ? true : (switches[1]==1) ? false : (switches[0]==2) ?
|
||||
true: false;
|
||||
testClass1.testAssert(assertsOn);
|
||||
|
||||
// Class1 inner class Class11
|
||||
assertsOn = (switches[4]==2) ? true : (switches[4]==1) ? false :
|
||||
(switches[1]==2) ? true : (switches[1]==1) ? false : (switches[0]==2) ?
|
||||
true: false;
|
||||
Class1.Class11.testAssert(assertsOn);
|
||||
|
||||
// Class2
|
||||
assertsOn = (switches[5]==2) ? true : (switches[5]==1) ? false :
|
||||
(switches[2]==2) ? true : (switches[2]==1) ? false : (switches[0]==2) ?
|
||||
true: false;
|
||||
testClass2.testAssert(assertsOn);
|
||||
|
||||
// Class3 and anonymous inner class
|
||||
assertsOn = (switches[6]==2) ? true : (switches[6]==1) ? false :
|
||||
(switches[3]==2) ? true : (switches[3]==1) ? false :
|
||||
(switches[1]==2) ? true : (switches[1]==1) ? false :
|
||||
(switches[0]==2) ? true: false;
|
||||
testClass3.testAssert(assertsOn);
|
||||
|
||||
// Class3 inner class Class31
|
||||
assertsOn = (switches[6]==2) ? true : (switches[6]==1) ? false :
|
||||
(switches[3]==2) ? true : (switches[3]==1) ? false :
|
||||
(switches[1]==2) ? true : (switches[1]==1) ? false :
|
||||
(switches[0]==2) ? true : false;
|
||||
Class3.Class31.testAssert(assertsOn);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the class tree to be tested. Each test run must reload the classes
|
||||
* of the tree since assertion status is determined at class load time.
|
||||
*/
|
||||
private static void ConstructClassTree() {
|
||||
testClass1 = new Class1();
|
||||
testClass2 = new Class2();
|
||||
testClass3 = new Class3();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 8281000
|
||||
* @summary Test ClassLoader.isRegisteredAsParallelCapable() method with an
|
||||
* invalid caller (non-JNI cases). This test uses reflection and opens
|
||||
* the java.base module so it runs separate from behavior tests of
|
||||
* isRegisteredParallelCapable to avoid side effects.
|
||||
* @modules java.base/java.lang:open
|
||||
* @run main/othervm BadRegisterAsParallelCapableCaller
|
||||
*/
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class BadRegisterAsParallelCapableCaller {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Throwable thrown = null;
|
||||
final Method m = ClassLoader.class.getDeclaredMethod("registerAsParallelCapable");
|
||||
m.setAccessible(true);
|
||||
try {
|
||||
m.invoke(null);
|
||||
} catch (InvocationTargetException ite) {
|
||||
thrown = ite.getCause();
|
||||
}
|
||||
if (! (thrown instanceof IllegalCallerException)) {
|
||||
throw new RuntimeException("Didn't get expected IllegalCallerException, got "+ thrown);
|
||||
} else {
|
||||
System.out.println("Invalid caller threw IllegalCallerException as expected");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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.io.PrintStream;
|
||||
|
||||
/*
|
||||
* Custom system class loader.
|
||||
*/
|
||||
public class CustomLoader extends ClassLoader {
|
||||
private static PrintStream out = System.out;
|
||||
public static ClassLoader INSTANCE;
|
||||
|
||||
public CustomLoader(ClassLoader classLoader) {
|
||||
super("CustomSystemLoader", classLoader);
|
||||
assert INSTANCE == null;
|
||||
INSTANCE = this;
|
||||
|
||||
// test cases to validate that ClassLoader::getSystemClassLoader
|
||||
// is not triggered during custom system class loader initialization
|
||||
testEnumValueOf();
|
||||
}
|
||||
|
||||
static void testEnumValueOf() {
|
||||
TestEnum e = java.lang.Enum.valueOf(TestEnum.class, "C1");
|
||||
if (e != TestEnum.C1) {
|
||||
throw new RuntimeException("Expected: " + TestEnum.C1 + " got: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
out.println("CustomLoader: loading class: " + name);
|
||||
return super.loadClass(name);
|
||||
}
|
||||
|
||||
static enum TestEnum {
|
||||
C1, C2, C3
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 8179950
|
||||
* @build CustomLoader InitSystemLoaderTest
|
||||
* @run main/othervm -Djava.system.class.loader=CustomLoader InitSystemLoaderTest
|
||||
* @summary Test custom system loader initialization and verify their ancestors
|
||||
*/
|
||||
|
||||
public class InitSystemLoaderTest {
|
||||
public static void main(String... args) {
|
||||
// check that system class loader is the custom loader
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
if (loader != CustomLoader.INSTANCE) {
|
||||
throw new RuntimeException("Expected custom loader: "
|
||||
+ CustomLoader.INSTANCE + " got: " + loader);
|
||||
}
|
||||
|
||||
// parent of the custom loader should be builtin system class loader
|
||||
ClassLoader builtinSystemLoader = loader.getParent();
|
||||
ClassLoader grandparent = builtinSystemLoader.getParent();
|
||||
if (grandparent != ClassLoader.getPlatformClassLoader()) {
|
||||
throw new RuntimeException("Expected class loader ancestor: "
|
||||
+ ClassLoader.getPlatformClassLoader() + " got: " + grandparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
86
test/jdk/java/lang/ClassLoader/EndorsedDirs.java
Normal file
86
test/jdk/java/lang/ClassLoader/EndorsedDirs.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2018, 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 8060206 8067366
|
||||
* @library /test/lib
|
||||
* @summary Endorsed standards and override mechanism is removed
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class EndorsedDirs {
|
||||
private static String TEST_CLASSES = System.getProperty("test.classes", ".");
|
||||
|
||||
private static String[] VALUES = new String[] {
|
||||
null,
|
||||
"",
|
||||
"\"\""
|
||||
};
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
String value = System.getProperty("java.endorsed.dirs");
|
||||
System.out.format("java.endorsed.dirs = '%s'%n", value);
|
||||
if (args.length > 0) {
|
||||
int index = Integer.valueOf(args[0]);
|
||||
String expectedValue = VALUES[index];
|
||||
if (!(expectedValue == value ||
|
||||
(value != null && value.isEmpty()) ||
|
||||
(expectedValue != null & expectedValue.equals(value)))) {
|
||||
throw new RuntimeException("java.endorsed.dirs (" +
|
||||
value + ") != " + expectedValue);
|
||||
}
|
||||
// launched by subprocess.
|
||||
return;
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
throw new RuntimeException("java.endorsed.dirs not removed: " + value);
|
||||
}
|
||||
|
||||
fatalError(0, "-Djava.endorsed.dirs=foo");
|
||||
start(0);
|
||||
start(1, "-Djava.endorsed.dirs=");
|
||||
start(2, "-Djava.endorsed.dirs=\"\"");
|
||||
}
|
||||
|
||||
static String[] launchOptions(int testParam, String... args) {
|
||||
return Stream.concat(Stream.of(args),
|
||||
Stream.of("-cp", TEST_CLASSES, "EndorsedDirs",
|
||||
String.valueOf(testParam)))
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
static void start(int testParam, String... args) throws Exception {
|
||||
ProcessTools.executeTestJava(launchOptions(testParam, args))
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
static void fatalError(int testParam, String... args) throws Exception {
|
||||
ProcessTools.executeTestJava(launchOptions(testParam, args))
|
||||
.stderrShouldContain("Could not create the Java Virtual Machine");
|
||||
}
|
||||
}
|
||||
52
test/jdk/java/lang/ClassLoader/ExceptionHidingLoader.java
Normal file
52
test/jdk/java/lang/ClassLoader/ExceptionHidingLoader.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 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 4135104
|
||||
@summary If a badly behaved ClassLoader returns null but doesn't
|
||||
raise an exception, the VM core dumps.
|
||||
*/
|
||||
|
||||
|
||||
public class ExceptionHidingLoader extends ClassLoader {
|
||||
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
boolean exception = false;
|
||||
|
||||
try {
|
||||
Class.forName("aha", false, new ExceptionHidingLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
/* VM was smart enough to detect the problem and raise an
|
||||
exception. */
|
||||
exception = true;
|
||||
}
|
||||
if (!exception) {
|
||||
throw new Exception("Bogus loader behavior not being corrected");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
87
test/jdk/java/lang/ClassLoader/ExtDirs.java
Normal file
87
test/jdk/java/lang/ClassLoader/ExtDirs.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2018, 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 8060206 8067366
|
||||
* @library /test/lib
|
||||
* @summary Extension mechanism is removed
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
import java.lang.Integer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ExtDirs {
|
||||
private static String TEST_CLASSES = System.getProperty("test.classes", ".");
|
||||
|
||||
private static String[] VALUES = new String[] {
|
||||
null,
|
||||
"",
|
||||
"\"\""
|
||||
};
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
String value = System.getProperty("java.ext.dirs");
|
||||
System.out.format("java.ext.dirs = '%s'%n", value);
|
||||
if (args.length > 0) {
|
||||
int index = Integer.valueOf(args[0]);
|
||||
String expectedValue = VALUES[index];
|
||||
if (!(expectedValue == value ||
|
||||
(value != null && value.isEmpty()) ||
|
||||
(expectedValue != null & expectedValue.equals(value)))) {
|
||||
throw new RuntimeException("java.ext.dirs (" +
|
||||
value + ") != " + expectedValue);
|
||||
}
|
||||
// launched by subprocess.
|
||||
return;
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
throw new RuntimeException("java.ext.dirs not removed: " + value);
|
||||
}
|
||||
|
||||
fatalError(0, "-Djava.ext.dirs=foo");
|
||||
start(0);
|
||||
start(1, "-Djava.ext.dirs=");
|
||||
start(2, "-Djava.ext.dirs=\"\"");
|
||||
}
|
||||
|
||||
static String[] launchOptions(int testParam, String... args) {
|
||||
return Stream.concat(Stream.of(args),
|
||||
Stream.of("-cp", TEST_CLASSES, "ExtDirs",
|
||||
String.valueOf(testParam)))
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
static void start(int testParam, String... args) throws Exception {
|
||||
ProcessTools.executeTestJava(launchOptions(testParam, args))
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
static void fatalError(int testParam, String... args) throws Exception {
|
||||
ProcessTools.executeTestJava(launchOptions(testParam, args))
|
||||
.stderrShouldContain("Could not create the Java Virtual Machine");
|
||||
}
|
||||
}
|
||||
57
test/jdk/java/lang/ClassLoader/GetDefinedPackage.java
Normal file
57
test/jdk/java/lang/ClassLoader/GetDefinedPackage.java
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 8165346
|
||||
* @summary Basic test for ClassLoader::getDefinedPackage
|
||||
*/
|
||||
|
||||
public class GetDefinedPackage {
|
||||
public static void main(String... args) {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
Package pkg = loader.getDefinedPackage(TestClassLoader.PKG_NAME);
|
||||
if (pkg == null) {
|
||||
throw new RuntimeException("package foo not found");
|
||||
}
|
||||
|
||||
try {
|
||||
loader.getDefinedPackage(null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
|
||||
static class TestClassLoader extends ClassLoader {
|
||||
public static final String PKG_NAME = "foo";
|
||||
|
||||
public TestClassLoader() {
|
||||
super();
|
||||
definePackage(PKG_NAME);
|
||||
}
|
||||
|
||||
public Package definePackage(String name) {
|
||||
return definePackage(name, null, null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
80
test/jdk/java/lang/ClassLoader/GetDotResource.java
Normal file
80
test/jdk/java/lang/ClassLoader/GetDotResource.java
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2018, 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 4273031
|
||||
* @summary ClassLoader.getResouce() should be able to
|
||||
* find resources with leading "." in their names
|
||||
* @library /test/lib
|
||||
* @run main GetDotResource
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class GetDotResource {
|
||||
|
||||
private static final String JAR_FILENAME = "resource.jar";
|
||||
private static final String DOT_FILENAME = ".resource";
|
||||
private static final String CP = JAR_FILENAME + File.pathSeparator
|
||||
+ System.getProperty("test.class.path");
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
if (args.length == 0) {
|
||||
createJar(JAR_FILENAME, DOT_FILENAME);
|
||||
|
||||
ProcessTools.executeTestJava("-cp", CP,
|
||||
GetDotResource.class.getName(),
|
||||
DOT_FILENAME)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldHaveExitValue(0);
|
||||
} else {
|
||||
runTest(args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runTest(String dotFileName) throws Exception {
|
||||
if (GetDotResource.class.getClassLoader().
|
||||
getResourceAsStream(dotFileName) == null) {
|
||||
throw new Exception("Could not find resource with "
|
||||
+ "leading . in their names");
|
||||
}
|
||||
}
|
||||
|
||||
public static void createJar(String jarFileName, String dotFileName)
|
||||
throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(jarFileName);
|
||||
JarOutputStream out = new JarOutputStream(fos))
|
||||
{
|
||||
out.putNextEntry(new JarEntry(dotFileName));
|
||||
out.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
68
test/jdk/java/lang/ClassLoader/GetPackage.java
Normal file
68
test/jdk/java/lang/ClassLoader/GetPackage.java
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 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 4256589
|
||||
* @summary Test if getPackage() and getPackages()
|
||||
* return consistent values.
|
||||
*/
|
||||
|
||||
public class GetPackage {
|
||||
public static void main(String arg[]) throws Exception {
|
||||
TestClassLoader parent = new TestClassLoader();
|
||||
TestClassLoader child = new TestClassLoader(parent);
|
||||
// child define a package first
|
||||
child.defineEmptyPackage("foo");
|
||||
// parent then define another package with the same name
|
||||
parent.defineEmptyPackage("foo");
|
||||
if (!child.testPackageView("foo"))
|
||||
throw new Exception("Inconsistent packages view");
|
||||
}
|
||||
}
|
||||
|
||||
class TestClassLoader extends ClassLoader {
|
||||
public TestClassLoader() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TestClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public Package defineEmptyPackage(String name) {
|
||||
return definePackage(name, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/* test to see if getPackage() and getPackages()
|
||||
* are consistent.
|
||||
*/
|
||||
public boolean testPackageView(String name) {
|
||||
Package[] pkgs = getPackages();
|
||||
Package pkg = getPackage(name);
|
||||
for(int i = 0; i < pkgs.length; i++)
|
||||
if (pkgs[i].getName().equals(name) && pkgs[i] == pkg)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
96
test/jdk/java/lang/ClassLoader/GetResourceNullArg.java
Normal file
96
test/jdk/java/lang/ClassLoader/GetResourceNullArg.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Enumeration;
|
||||
import java.util.stream.Stream;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8136831
|
||||
* @summary Test null argument to ClassLoader.getResourceXXXX()
|
||||
* @run testng GetResourceNullArg
|
||||
*/
|
||||
|
||||
public class GetResourceNullArg {
|
||||
private static class MyClassLoader extends ClassLoader {
|
||||
public MyClassLoader() {
|
||||
super(null);
|
||||
}
|
||||
@Override
|
||||
public Class findClass(String name) throws ClassNotFoundException {
|
||||
throw new ClassNotFoundException("Why are you using this?");
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public static ClassLoader[][] provider() {
|
||||
try {
|
||||
return new ClassLoader[][] {
|
||||
{ ClassLoader.getSystemClassLoader() },
|
||||
{ new MyClassLoader() },
|
||||
{ new URLClassLoader(new URL[]{ Paths.get(".").toUri().toURL() },
|
||||
ClassLoader.getSystemClassLoader()) }
|
||||
};
|
||||
} catch (MalformedURLException e) { throw new RuntimeException(e); }
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void classGetResource() {
|
||||
this.getClass().getResource(null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void classGetResourceAsStream() {
|
||||
this.getClass().getResourceAsStream(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider",
|
||||
expectedExceptions = NullPointerException.class)
|
||||
public void loaderGetResource(ClassLoader cl) {
|
||||
cl.getResource(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider",
|
||||
expectedExceptions = NullPointerException.class)
|
||||
public static void loaderGetResources(ClassLoader cl) throws IOException {
|
||||
Enumeration<URL> retVal = cl.getResources(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider",
|
||||
expectedExceptions = NullPointerException.class)
|
||||
public static void loaderResources(ClassLoader cl) throws IOException {
|
||||
Stream<URL> retVal = cl.resources(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "provider",
|
||||
expectedExceptions = NullPointerException.class)
|
||||
public void loaderGetResourceAsStream(ClassLoader cl) {
|
||||
cl.getResourceAsStream(null);
|
||||
}
|
||||
}
|
||||
233
test/jdk/java/lang/ClassLoader/GetSystemPackage.java
Normal file
233
test/jdk/java/lang/ClassLoader/GetSystemPackage.java
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2023, 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 8060130
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib
|
||||
* @build package2.Class2 GetSystemPackage
|
||||
* @summary Test if getSystemPackage() return consistent values for cases
|
||||
* where a manifest is provided or not and ensure only jars on
|
||||
* bootclasspath gets resolved via Package.getSystemPackage
|
||||
* @run main GetSystemPackage
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class GetSystemPackage {
|
||||
|
||||
static final String testClassesDir = System.getProperty("test.classes", ".");
|
||||
static final File tmpFolder = new File(testClassesDir);
|
||||
static final String manifestTitle = "Special JAR";
|
||||
|
||||
public static void main(String ... args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
buildJarsAndInitiateSystemPackageTest();
|
||||
return;
|
||||
}
|
||||
switch (args[0]) {
|
||||
case "system-manifest":
|
||||
verifyPackage(true, true);
|
||||
break;
|
||||
case "system-no-manifest":
|
||||
verifyPackage(false, true);
|
||||
break;
|
||||
case "non-system-manifest":
|
||||
verifyPackage(true, false);
|
||||
break;
|
||||
case "non-system-no-manifest":
|
||||
default:
|
||||
verifyPackage(false, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildJarsAndInitiateSystemPackageTest()
|
||||
throws Exception
|
||||
{
|
||||
Manifest m = new Manifest();
|
||||
// not setting MANIFEST_VERSION prevents META-INF/MANIFEST.MF from
|
||||
// getting written
|
||||
m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
m.getMainAttributes().put(Attributes.Name.SPECIFICATION_TITLE,
|
||||
manifestTitle);
|
||||
|
||||
buildJar("manifest.jar", m);
|
||||
buildJar("no-manifest.jar", null);
|
||||
|
||||
runSubProcess("System package with manifest improperly resolved.",
|
||||
"-Xbootclasspath/a:" + testClassesDir + "/manifest.jar",
|
||||
"GetSystemPackage", "system-manifest");
|
||||
|
||||
runSubProcess("System package from directory improperly resolved.",
|
||||
"-Xbootclasspath/a:" + testClassesDir, "GetSystemPackage",
|
||||
"system-no-manifest");
|
||||
|
||||
runSubProcess("System package with no manifest improperly resolved",
|
||||
"-Xbootclasspath/a:" + testClassesDir + "/no-manifest.jar",
|
||||
"GetSystemPackage", "system-no-manifest");
|
||||
|
||||
runSubProcess("Classpath package with manifest improperly resolved",
|
||||
"-cp", testClassesDir + "/manifest.jar", "GetSystemPackage",
|
||||
"non-system-manifest");
|
||||
|
||||
runSubProcess("Classpath package with no manifest improperly resolved",
|
||||
"-cp", testClassesDir + "/no-manifest.jar", "GetSystemPackage",
|
||||
"non-system-no-manifest");
|
||||
|
||||
}
|
||||
|
||||
private static void buildJar(String name, Manifest man) throws Exception {
|
||||
JarBuilder jar = new JarBuilder(tmpFolder, name, man);
|
||||
jar.addClassFile("package2/Class2.class",
|
||||
testClassesDir + "/package2/Class2.class");
|
||||
jar.addClassFile("GetSystemPackage.class",
|
||||
testClassesDir + "/GetSystemPackage.class");
|
||||
jar.build();
|
||||
}
|
||||
|
||||
private static void runSubProcess(String messageOnError, String ... args)
|
||||
throws Exception
|
||||
{
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args)
|
||||
.directory(tmpFolder);
|
||||
int res = ProcessTools.executeProcess(pb).getExitValue();
|
||||
if (res != 0) {
|
||||
throw new RuntimeException(messageOnError);
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyPackage(boolean hasManifest,
|
||||
boolean isSystemPackage)
|
||||
throws Exception
|
||||
{
|
||||
Class<?> c = Class.forName("package2.Class2");
|
||||
Package pkg = c.getPackage();
|
||||
if (pkg == null || pkg != Package.getPackage("package2") ||
|
||||
!"package2".equals(pkg.getName())) {
|
||||
fail("package2 not found via Package.getPackage()");
|
||||
}
|
||||
|
||||
String specificationTitle = pkg.getSpecificationTitle();
|
||||
if (!"package2".equals(pkg.getName())) {
|
||||
fail("Invalid package for Class2");
|
||||
}
|
||||
|
||||
if (hasManifest && (specificationTitle == null
|
||||
|| !manifestTitle.equals(specificationTitle))) {
|
||||
fail("Invalid manifest for package " + pkg.getName());
|
||||
}
|
||||
if (!hasManifest && specificationTitle != null) {
|
||||
fail("Invalid manifest for package " + pkg.getName() + ": was " +
|
||||
specificationTitle + " expected: null");
|
||||
}
|
||||
|
||||
ClassLoader ld = c.getClassLoader();
|
||||
Package systemPkg = ld != null ? null : Package.getPackage("package2");
|
||||
|
||||
if (findPackage("java.lang") == null) {
|
||||
fail("java.lang not found via Package.getPackages()");
|
||||
}
|
||||
Package foundPackage = findPackage("package2");
|
||||
if (isSystemPackage) {
|
||||
if (systemPkg == null) {
|
||||
fail("System package could not be found via getSystemPackage");
|
||||
}
|
||||
if (foundPackage != systemPkg || systemPkg != pkg) {
|
||||
fail("Inconsistent package found via Package.getPackages()");
|
||||
}
|
||||
} else {
|
||||
if (systemPkg != null) {
|
||||
fail("Non-system package could be found via getSystemPackage");
|
||||
}
|
||||
if (foundPackage == null) {
|
||||
fail("Non-system package not found via Package.getPackages()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Package findPackage(String name) {
|
||||
Package[] packages = Package.getPackages();
|
||||
for (Package p : packages) {
|
||||
if (p.getName().equals(name)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void fail(String message) {
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper class for building jar files
|
||||
*/
|
||||
class JarBuilder {
|
||||
|
||||
private JarOutputStream os;
|
||||
|
||||
public JarBuilder(File tmpFolder, String jarName, Manifest manifest)
|
||||
throws FileNotFoundException, IOException
|
||||
{
|
||||
File jarFile = new File(tmpFolder, jarName);
|
||||
if (manifest != null) {
|
||||
this.os = new JarOutputStream(new FileOutputStream(jarFile),
|
||||
manifest);
|
||||
} else {
|
||||
this.os = new JarOutputStream(new FileOutputStream(jarFile));
|
||||
}
|
||||
}
|
||||
|
||||
public void addClassFile(String pathFromRoot, String file)
|
||||
throws IOException
|
||||
{
|
||||
byte[] buf = new byte[1024];
|
||||
try (FileInputStream in = new FileInputStream(file)) {
|
||||
JarEntry entry = new JarEntry(pathFromRoot);
|
||||
os.putNextEntry(entry);
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
os.write(buf, 0, len);
|
||||
}
|
||||
os.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public void build() throws IOException {
|
||||
os.close();
|
||||
}
|
||||
}
|
||||
114
test/jdk/java/lang/ClassLoader/IsParallelCapable.java
Normal file
114
test/jdk/java/lang/ClassLoader/IsParallelCapable.java
Normal file
|
|
@ -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 8169435
|
||||
* @summary Test ClassLoader.isRegisteredAsParallelCapable() 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().isRegisteredAsParallelCapable()) {
|
||||
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.isRegisteredAsParallelCapable()) {
|
||||
throw new RuntimeException(klazz + " expectCapable: " +
|
||||
cl.expectCapable() + ", isRegisteredAsParallelCapable: " +
|
||||
cl.isRegisteredAsParallelCapable());
|
||||
} else {
|
||||
System.out.println(klazz + " passed");
|
||||
}
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
82
test/jdk/java/lang/ClassLoader/LibraryPathProperty.java
Normal file
82
test/jdk/java/lang/ClassLoader/LibraryPathProperty.java
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2020, 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 8067951 8236075
|
||||
* @summary Unit test for internal ClassLoaderHelper#parsePath().
|
||||
* Quoted entries should get unquoted on Windows.
|
||||
* Empty entries should be replaced with dot.
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.loader:open
|
||||
* @build jdk.test.lib.Platform
|
||||
* @run main LibraryPathProperty
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
public class LibraryPathProperty {
|
||||
|
||||
static final String SP = File.pathSeparator;
|
||||
static Method method;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> klass = Class.forName("jdk.internal.loader.ClassLoaderHelper");
|
||||
method = klass.getDeclaredMethod("parsePath", String.class);
|
||||
method.setAccessible(true);
|
||||
|
||||
test("", ".");
|
||||
test(SP, ".", ".");
|
||||
test("a" + SP, "a", ".");
|
||||
test(SP + "b", ".", "b");
|
||||
test("a" + SP + SP + "b", "a", ".", "b");
|
||||
|
||||
if (Platform.isWindows()) {
|
||||
// on Windows parts of paths may be quoted
|
||||
test("\"\"", ".");
|
||||
test("\"\"" + SP, ".", ".");
|
||||
test(SP + "\"\"", ".", ".");
|
||||
test("a" + SP + "\"b\"" + SP, "a", "b", ".");
|
||||
test(SP + "\"a\"" + SP + SP + "b", ".", "a", ".", "b");
|
||||
test("\"a\"" + SP + "\"b\"", "a", "b");
|
||||
test("\"/a/\"b" + SP + "c", "/a/b", "c");
|
||||
test("\"/a;b\"" + SP + "c", "/a;b", "c");
|
||||
test("\"/a:b\"" + SP + "c", "/a:b", "c");
|
||||
test("\"/a" + SP + "b\"" + SP + "c", "/a" + SP + "b", "c");
|
||||
test("/\"a\"\";\"\"b\"" + SP + "\"c\"", "/a;b", "c");
|
||||
test("/\"a:\"b" + SP + "c", "/a:b", "c");
|
||||
}
|
||||
}
|
||||
|
||||
static void test(String s, String... expected) throws Throwable {
|
||||
String[] res = (String[])method.invoke(null, s);
|
||||
if (!Arrays.asList(res).equals(Arrays.asList(expected))) {
|
||||
throw new RuntimeException("Parsing [" + s + "] " +
|
||||
" result " + Arrays.asList(res) +
|
||||
" doesn't match " + Arrays.asList(expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
55
test/jdk/java/lang/ClassLoader/LoadNullClass.java
Normal file
55
test/jdk/java/lang/ClassLoader/LoadNullClass.java
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 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 4263588 4292814
|
||||
* @summary ClassLoader.loadClass() should not core dump
|
||||
* on null class names.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
|
||||
public class LoadNullClass {
|
||||
public static void main(String[] args) throws Exception {
|
||||
File f = new File(System.getProperty("test.src", "."));
|
||||
// give the class loader a good but useless url
|
||||
FileClassLoader cl = new FileClassLoader
|
||||
(new URL[]{new URL("file:"+ f.getAbsolutePath())});
|
||||
cl.testFindLoadedClass(null);
|
||||
}
|
||||
}
|
||||
|
||||
class FileClassLoader extends URLClassLoader {
|
||||
|
||||
public FileClassLoader(URL[] urls) {
|
||||
super(urls);
|
||||
}
|
||||
|
||||
public void testFindLoadedClass(String name) throws Exception {
|
||||
super.findLoadedClass(name);
|
||||
}
|
||||
}
|
||||
56
test/jdk/java/lang/ClassLoader/RecursiveSystemLoader.java
Normal file
56
test/jdk/java/lang/ClassLoader/RecursiveSystemLoader.java
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 8187222
|
||||
* @run main/othervm -Djava.system.class.loader=RecursiveSystemLoader RecursiveSystemLoader
|
||||
* @summary Test for IllegalStateException if a custom system loader recursively calls getSystemClassLoader()
|
||||
*/
|
||||
public class RecursiveSystemLoader extends ClassLoader {
|
||||
public static void main(String[] args) {
|
||||
ClassLoader sys = ClassLoader.getSystemClassLoader();
|
||||
if (!(sys instanceof RecursiveSystemLoader)) {
|
||||
throw new RuntimeException("Unexpected system classloader: " + sys);
|
||||
}
|
||||
}
|
||||
public RecursiveSystemLoader(ClassLoader classLoader) {
|
||||
super("RecursiveSystemLoader", classLoader);
|
||||
|
||||
// Calling ClassLoader.getSystemClassLoader() before the VM is booted
|
||||
// should throw an IllegalStateException.
|
||||
try {
|
||||
ClassLoader.getSystemClassLoader();
|
||||
} catch(IllegalStateException ise) {
|
||||
System.err.println("Caught expected exception:");
|
||||
ise.printStackTrace();
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("Expected IllegalStateException was not thrown.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
return super.loadClass(name);
|
||||
}
|
||||
}
|
||||
90
test/jdk/java/lang/ClassLoader/ResourcesStreamTest.java
Normal file
90
test/jdk/java/lang/ClassLoader/ResourcesStreamTest.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8161230
|
||||
* @summary Test java.lang.ClassLoader.resources() method
|
||||
*
|
||||
* @build ResourcesStreamTest
|
||||
* @run main ResourcesStreamTest
|
||||
*/
|
||||
public class ResourcesStreamTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testSuccess();
|
||||
testFailure();
|
||||
}
|
||||
|
||||
public static void testSuccess() throws Exception {
|
||||
// failing part first
|
||||
try {
|
||||
ClassLoader cl = new FailingClassLoader();
|
||||
// should create the stream pipe
|
||||
Stream<URL> stream = cl.resources("the name");
|
||||
// expect function to throw an exception when calling the method
|
||||
stream.forEach(System.out::println);
|
||||
throw new Exception("expected UncheckedIOException not thrown");
|
||||
} catch (UncheckedIOException uio) {
|
||||
String causeMessage = uio.getCause().getMessage();
|
||||
if (!"the name".equals(causeMessage))
|
||||
throw new Exception("unexpected cause message: " + causeMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static void testFailure() throws Exception {
|
||||
ClassLoader cl = new SuccessClassLoader();
|
||||
long count = cl.resources("the name").count();
|
||||
if (count != 1)
|
||||
throw new Exception("expected resource is null or empty");
|
||||
|
||||
cl.resources("the name")
|
||||
.filter(url -> "file:/somefile".equals(url.toExternalForm()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new Exception("correct URL not found"));
|
||||
}
|
||||
|
||||
public static class SuccessClassLoader extends ClassLoader {
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
URL url = new URL("file:/somefile");
|
||||
return Collections.enumeration(Collections.singleton(url));
|
||||
}
|
||||
}
|
||||
|
||||
public static class FailingClassLoader extends ClassLoader {
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
throw new IOException(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
130
test/jdk/java/lang/ClassLoader/deadlock/DelegateTest.java
Normal file
130
test/jdk/java/lang/ClassLoader/deadlock/DelegateTest.java
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 2017, 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 4735126
|
||||
* @summary (cl) ClassLoader.loadClass locks all instances in chain when delegating
|
||||
* @modules java.base/java.lang:open
|
||||
* jdk.compiler
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.compiler.CompilerUtils
|
||||
* @run main/othervm -Xlog:class+load DelegateTest one-way
|
||||
* @run main/othervm -Xlog:class+load DelegateTest cross
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
|
||||
public class DelegateTest implements Runnable {
|
||||
|
||||
private static final Path TEST_DIR = Paths.get(System.getProperty("user.dir", "."));
|
||||
private static final Path SRC_DIR = Paths.get(System.getProperty("test.src"), "src");
|
||||
|
||||
private String id;
|
||||
private DelegatingLoader dl;
|
||||
private String startClass;
|
||||
|
||||
private static DelegatingLoader saLoader, sbLoader;
|
||||
|
||||
public static void log(String line) {
|
||||
System.out.println(line);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (!CompilerUtils.compile(SRC_DIR, TEST_DIR)) {
|
||||
throw new RuntimeException("Failed to compile "
|
||||
+ SRC_DIR.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
URL[] url = new URL[1];
|
||||
try {
|
||||
url[0] = new URL("file://" + TEST_DIR + File.separator);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Set up Classloader delegation hierarchy
|
||||
saLoader = new DelegatingLoader(url);
|
||||
sbLoader = new DelegatingLoader(url);
|
||||
|
||||
String[] saClasses = { "comSA.SupBob", "comSA.Alice" };
|
||||
String[] sbClasses = { "comSB.SupAlice", "comSB.Bob" };
|
||||
|
||||
saLoader.setDelegate(sbClasses, sbLoader);
|
||||
sbLoader.setDelegate(saClasses, saLoader);
|
||||
|
||||
// test one-way delegate
|
||||
String testType = args[0];
|
||||
if (testType.equals("one-way")) {
|
||||
test("comSA.Alice", "comSA.SupBob");
|
||||
} else if (testType.equals("cross")) {
|
||||
// test cross delegate
|
||||
test("comSA.Alice", "comSB.Bob");
|
||||
} else {
|
||||
System.out.println("ERROR: unsupported - " + testType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void test(String clsForSA, String clsForSB) throws InterruptedException {
|
||||
DelegateTest ia = new DelegateTest("SA", saLoader, clsForSA);
|
||||
DelegateTest ib = new DelegateTest("SB", sbLoader, clsForSB);
|
||||
Thread ta = new Thread(ia);
|
||||
Thread tb = new Thread(ib);
|
||||
ta.start();
|
||||
tb.start();
|
||||
ta.join();
|
||||
tb.join();
|
||||
}
|
||||
|
||||
public static void sleep() {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
log("Thread interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
private DelegateTest(String id, DelegatingLoader dl, String startClass) {
|
||||
this.id = id;
|
||||
this.dl = dl;
|
||||
this.startClass = startClass;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
log("Spawned thread " + id + " running");
|
||||
try {
|
||||
// To mirror the WAS deadlock, need to ensure class load
|
||||
// is routed via the VM.
|
||||
Class.forName(startClass, true, dl);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
log("Thread " + id + " terminating");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 2017, 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.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class DelegatingLoader extends URLClassLoader {
|
||||
|
||||
private DelegatingLoader delLoader;
|
||||
private String[] delClasses;
|
||||
|
||||
static {
|
||||
boolean supportParallel = false;
|
||||
try {
|
||||
Class c = Class.forName("java.lang.ClassLoader");
|
||||
Method m = c.getDeclaredMethod("registerAsParallelCapable",
|
||||
new Class[0]);
|
||||
m.setAccessible(true);
|
||||
Object result = (Boolean) m.invoke(null);
|
||||
if (result instanceof Boolean) {
|
||||
supportParallel = ((Boolean) result).booleanValue();
|
||||
} else {
|
||||
// Should never happen
|
||||
System.out.println("Error: ClassLoader.registerAsParallelCapable() did not return a boolean!");
|
||||
System.exit(1);
|
||||
}
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
System.out.println("No ClassLoader.registerAsParallelCapable() API");
|
||||
} catch (NoSuchMethodError nsme2) {
|
||||
System.out.println("No ClassLoader.registerAsParallelCapable() API");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
// Exit immediately to indicate an error
|
||||
System.exit(1);
|
||||
}
|
||||
System.out.println("Parallel ClassLoader registration: " +
|
||||
supportParallel);
|
||||
}
|
||||
|
||||
public DelegatingLoader(URL urls[]) {
|
||||
super(urls);
|
||||
System.out.println("DelegatingLoader using URL " + urls[0]);
|
||||
}
|
||||
|
||||
public void setDelegate(String[] delClasses, DelegatingLoader delLoader) {
|
||||
this.delClasses = delClasses;
|
||||
this.delLoader = delLoader;
|
||||
}
|
||||
|
||||
public Class loadClass(String className, boolean resolve)
|
||||
throws ClassNotFoundException {
|
||||
for (int i = 0; i < delClasses.length; i++) {
|
||||
if (delClasses[i].equals(className)) {
|
||||
DelegateTest.log("Delegating class loading for " + className);
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException ie) {
|
||||
return null;
|
||||
}
|
||||
return delLoader.loadClass(className, resolve);
|
||||
}
|
||||
}
|
||||
|
||||
DelegateTest.log("Loading local class " + className);
|
||||
// synchronized (getClassLoadingLock(className)) {
|
||||
return super.loadClass(className, resolve);
|
||||
// }
|
||||
}
|
||||
}
|
||||
104
test/jdk/java/lang/ClassLoader/deadlock/GetResource.java
Normal file
104
test/jdk/java/lang/ClassLoader/deadlock/GetResource.java
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 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.
|
||||
*/
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
/* @test
|
||||
* @bug 6977738 8029891
|
||||
* @summary Test ClassLoader.getResource() that should not deadlock
|
||||
# if another thread is holding the system properties object
|
||||
*
|
||||
* @build GetResource
|
||||
* @run main GetResource
|
||||
*/
|
||||
|
||||
public class GetResource {
|
||||
CyclicBarrier go = new CyclicBarrier(2);
|
||||
CyclicBarrier done = new CyclicBarrier(2);
|
||||
Thread t1, t2;
|
||||
public GetResource() {
|
||||
t1 = new Thread() {
|
||||
public void run() {
|
||||
Properties prop = System.getProperties();
|
||||
synchronized (prop) {
|
||||
System.out.println("Thread 1 ready");
|
||||
try {
|
||||
go.await();
|
||||
prop.put("property", "value");
|
||||
prop.store(System.out, "");
|
||||
done.await(); // keep holding the lock until t2 finishes
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (BrokenBarrierException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
System.out.println("Thread 1 exits");
|
||||
}
|
||||
};
|
||||
|
||||
t2 = new Thread() {
|
||||
public void run() {
|
||||
System.out.println("Thread 2 ready");
|
||||
try {
|
||||
go.await(); // wait until t1 holds the lock of the system properties
|
||||
|
||||
URL u1 = Thread.currentThread().getContextClassLoader().getResource("unknownresource");
|
||||
done.await();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (BrokenBarrierException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("Thread 2 exits");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
t1.start();
|
||||
t2.start();
|
||||
try {
|
||||
t1.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
try {
|
||||
t2.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new GetResource().run();
|
||||
}
|
||||
}
|
||||
29
test/jdk/java/lang/ClassLoader/deadlock/src/comSA/Alice.java
Normal file
29
test/jdk/java/lang/ClassLoader/deadlock/src/comSA/Alice.java
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*/
|
||||
package comSA;
|
||||
|
||||
public class Alice extends comSB.SupAlice {
|
||||
static {
|
||||
System.out.println("comSA.Alice loaded");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*/
|
||||
package comSA;
|
||||
|
||||
public class SupBob {
|
||||
static {
|
||||
System.out.println("comSA.SupBob loaded");
|
||||
}
|
||||
}
|
||||
29
test/jdk/java/lang/ClassLoader/deadlock/src/comSB/Bob.java
Normal file
29
test/jdk/java/lang/ClassLoader/deadlock/src/comSB/Bob.java
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*/
|
||||
package comSB;
|
||||
|
||||
public class Bob extends comSA.SupBob {
|
||||
static {
|
||||
System.out.println("comSB.Bob loaded");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 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.
|
||||
*/
|
||||
package comSB;
|
||||
|
||||
public class SupAlice {
|
||||
static {
|
||||
System.out.println("comSB.SupAlice loaded");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2010, 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 4894899
|
||||
* @summary Test various cases of passing java.nio.ByteBuffers
|
||||
* to defineClass().
|
||||
*
|
||||
* @build DefineClassByteBuffer TestClass
|
||||
* @run main DefineClassByteBuffer
|
||||
*/
|
||||
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.io.*;
|
||||
|
||||
public class DefineClassByteBuffer {
|
||||
|
||||
static void test(ClassLoader cl) throws Exception {
|
||||
Class<?> c = Class.forName("TestClass", true, cl);
|
||||
if (!"TestClass".equals(c.getName())) {
|
||||
throw new RuntimeException("Got wrong class: " + c);
|
||||
}
|
||||
if (c.getClassLoader() != cl) {
|
||||
throw new RuntimeException("TestClass defined by wrong classloader: " + c.getClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String arg[]) throws Exception {
|
||||
DummyClassLoader[] cls = new DummyClassLoader[DummyClassLoader.MAX_TYPE];
|
||||
for (int i = 0; i < cls.length; i++) {
|
||||
cls[i] = new DummyClassLoader(i);
|
||||
}
|
||||
|
||||
/* Create several instances of the class using different classloaders,
|
||||
which are using different types of ByteBuffer. */
|
||||
for (int i = 0; i < cls.length; i++) {
|
||||
test(cls[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Always loads the same class, using various types of ByteBuffers */
|
||||
public static class DummyClassLoader extends ClassLoader {
|
||||
|
||||
public static final String CLASS_NAME = "TestClass";
|
||||
|
||||
public static final int MAPPED_BUFFER = 0;
|
||||
public static final int DIRECT_BUFFER = 1;
|
||||
public static final int ARRAY_BUFFER = 2;
|
||||
public static final int WRAPPED_BUFFER = 3;
|
||||
public static final int READ_ONLY_ARRAY_BUFFER = 4;
|
||||
public static final int READ_ONLY_DIRECT_BUFFER = 5;
|
||||
public static final int DUP_ARRAY_BUFFER = 6;
|
||||
public static final int DUP_DIRECT_BUFFER = 7;
|
||||
public static final int MAX_TYPE = 7;
|
||||
|
||||
int loaderType;
|
||||
|
||||
DummyClassLoader(int loaderType) {
|
||||
this.loaderType = loaderType;
|
||||
}
|
||||
|
||||
static ByteBuffer[] buffers = new ByteBuffer[MAX_TYPE + 1];
|
||||
|
||||
static ByteBuffer readClassFile(String name) {
|
||||
try {
|
||||
File f = new File(System.getProperty("test.classes", "."),
|
||||
name);
|
||||
FileInputStream fin = new FileInputStream(f);
|
||||
FileChannel fc = fin.getChannel();
|
||||
return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException("Can't open file: " + name, e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Can't open file: " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
/* create a bunch of different ByteBuffers, starting with a mapped
|
||||
buffer from a class file, and create various duplicate and wrapped
|
||||
buffers. */
|
||||
buffers[MAPPED_BUFFER] = readClassFile(CLASS_NAME + ".class");
|
||||
byte[] array = new byte[buffers[MAPPED_BUFFER].limit()];
|
||||
buffers[MAPPED_BUFFER].get(array).flip();
|
||||
|
||||
buffers[DIRECT_BUFFER] = ByteBuffer.allocateDirect(array.length);
|
||||
buffers[DIRECT_BUFFER].put(array).flip();
|
||||
|
||||
buffers[ARRAY_BUFFER] = ByteBuffer.allocate(array.length);
|
||||
buffers[ARRAY_BUFFER].put(array).flip();
|
||||
|
||||
buffers[WRAPPED_BUFFER] = ByteBuffer.wrap(array);
|
||||
|
||||
buffers[READ_ONLY_ARRAY_BUFFER] = buffers[ARRAY_BUFFER].asReadOnlyBuffer();
|
||||
|
||||
buffers[READ_ONLY_DIRECT_BUFFER] = buffers[DIRECT_BUFFER].asReadOnlyBuffer();
|
||||
|
||||
buffers[DUP_ARRAY_BUFFER] = buffers[ARRAY_BUFFER].duplicate();
|
||||
|
||||
buffers[DUP_DIRECT_BUFFER] = buffers[DIRECT_BUFFER].duplicate();
|
||||
}
|
||||
|
||||
protected Class<?> loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
Class<?> c;
|
||||
if (!"TestClass".equals(name)) {
|
||||
c = super.loadClass(name, resolve);
|
||||
} else {
|
||||
// should not delegate to the system class loader
|
||||
c = findClass(name);
|
||||
if (resolve) {
|
||||
resolveClass(c);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
protected Class<?> findClass(String name)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
if (!"TestClass".equals(name)) {
|
||||
throw new ClassNotFoundException("Unexpected class: " + name);
|
||||
}
|
||||
return defineClass(name, buffers[loaderType], null);
|
||||
}
|
||||
} /* DummyClassLoader */
|
||||
|
||||
} /* DefineClassByteBuffer */
|
||||
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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
|
||||
* @summary Test various cases of passing java.nio.ByteBuffers to defineClass().
|
||||
* @bug 8365588
|
||||
*
|
||||
* @build DefineClassDirectByteBuffer
|
||||
* @run junit/othervm --add-opens java.base/java.lang=ALL-UNNAMED -Dmode=Direct DefineClassDirectByteBuffer
|
||||
* @run junit/othervm --add-opens java.base/java.lang=ALL-UNNAMED -Dmode=Heap DefineClassDirectByteBuffer
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.HexFormat;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class DefineClassDirectByteBuffer {
|
||||
// this is for the trusted/biltin classloader
|
||||
private static final String mode = System.getProperty("mode", "Direct");
|
||||
private static final int CLASSBYTES_OFFSET = 16;
|
||||
|
||||
// -------- untrusted path (custom loader) --------
|
||||
static Stream<ByteBuffer> bytebuffers() throws Exception {
|
||||
byte[] classBytes = getTestClassBytes();
|
||||
byte[] classBytesAtOffset = new byte[classBytes.length + CLASSBYTES_OFFSET];
|
||||
System.arraycopy(classBytes, 0, classBytesAtOffset, CLASSBYTES_OFFSET, classBytes.length);
|
||||
|
||||
return Stream.of(
|
||||
// WRAPPED_BUFFER
|
||||
ByteBuffer.wrap(classBytes),
|
||||
ByteBuffer.wrap(classBytes)
|
||||
.asReadOnlyBuffer(),
|
||||
ByteBuffer.wrap(classBytesAtOffset)
|
||||
.position(CLASSBYTES_OFFSET),
|
||||
ByteBuffer.wrap(classBytesAtOffset)
|
||||
.position(CLASSBYTES_OFFSET)
|
||||
.asReadOnlyBuffer(),
|
||||
// ARRAY_BUFFER
|
||||
ByteBuffer.allocate(classBytes.length)
|
||||
.put(classBytes)
|
||||
.flip(),
|
||||
ByteBuffer.allocate(classBytes.length)
|
||||
.put(classBytes)
|
||||
.flip()
|
||||
.asReadOnlyBuffer(),
|
||||
ByteBuffer.allocate(classBytesAtOffset.length)
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET),
|
||||
ByteBuffer.allocate(classBytesAtOffset.length)
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET)
|
||||
.asReadOnlyBuffer(),
|
||||
// DIRECT_BUFFER
|
||||
ByteBuffer.allocateDirect(classBytes.length)
|
||||
.put(classBytes)
|
||||
.flip(),
|
||||
ByteBuffer.allocateDirect(classBytes.length)
|
||||
.put(classBytes)
|
||||
.flip()
|
||||
.asReadOnlyBuffer(),
|
||||
ByteBuffer.allocateDirect(classBytesAtOffset.length)
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET),
|
||||
ByteBuffer.allocateDirect(classBytesAtOffset.length)
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET)
|
||||
.asReadOnlyBuffer(),
|
||||
// FOREIGN_AUTO_BUFFER
|
||||
Arena.ofAuto()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip(),
|
||||
Arena.ofAuto()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip()
|
||||
.asReadOnlyBuffer(),
|
||||
Arena.ofAuto()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET),
|
||||
Arena.ofAuto()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET)
|
||||
.asReadOnlyBuffer(),
|
||||
// FOREIGN_CONFINED_BUFFER
|
||||
Arena.ofConfined()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip(),
|
||||
Arena.ofConfined()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip()
|
||||
.asReadOnlyBuffer(),
|
||||
Arena.ofConfined()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET),
|
||||
Arena.ofConfined()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET)
|
||||
.asReadOnlyBuffer(),
|
||||
// FOREIGN_GLOBAL_BUFFER
|
||||
Arena.global()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip(),
|
||||
Arena.global()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip()
|
||||
.asReadOnlyBuffer(),
|
||||
Arena.global()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET),
|
||||
Arena.global()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET)
|
||||
.asReadOnlyBuffer(),
|
||||
// FOREIGN_SHARED_BUFFER
|
||||
Arena.ofShared()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip(),
|
||||
Arena.ofShared()
|
||||
.allocate(classBytes.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytes)
|
||||
.flip()
|
||||
.asReadOnlyBuffer(),
|
||||
Arena.ofShared()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET),
|
||||
Arena.ofShared()
|
||||
.allocate(classBytesAtOffset.length)
|
||||
.asByteBuffer()
|
||||
.put(classBytesAtOffset)
|
||||
.flip()
|
||||
.position(CLASSBYTES_OFFSET)
|
||||
.asReadOnlyBuffer(),
|
||||
// MAPPED_BUFFER: MapMode.READ_ONLY from READ fc, the bb is readonly
|
||||
getMappedByteBuffer(classBytes, 0),
|
||||
getMappedByteBuffer(classBytesAtOffset, CLASSBYTES_OFFSET)
|
||||
);
|
||||
}
|
||||
|
||||
static ByteBuffer getMappedByteBuffer(byte[] classBytes, int offset) throws Exception {
|
||||
Path tempDir = Paths.get(System.getProperty("test.classes", "."));
|
||||
Files.createDirectories(tempDir);
|
||||
Path tempClassFile = tempDir.resolve(
|
||||
String.format("DefineClassDirectByteBuffer_Greeting_%d.class", offset));
|
||||
Files.write(tempClassFile, classBytes);
|
||||
try (FileChannel fc = FileChannel.open(tempClassFile, StandardOpenOption.READ)) {
|
||||
return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).position(offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest()
|
||||
@MethodSource("bytebuffers")
|
||||
void testDefineClassWithCustomLoaderByteBuffer(ByteBuffer bb) throws Exception {
|
||||
int originalPos = bb.position();
|
||||
int originalLimit = bb.limit();
|
||||
CustomClassLoader loader = new CustomClassLoader();
|
||||
Class<?> clazz = loader.defineClassFromByteBuffer(bb);
|
||||
assertInvocating(clazz);
|
||||
// long-standing (and undocumented) behavior, see JDK-8352583
|
||||
if (bb.isDirect() || bb.hasArray()) {
|
||||
assertEquals(originalPos, bb.position());
|
||||
} else {
|
||||
assertEquals(originalLimit, bb.position());
|
||||
}
|
||||
}
|
||||
|
||||
// -------- trusted path (BuiltinClassLoader) --------
|
||||
@Test
|
||||
void testDefineClassWithBuiltinLoaderByteBuffer() throws Exception {
|
||||
var classBytes = getTestClassBytes();
|
||||
var builtin = ClassLoader.getPlatformClassLoader();
|
||||
var bb = mode.equals("Direct")
|
||||
? ByteBuffer.allocateDirect(classBytes.length).put(classBytes).flip()
|
||||
: ByteBuffer.allocate(classBytes.length).put(classBytes).flip();
|
||||
var originalPos = bb.position();
|
||||
// reflectively call protected defineClass(String, ByteBuffer, ProtectionDomain)
|
||||
Method m = ClassLoader.class.getDeclaredMethod(
|
||||
"defineClass", String.class, ByteBuffer.class, ProtectionDomain.class
|
||||
);
|
||||
m.setAccessible(true);
|
||||
Class<?> clazz = (Class<?>) m.invoke(builtin, null, bb, null);
|
||||
assertInvocating(clazz);
|
||||
assertEquals(originalPos, bb.position());
|
||||
}
|
||||
|
||||
// -------- shared helpers --------
|
||||
private static void assertInvocating(Class<?> clazz) throws Exception {
|
||||
var instance = clazz.getDeclaredConstructor().newInstance();
|
||||
var m = clazz.getMethod("hello");
|
||||
assertEquals("Hello", m.invoke(instance));
|
||||
}
|
||||
|
||||
private static class CustomClassLoader extends ClassLoader {
|
||||
Class<?> defineClassFromByteBuffer(ByteBuffer bb) throws Exception {
|
||||
return defineClass(null, bb, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getTestClassBytes() throws Exception {
|
||||
final String source = """
|
||||
public class Greeting {
|
||||
public String hello() {
|
||||
return "Hello";
|
||||
}
|
||||
}
|
||||
""";
|
||||
// (externally) compiled content of the above source, represented as hex
|
||||
final String classBytesHex = """
|
||||
cafebabe0000004600110a000200030700040c000500060100106a617661
|
||||
2f6c616e672f4f626a6563740100063c696e69743e010003282956080008
|
||||
01000548656c6c6f07000a0100084772656574696e67010004436f646501
|
||||
000f4c696e654e756d6265725461626c6501000568656c6c6f0100142829
|
||||
4c6a6176612f6c616e672f537472696e673b01000a536f7572636546696c
|
||||
6501000d4772656574696e672e6a61766100210009000200000000000200
|
||||
01000500060001000b0000001d00010001000000052ab70001b100000001
|
||||
000c000000060001000000010001000d000e0001000b0000001b00010001
|
||||
000000031207b000000001000c000000060001000000030001000f000000
|
||||
020010
|
||||
""";
|
||||
return HexFormat.of().parseHex(classBytesHex.replaceAll("\n", ""));
|
||||
}
|
||||
}
|
||||
28
test/jdk/java/lang/ClassLoader/defineClass/TestClass.java
Normal file
28
test/jdk/java/lang/ClassLoader/defineClass/TestClass.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 TestClass {
|
||||
public static String foo() {
|
||||
return "OK";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2025, 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 8365203
|
||||
* @summary Tests guarding of ByteBuffers in ClassLoader::defineClass
|
||||
* @run junit TestGuardByteBuffer
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.util.HexFormat;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
final class TestGuardByteBuffer {
|
||||
|
||||
@Test
|
||||
void guardCrash() {
|
||||
final byte[] classBytes = getClassBytes(); // get bytes of a valid class
|
||||
final var cl = new ClassLoader() {
|
||||
void tryCrash() {
|
||||
var arena = Arena.ofConfined();
|
||||
var byteBuffer = arena.allocate(classBytes.length).asByteBuffer();
|
||||
// Close the arena underneath
|
||||
arena.close();
|
||||
// expected to always fail because the arena
|
||||
// from which the ByteBuffer was constructed
|
||||
// has been closed
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> defineClass(null, byteBuffer, null));
|
||||
}
|
||||
};
|
||||
for (int i = 0; i < 10_000; i++) {
|
||||
cl.tryCrash();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getClassBytes() {
|
||||
// unused. this is here just for reference
|
||||
final String source = """
|
||||
public class NoOp {}
|
||||
""";
|
||||
// (externally) compiled content of the above "source", represented as hex
|
||||
final String classBytesHex = """
|
||||
cafebabe00000044000d0a000200030700040c000500060100106a6176612f
|
||||
6c616e672f4f626a6563740100063c696e69743e0100032829560700080100
|
||||
044e6f4f70010004436f646501000f4c696e654e756d6265725461626c6501
|
||||
000a536f7572636546696c650100094e6f4f702e6a61766100210007000200
|
||||
0000000001000100050006000100090000001d00010001000000052ab70001
|
||||
b100000001000a000000060001000000010001000b00000002000c
|
||||
""";
|
||||
|
||||
return HexFormat.of().parseHex(classBytesHex.replaceAll("\n", ""));
|
||||
}
|
||||
|
||||
}
|
||||
BIN
test/jdk/java/lang/ClassLoader/findSystemClass/Loadee.classfile
Normal file
BIN
test/jdk/java/lang/ClassLoader/findSystemClass/Loadee.classfile
Normal file
Binary file not shown.
29
test/jdk/java/lang/ClassLoader/findSystemClass/Loadee.java
Normal file
29
test/jdk/java/lang/ClassLoader/findSystemClass/Loadee.java
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 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 Loadee {
|
||||
Loader app;
|
||||
public Loadee() {
|
||||
app = new Loader();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
It really doesn't matter what is in this file, so long as this file is
|
||||
there.
|
||||
134
test/jdk/java/lang/ClassLoader/findSystemClass/Loader.java
Normal file
134
test/jdk/java/lang/ClassLoader/findSystemClass/Loader.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2010, 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 test runs in othervm mode as it tests ClassLoader.findSystemClass
|
||||
* and getSystemResource methods.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@bug 4147599 4478150
|
||||
@summary In 1.2beta4-I ClassLoader loaded classes can not link
|
||||
against application classes.
|
||||
@run main/othervm Loader
|
||||
*/
|
||||
|
||||
/*
|
||||
* We are trying to test that certain methods of ClassLoader look at the same
|
||||
* paths as they did in 1.1. To run this test on 1.1, you will have to pass
|
||||
* "-1.1" as option on the command line.
|
||||
*
|
||||
* The required files are:
|
||||
*
|
||||
* - Loader.java (a 1.1 style class loader)
|
||||
* - Loadee.java (source for a class that refers to Loader)
|
||||
* - Loadee.classfile (to test findSystemClass)
|
||||
* - Loadee.resource (to test getSystemResource)
|
||||
*
|
||||
* The extension ".classfile" is so the class file is not seen by any loader
|
||||
* other than Loader. If you need to make any changes you will have to
|
||||
* compile Loadee.java and rename Loadee.class to Loadee.classfile.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
/**
|
||||
* A 1.1-style ClassLoader. The only class it can really load is "Loadee".
|
||||
* For other classes it might be asked to load, it relies on loaders set up by
|
||||
* the launcher.
|
||||
*/
|
||||
public class Loader extends ClassLoader {
|
||||
|
||||
public Class loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException {
|
||||
Class c = null;
|
||||
try {
|
||||
c = findSystemClass(name);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
}
|
||||
if (c == null) {
|
||||
if (!name.equals("Loadee"))
|
||||
throw new Error("java.lang.ClassLoader.findSystemClass() " +
|
||||
"did not find class " + name);
|
||||
byte[] b = locateBytes();
|
||||
c = defineClass(name, b, 0, b.length);
|
||||
}
|
||||
if (resolve) {
|
||||
resolveClass(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private byte[] locateBytes() {
|
||||
try {
|
||||
File f = new File(System.getProperty("test.src", "."),
|
||||
"Loadee.classfile");
|
||||
long l = f.length();
|
||||
byte[] b = new byte[(int)l];
|
||||
DataInputStream in =
|
||||
new DataInputStream(new FileInputStream(f));
|
||||
in.readFully(b);
|
||||
return b;
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
throw new Error("Test failed due to IOException!");
|
||||
}
|
||||
}
|
||||
|
||||
private static final int FIND = 0x1;
|
||||
private static final int RESOURCE = 0x2;
|
||||
private static final int RESOURCES = 0x4;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int tests = FIND | RESOURCE | RESOURCES;
|
||||
|
||||
if (args.length == 1 && args[0].equals("-1.1")) {
|
||||
tests &= ~RESOURCES; /* Do not run getResources test. */
|
||||
}
|
||||
|
||||
if ((tests & FIND) == FIND) {
|
||||
report("findSystemClass()");
|
||||
ClassLoader l = new Loader();
|
||||
Class c = l.loadClass("Loadee");
|
||||
Object o = c.newInstance();
|
||||
}
|
||||
|
||||
if ((tests & RESOURCE) == RESOURCE) {
|
||||
report("getSystemResource()");
|
||||
URL u = getSystemResource("Loadee.resource");
|
||||
if (u == null)
|
||||
throw new Exception
|
||||
("java.lang.ClassLoader.getSystemResource() test failed!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void report(String s) {
|
||||
System.out.println("Testing java.lang.ClassLoader." + s + " ...");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Fake resource, to test the getResources() variant.
|
||||
45
test/jdk/java/lang/ClassLoader/forNameLeak/ClassForName.java
Normal file
45
test/jdk/java/lang/ClassLoader/forNameLeak/ClassForName.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/*
|
||||
* This class is loaded by the custom URLClassLoader, and then calls
|
||||
* Class.forName();
|
||||
*/
|
||||
public class ClassForName implements Runnable {
|
||||
static {
|
||||
if (!(ClassForName.class.getClassLoader() instanceof URLClassLoader)) {
|
||||
throw new RuntimeException("Supposed to be loaded by URLClassLoader");
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
Class.forName(java.util.List.class.getName(), false,
|
||||
ClassLoader.getSystemClassLoader());
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
121
test/jdk/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java
Normal file
121
test/jdk/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2024, 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 8151486
|
||||
* @summary Call Class.forName() on the system classloader from a class loaded
|
||||
* from a custom classloader.
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Utils
|
||||
* jdk.test.lib.util.ForceGC
|
||||
* jdk.test.lib.util.JarUtils
|
||||
* @build ClassForName ClassForNameLeak
|
||||
* @run main/othervm ClassForNameLeak
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.util.ForceGC;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
|
||||
/*
|
||||
* Create .jar, load ClassForName from .jar using a URLClassLoader
|
||||
*/
|
||||
public class ClassForNameLeak {
|
||||
private static final long TIMEOUT = (long)(5000.0 * Utils.TIMEOUT_FACTOR);
|
||||
private static final int THREADS = 10;
|
||||
private static final Path jarFilePath = Paths.get("cfn.jar");
|
||||
|
||||
static class TestLoader extends URLClassLoader {
|
||||
static URL[] toURLs() {
|
||||
try {
|
||||
return new URL[]{jarFilePath.toUri().toURL()};
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
TestLoader() {
|
||||
super("LeakedClassLoader", toURLs(), ClassLoader.getPlatformClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
// Use a new classloader to load the ClassForName class, then run its
|
||||
// Runnable.
|
||||
static WeakReference<TestLoader> loadAndRun() {
|
||||
TestLoader classLoader = new TestLoader();
|
||||
try {
|
||||
Class<?> loadClass = Class.forName("ClassForName", true, classLoader);
|
||||
((Runnable) loadClass.newInstance()).run();
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return new WeakReference<>(classLoader);
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
// create the JAR file
|
||||
setup();
|
||||
|
||||
// Make simultaneous calls to the test method, to stress things a bit
|
||||
ExecutorService es = Executors.newFixedThreadPool(THREADS);
|
||||
|
||||
List<Callable<WeakReference<TestLoader>>> callables =
|
||||
Stream.generate(() -> {
|
||||
Callable<WeakReference<TestLoader>> cprcl = ClassForNameLeak::loadAndRun;
|
||||
return cprcl;
|
||||
}).limit(THREADS).collect(Collectors.toList());
|
||||
|
||||
for (Future<WeakReference<TestLoader>> future : es.invokeAll(callables)) {
|
||||
WeakReference<TestLoader> ref = future.get();
|
||||
if (!ForceGC.wait(() -> ref.refersTo(null))) {
|
||||
throw new RuntimeException(ref.get() + " not unloaded");
|
||||
}
|
||||
}
|
||||
es.shutdown();
|
||||
}
|
||||
|
||||
private static final String CLASSFILENAME = "ClassForName.class";
|
||||
private static void setup() throws IOException {
|
||||
String testclasses = System.getProperty("test.classes", ".");
|
||||
|
||||
// Create a temporary .jar file containing ClassForName.class
|
||||
Path testClassesDir = Paths.get(testclasses);
|
||||
JarUtils.createJarFile(jarFilePath, testClassesDir, CLASSFILENAME);
|
||||
}
|
||||
}
|
||||
156
test/jdk/java/lang/ClassLoader/getResource/GetResource.java
Normal file
156
test/jdk/java/lang/ClassLoader/getResource/GetResource.java
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2023, 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 6760902
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.process.ProcessTools
|
||||
* @run testng GetResource
|
||||
* @summary Empty path on bootclasspath is not default to current working
|
||||
* directory for both class lookup and resource lookup whereas
|
||||
* empty path on classpath is default to current working directory.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static jdk.test.lib.process.ProcessTools.*;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class GetResource {
|
||||
private static final Path CWD = Paths.get(System.getProperty("user.dir"));
|
||||
private static final String DIR_A = "a";
|
||||
private static final String DIR_B = "b";
|
||||
|
||||
private static final String RESOURCE_NAME = "test.properties";
|
||||
private static final String GETRESOURCE_CLASS = "GetResource.class";
|
||||
|
||||
public static void main(String... args) {
|
||||
String expect = args[0] + "/" + RESOURCE_NAME;
|
||||
URL url = GetResource.class.getResource(RESOURCE_NAME);
|
||||
System.out.println("getResource found: " + url);
|
||||
if (!url.toString().endsWith(expect)) {
|
||||
throw new RuntimeException(url + " != expected resource " + expect);
|
||||
}
|
||||
|
||||
url = ClassLoader.getSystemResource(RESOURCE_NAME);
|
||||
System.out.println("getSystemResource found: " + url);
|
||||
if (!url.toString().endsWith(expect)) {
|
||||
throw new RuntimeException(url + " != expected resource " + expect);
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeTest
|
||||
public void setup() throws IOException {
|
||||
// setup two directories "a" and "b"
|
||||
// each directory contains both test.properties and this test class
|
||||
Path testSrc = Paths.get(System.getProperty("test.src"));
|
||||
Path testClasses = Paths.get(System.getProperty("test.classes"));
|
||||
|
||||
Files.createDirectories(Paths.get(DIR_A));
|
||||
Files.createDirectories(Paths.get(DIR_B));
|
||||
|
||||
Files.copy(testSrc.resolve(RESOURCE_NAME),
|
||||
Paths.get(DIR_A, RESOURCE_NAME));
|
||||
Files.copy(testSrc.resolve(RESOURCE_NAME),
|
||||
Paths.get(DIR_B, RESOURCE_NAME));
|
||||
|
||||
Files.copy(testClasses.resolve(GETRESOURCE_CLASS),
|
||||
Paths.get(DIR_A, GETRESOURCE_CLASS));
|
||||
Files.copy(testClasses.resolve(GETRESOURCE_CLASS),
|
||||
Paths.get(DIR_B, GETRESOURCE_CLASS));
|
||||
}
|
||||
|
||||
private String concat(String... dirs) {
|
||||
return Stream.of(dirs).collect(Collectors.joining(File.pathSeparator));
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] options() {
|
||||
return new Object[][] {
|
||||
new Object[] { List.of("-Xbootclasspath/a:a"), "a"},
|
||||
new Object[] { List.of("-Xbootclasspath/a:b"), "b"},
|
||||
new Object[] { List.of("-Xbootclasspath/a:" + concat("a", "b")), "a"},
|
||||
new Object[] { List.of("-Xbootclasspath/a:" + concat("b", "a")), "b"},
|
||||
|
||||
new Object[] { List.of("-cp", "a"), "a"},
|
||||
new Object[] { List.of("-cp", "b"), "b"},
|
||||
new Object[] { List.of("-cp", concat("a", "b")), "a"},
|
||||
new Object[] { List.of("-cp", concat("b", "a")), "b"},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "options")
|
||||
public void test(List<String> options, String expected) throws Throwable {
|
||||
runTest(CWD, options, expected);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] dirA() {
|
||||
String dirB = ".." + File.separator + "b";
|
||||
return new Object[][] {
|
||||
new Object[] { List.of("-Xbootclasspath/a:."), "a"},
|
||||
|
||||
new Object[] { List.of("-Xbootclasspath/a:" + dirB), "b"},
|
||||
// empty path in first element
|
||||
new Object[] { List.of("-Xbootclasspath/a:" + File.pathSeparator + dirB), "b"},
|
||||
|
||||
new Object[] { List.of("-cp", File.pathSeparator), "a"},
|
||||
new Object[] { List.of("-cp", dirB), "b"},
|
||||
new Object[] { List.of("-cp", File.pathSeparator + dirB), "a"},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "dirA")
|
||||
public void testCurrentDirA(List<String> options, String expected) throws Throwable {
|
||||
// current working directory is "a"
|
||||
runTest(CWD.resolve(DIR_A), options, expected);
|
||||
}
|
||||
|
||||
private void runTest(Path dir, List<String> options, String expected)
|
||||
throws Throwable
|
||||
{
|
||||
List<String> cmdLine = new ArrayList<>();
|
||||
options.forEach(cmdLine::add);
|
||||
|
||||
cmdLine.add("GetResource");
|
||||
cmdLine.add(expected);
|
||||
ProcessBuilder pb = createTestJavaProcessBuilder(cmdLine);
|
||||
pb.directory(dir.toFile()); // change working directory
|
||||
pb.environment().remove("CLASSPATH"); // remove CLASSPATH environment variable
|
||||
executeCommand(pb).shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2018, 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
|
||||
* @library /test/lib
|
||||
* @build Driver Main
|
||||
* jdk.test.lib.util.JarUtils
|
||||
* @run main Driver
|
||||
* @summary Test ClassLoader.getResourceXXX to locate resources in an automatic
|
||||
* module
|
||||
*/
|
||||
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
|
||||
/**
|
||||
* The driver creates a JAR file containing p/Foo.class, p/foo.properties,
|
||||
* and p/resources/bar.properties. This ensures there are is a resource in
|
||||
* a module package and a resource that is not in the module package. The
|
||||
* test is then launched to locate every resource in the JAR file.
|
||||
*/
|
||||
|
||||
public class Driver {
|
||||
|
||||
private static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// create content for JAR file
|
||||
Path dir = Files.createTempDirectory("classes");
|
||||
Path p = Files.createDirectory(dir.resolve("p"));
|
||||
Files.createFile(p.resolve("Foo.class"));
|
||||
Files.createFile(p.resolve("foo.properties"));
|
||||
Path resources = Files.createDirectory(p.resolve("resources"));
|
||||
Files.createFile(resources.resolve("bar.properties"));
|
||||
|
||||
// create the JAR file, including a manifest
|
||||
Path jarFile = Paths.get("library-1.0.jar");
|
||||
Manifest man = new Manifest();
|
||||
Attributes attrs = man.getMainAttributes();
|
||||
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
|
||||
JarUtils.createJarFile(jarFile, man, dir, p);
|
||||
|
||||
// get the module name
|
||||
ModuleFinder finder = ModuleFinder.of(jarFile);
|
||||
ModuleReference mref = finder.findAll().stream().findAny().orElse(null);
|
||||
if (mref == null)
|
||||
throw new RuntimeException("Module not found!!!");
|
||||
String name = mref.descriptor().name();
|
||||
|
||||
// launch the test with the JAR file on the module path
|
||||
if (ProcessTools.executeTestJava("-p", jarFile.toString(),
|
||||
"--add-modules", name,
|
||||
"-cp", TEST_CLASSES,
|
||||
"Main", name)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.getExitValue() != 0)
|
||||
throw new RuntimeException("Test failed - see output");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Usage: Main $MODULE
|
||||
*
|
||||
* Finds $MODULE in the boot layer and then tests that it can locate every
|
||||
* resource in the module content (JAR file).
|
||||
*/
|
||||
|
||||
public class Main {
|
||||
|
||||
static void testFind(String name) throws Exception {
|
||||
// getResource
|
||||
URL url = Main.class.getClassLoader().getResource(name);
|
||||
if (url == null)
|
||||
throw new RuntimeException("Unable to locate: " + name);
|
||||
System.out.println(name + " => " + url);
|
||||
|
||||
// getResources
|
||||
Enumeration<URL> urls = Main.class.getClassLoader().getResources(name);
|
||||
if (!urls.hasMoreElements())
|
||||
throw new RuntimeException("Unable to locate: " + name);
|
||||
URL first = urls.nextElement();
|
||||
if (!first.toURI().equals(url.toURI()))
|
||||
throw new RuntimeException("found " + first + " ???");
|
||||
|
||||
// getResourceAsStream
|
||||
if (!url.toString().endsWith("/")) {
|
||||
InputStream in = Main.class.getClassLoader().getResourceAsStream(name);
|
||||
if (in == null)
|
||||
throw new RuntimeException("Unable to locate: " + name);
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
static void testFindUnchecked(String name) {
|
||||
try {
|
||||
testFind(name);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String mn = args[0];
|
||||
|
||||
ModuleReference mref = ModuleLayer.boot()
|
||||
.configuration()
|
||||
.findModule(mn)
|
||||
.map(ResolvedModule::reference)
|
||||
.orElseThrow(() -> new RuntimeException(mn + " not resolved!!"));
|
||||
|
||||
try (ModuleReader reader = mref.open();
|
||||
Stream<String> stream = reader.list()) {
|
||||
stream.forEach(name -> {
|
||||
testFindUnchecked(name);
|
||||
|
||||
// if the resource is a directory then find without trailing slash
|
||||
if (name.endsWith("/")) {
|
||||
testFindUnchecked(name.substring(0, name.length() - 1));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
365
test/jdk/java/lang/ClassLoader/getResource/modules/Main.java
Normal file
365
test/jdk/java/lang/ClassLoader/getResource/modules/Main.java
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2024, 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.io.InputStream;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Basic test of ClassLoader getResource and getResourceAsStream when
|
||||
* invoked from code in named modules.
|
||||
*/
|
||||
|
||||
public class Main {
|
||||
|
||||
static final String NAME = "myresource";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
// create resources in m1
|
||||
createResource("m1", Paths.get("."), "m1");
|
||||
createResource("m1", Paths.get("p1"), "m1/p1");
|
||||
createResource("m1", Paths.get("p1", "impl"), "m1/p1.impl");
|
||||
createResource("m1", Paths.get("p1", "resources"), "m1/p1.resources");
|
||||
|
||||
// create resources in m2
|
||||
createResource("m2", Paths.get("."), "m2");
|
||||
createResource("m2", Paths.get("p2"), "m2/p2");
|
||||
createResource("m2", Paths.get("p2", "impl"), "m2/p2.impl");
|
||||
createResource("m2", Paths.get("p2", "resources"), "m2/p2.resources");
|
||||
|
||||
|
||||
// invoke ClassLoader getResource from the unnamed module
|
||||
ClassLoader thisLoader = Main.class.getClassLoader();
|
||||
|
||||
URL url = thisLoader.getResource(NAME);
|
||||
assertNotNull(url);
|
||||
|
||||
url = thisLoader.getResource("p1/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = thisLoader.getResource("p1/impl/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = thisLoader.getResource("p1/resources/" + NAME);
|
||||
assertEquals(readAllAsString(url), "m1/p1.resources");
|
||||
|
||||
url = thisLoader.getResource("p2/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = thisLoader.getResource("p2/impl/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = thisLoader.getResource("p2/resources/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
|
||||
// invoke ClassLoader getResource from module m1
|
||||
url = p1.Main.getResourceInClassLoader(NAME);
|
||||
assertNotNull(url);
|
||||
|
||||
url = p1.Main.getResourceInClassLoader("p1/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p1.Main.getResourceInClassLoader("p1/impl/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p1.Main.getResourceInClassLoader("p1/resources/" + NAME);
|
||||
assertEquals(readAllAsString(url), "m1/p1.resources");
|
||||
|
||||
url = p1.Main.getResourceInClassLoader("p2/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p1.Main.getResourceInClassLoader("p2/impl/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p1.Main.getResourceInClassLoader("p2/resources/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
|
||||
// invoke ClassLoader getResource from module m2
|
||||
url = p2.Main.getResourceInClassLoader(NAME);
|
||||
assertNotNull(url);
|
||||
|
||||
url = p2.Main.getResourceInClassLoader("p1/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p2.Main.getResourceInClassLoader("p1/impl/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p2.Main.getResourceInClassLoader("p1/resources/" + NAME);
|
||||
assertEquals(readAllAsString(url), "m1/p1.resources");
|
||||
|
||||
url = p2.Main.getResourceInClassLoader("p2/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p2.Main.getResourceInClassLoader("p2/impl/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
url = p2.Main.getResourceInClassLoader("p2/resources/" + NAME);
|
||||
assertNull(url);
|
||||
|
||||
|
||||
// invoke ClassLoader getResources from the unnamed module
|
||||
Enumeration<URL> urls = thisLoader.getResources(NAME);
|
||||
List<String> resources = readAllAsStrings(urls);
|
||||
assertTrue(resources.size() == 2);
|
||||
assertTrue(resources.contains("m1"));
|
||||
assertTrue(resources.contains("m2"));
|
||||
|
||||
urls = thisLoader.getResources("p1/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = thisLoader.getResources("p1/impl/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = thisLoader.getResources("p1/resources/" + NAME);
|
||||
resources = readAllAsStrings(urls);
|
||||
assertTrue(resources.size() == 1);
|
||||
assertTrue(resources.contains("m1/p1.resources"));
|
||||
|
||||
urls = thisLoader.getResources("p2/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = thisLoader.getResources("p2/impl/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = thisLoader.getResources("p2/resources/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
|
||||
// invoke ClassLoader getResources from m1
|
||||
urls = p1.Main.getResourcesInClassLoader(NAME);
|
||||
resources = readAllAsStrings(urls);
|
||||
assertTrue(resources.size() == 2);
|
||||
assertTrue(resources.contains("m1"));
|
||||
assertTrue(resources.contains("m2"));
|
||||
|
||||
urls = p1.Main.getResourcesInClassLoader("p1/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p1.Main.getResourcesInClassLoader("p1/impl/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p1.Main.getResourcesInClassLoader("p1/resources/" + NAME);
|
||||
resources = readAllAsStrings(urls);
|
||||
assertTrue(resources.size() == 1);
|
||||
assertTrue(resources.contains("m1/p1.resources"));
|
||||
|
||||
urls = p1.Main.getResourcesInClassLoader("p2/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p1.Main.getResourcesInClassLoader("p2/impl/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p1.Main.getResourcesInClassLoader("p2/resources/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
|
||||
// invoke ClassLoader getResources from m2
|
||||
urls = p2.Main.getResourcesInClassLoader(NAME);
|
||||
resources = readAllAsStrings(urls);
|
||||
assertTrue(resources.size() == 2);
|
||||
assertTrue(resources.contains("m1"));
|
||||
assertTrue(resources.contains("m2"));
|
||||
|
||||
urls = p2.Main.getResourcesInClassLoader("p1/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p2.Main.getResourcesInClassLoader("p1/impl/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p2.Main.getResourcesInClassLoader("p1/resources/" + NAME);
|
||||
resources = readAllAsStrings(urls);
|
||||
assertTrue(resources.size() == 1);
|
||||
assertTrue(resources.contains("m1/p1.resources"));
|
||||
|
||||
urls = p2.Main.getResourcesInClassLoader("p2/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p2.Main.getResourcesInClassLoader("p2/impl/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
urls = p2.Main.getResourcesInClassLoader("p2/resources/" + NAME);
|
||||
assertTrue(readAllAsStrings(urls).isEmpty());
|
||||
|
||||
|
||||
// invoke ClassLoader getResourceAsStream from the unnamed module
|
||||
InputStream in = thisLoader.getResourceAsStream(NAME);
|
||||
assertNotNull(in);
|
||||
|
||||
in = thisLoader.getResourceAsStream("p1/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = thisLoader.getResourceAsStream("p1/impl/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = thisLoader.getResourceAsStream("p1/resources/" + NAME);
|
||||
assertEquals(readAllAsString(in), "m1/p1.resources");
|
||||
|
||||
in = thisLoader.getResourceAsStream("p2/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = thisLoader.getResourceAsStream("p2/impl/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = thisLoader.getResourceAsStream("p2/resources/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
|
||||
// invoke ClassLoader getResource from modules m1
|
||||
in = p1.Main.getResourceAsStreamInClassLoader(NAME);
|
||||
assertNotNull(in);
|
||||
|
||||
in = p1.Main.getResourceAsStreamInClassLoader("p1/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p1.Main.getResourceAsStreamInClassLoader("p1/impl/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p1.Main.getResourceAsStreamInClassLoader("p1/resources/" + NAME);
|
||||
assertEquals(readAllAsString(in), "m1/p1.resources");
|
||||
|
||||
in = p1.Main.getResourceAsStreamInClassLoader("p2/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p1.Main.getResourceAsStreamInClassLoader("p2/impl/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p1.Main.getResourceAsStreamInClassLoader("p2/resources/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
|
||||
// invoke ClassLoader getResource from modules m2
|
||||
in = p2.Main.getResourceAsStreamInClassLoader(NAME);
|
||||
assertNotNull(in);
|
||||
|
||||
in = p2.Main.getResourceAsStreamInClassLoader("p1/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p2.Main.getResourceAsStreamInClassLoader("p1/impl/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p2.Main.getResourceAsStreamInClassLoader("p1/resources/" + NAME);
|
||||
assertEquals(readAllAsString(in), "m1/p1.resources");
|
||||
|
||||
in = p2.Main.getResourceAsStreamInClassLoader("p2/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p2.Main.getResourceAsStreamInClassLoader("p2/impl/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
in = p2.Main.getResourceAsStreamInClassLoader("p2/resources/" + NAME);
|
||||
assertNull(in);
|
||||
|
||||
System.out.println("Success!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a resource in the sub-directory of the given exploded module
|
||||
*/
|
||||
static void createResource(String mn, Path subdir, String msg) throws IOException {
|
||||
Path dir = directoryFor(mn).resolve(subdir);
|
||||
Path file = dir.resolve(NAME);
|
||||
Files.write(file, msg.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory for the given module (by name).
|
||||
*/
|
||||
static Path directoryFor(String mn) {
|
||||
Configuration cf = ModuleLayer.boot().configuration();
|
||||
ResolvedModule resolvedModule = cf.findModule(mn).orElse(null);
|
||||
if (resolvedModule == null)
|
||||
throw new RuntimeException("not found: " + mn);
|
||||
Path dir = Paths.get(resolvedModule.reference().location().get());
|
||||
if (!Files.isDirectory(dir))
|
||||
throw new RuntimeException("not a directory: " + dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
static String readAllAsString(InputStream in) throws IOException {
|
||||
if (in == null)
|
||||
return null;
|
||||
try (in) {
|
||||
return new String(in.readAllBytes(), "UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
static String readAllAsString(URL url) throws IOException {
|
||||
if (url == null)
|
||||
return null;
|
||||
InputStream in = url.openStream();
|
||||
return readAllAsString(url.openStream());
|
||||
}
|
||||
|
||||
static List<String> readAllAsStrings(Enumeration<URL> urls) throws IOException {
|
||||
List<String> result = new ArrayList<>();
|
||||
while (urls.hasMoreElements()) {
|
||||
URL url = urls.nextElement();
|
||||
result.add(readAllAsString(url));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void assertTrue(boolean condition) {
|
||||
if (!condition) throw new RuntimeException();
|
||||
}
|
||||
|
||||
static void assertFalse(boolean condition) {
|
||||
if (condition) throw new RuntimeException();
|
||||
}
|
||||
|
||||
static void assertNull(Object o) {
|
||||
assertTrue(o == null);
|
||||
}
|
||||
|
||||
static void assertNotNull(Object o) {
|
||||
assertTrue(o != null);
|
||||
}
|
||||
|
||||
static void assertEquals(Object actual, Object expected) {
|
||||
if (expected == null) {
|
||||
assertNull(actual);
|
||||
} else {
|
||||
assertTrue(expected.equals(actual));
|
||||
}
|
||||
}
|
||||
|
||||
static void assertNotEquals(Object actual, Object expected) {
|
||||
if (expected == null) {
|
||||
assertNotNull(actual);
|
||||
} else {
|
||||
assertTrue(!expected.equals(actual));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2024, 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.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static jdk.test.lib.process.ProcessTools.executeTestJava;
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8087335
|
||||
* @library /test/lib
|
||||
* @modules jdk.compiler
|
||||
* @build ResourcesTest jdk.test.lib.compiler.CompilerUtils
|
||||
* @run testng ResourcesTest
|
||||
* @summary Driver for basic test of ClassLoader getResource and getResourceAsStream
|
||||
*/
|
||||
|
||||
@Test
|
||||
public class ResourcesTest {
|
||||
|
||||
private static final String TEST_SRC = System.getProperty("test.src");
|
||||
|
||||
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
|
||||
private static final Path CLASSES_DIR = Paths.get("classes");
|
||||
private static final Path MODS_DIR = Paths.get("mods");
|
||||
|
||||
/**
|
||||
* Compiles the modules used by the test and the test Main
|
||||
*/
|
||||
@BeforeTest
|
||||
public void compileAll() throws Exception {
|
||||
boolean compiled;
|
||||
|
||||
// javac --module-source-path mods -d mods src/**
|
||||
compiled = CompilerUtils
|
||||
.compile(SRC_DIR,
|
||||
MODS_DIR,
|
||||
"--module-source-path", SRC_DIR.toString());
|
||||
assertTrue(compiled);
|
||||
|
||||
// javac --module-path mods -d classes Main.java
|
||||
compiled = CompilerUtils
|
||||
.compile(Paths.get(TEST_SRC, "Main.java"),
|
||||
CLASSES_DIR,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"--add-modules", "m1,m2");
|
||||
assertTrue(compiled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the test
|
||||
*/
|
||||
public void runTest() throws Exception {
|
||||
int exitValue
|
||||
= executeTestJava("--module-path", MODS_DIR.toString(),
|
||||
"--add-modules", "m1,m2",
|
||||
"-cp", CLASSES_DIR.toString(),
|
||||
"Main")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
module m1 {
|
||||
exports p1;
|
||||
opens p1.resources;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
package p1;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class Main {
|
||||
private Main() { }
|
||||
|
||||
public static URL getResourceInClassLoader(String name) {
|
||||
return Main.class.getClassLoader().getResource(name);
|
||||
}
|
||||
|
||||
public static Enumeration<URL> getResourcesInClassLoader(String name) throws IOException {
|
||||
return Main.class.getClassLoader().getResources(name);
|
||||
}
|
||||
|
||||
public static InputStream getResourceAsStreamInClassLoader(String name) {
|
||||
return Main.class.getClassLoader().getResourceAsStream(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package p1.impl;
|
||||
|
||||
public class Type { }
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package p1.resources;
|
||||
|
||||
public class Type { }
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
module m2 {
|
||||
exports p2;
|
||||
exports p2.impl to m1;
|
||||
opens p2.resources to m1;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
package p2;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class Main {
|
||||
private Main() { }
|
||||
|
||||
public static URL getResourceInClassLoader(String name) {
|
||||
return Main.class.getClassLoader().getResource(name);
|
||||
}
|
||||
|
||||
public static Enumeration<URL> getResourcesInClassLoader(String name) throws IOException {
|
||||
return Main.class.getClassLoader().getResources(name);
|
||||
}
|
||||
|
||||
public static InputStream getResourceAsStreamInClassLoader(String name) {
|
||||
return Main.class.getClassLoader().getResourceAsStream(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package p2.impl;
|
||||
|
||||
public class Type { }
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package p2.resources;
|
||||
|
||||
public class Type { }
|
||||
|
|
@ -0,0 +1 @@
|
|||
# empty resource
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Class1 loads a native library that calls ClassLoader.findClass in JNI_OnLoad.
|
||||
* Class1 runs concurrently with another thread that opens a signed jar file.
|
||||
*/
|
||||
class Class1 {
|
||||
static {
|
||||
System.loadLibrary("loadLibraryDeadlock");
|
||||
System.out.println("Signed jar loaded from native library.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LoadLibraryDeadlock class triggers the deadlock between the two
|
||||
* lock objects - ZipFile object and ClassLoader.loadedLibraryNames hashmap.
|
||||
* Thread #2 loads a signed jar which leads to acquiring the lock objects in
|
||||
* natural order (ZipFile then HashMap) - loading a signed jar may involve
|
||||
* Providers initialization. Providers may load native libraries.
|
||||
* Thread #1 acquires the locks in reverse order, first entering loadLibrary
|
||||
* called from Class1, then acquiring ZipFile during the search for a class
|
||||
* triggered from JNI.
|
||||
*/
|
||||
import java.lang.*;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class LoadLibraryDeadlock {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("LoadLibraryDeadlock test started");
|
||||
Thread t1 = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
// an instance of unsigned class that loads a native library
|
||||
Class<?> c1 = Class.forName("Class1");
|
||||
Object o = c1.newInstance();
|
||||
System.out.println("Class1 loaded from " + getLocation(c1));
|
||||
} catch (ClassNotFoundException |
|
||||
InstantiationException |
|
||||
IllegalAccessException e) {
|
||||
System.out.println("Class Class1 not found.");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
Thread t2 = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
// load a class from a signed jar, which locks the JarFile
|
||||
Class<?> c2 = Class.forName("p.Class2");
|
||||
System.out.println("Class2 loaded from " + getLocation(c2));
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.out.println("Class Class2 not found.");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
t2.start();
|
||||
t1.start();
|
||||
try {
|
||||
t1.join();
|
||||
t2.join();
|
||||
} catch (InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLocation(Class<?> c) {
|
||||
var pd = c.getProtectionDomain();
|
||||
var cs = pd != null ? pd.getCodeSource() : null;
|
||||
try {
|
||||
// same format as returned by TestLoadLibraryDeadlock::getLocation
|
||||
return cs != null ? cs.getLocation().toURI().getPath() : null;
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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 8266310
|
||||
* @summary Checks if there's no deadlock between the two lock objects -
|
||||
* class loading lock and ClassLoader.loadedLibraryNames hashmap.
|
||||
* @library /test/lib
|
||||
* @build LoadLibraryDeadlock Class1 p.Class2
|
||||
* @run main/othervm/native -Xcheck:jni TestLoadLibraryDeadlock
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.process.*;
|
||||
import jdk.test.lib.util.FileUtils;
|
||||
|
||||
import java.lang.ProcessBuilder;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.spi.ToolProvider;
|
||||
|
||||
import static jdk.test.lib.process.ProcessTools.*;
|
||||
|
||||
public class TestLoadLibraryDeadlock {
|
||||
|
||||
private static final ToolProvider JAR = ToolProvider.findFirst("jar")
|
||||
.orElseThrow(() -> new RuntimeException("ToolProvider for jar not found"));
|
||||
|
||||
private static final String KEYSTORE = "keystore.jks";
|
||||
private static final String STOREPASS = "changeit";
|
||||
private static final String KEYPASS = "changeit";
|
||||
private static final String ALIAS = "test";
|
||||
private static final String DNAME = "CN=test";
|
||||
private static final String VALIDITY = "366";
|
||||
|
||||
private static String testClassPath = System.getProperty("test.classes");
|
||||
private static String testLibraryPath = System.getProperty("test.nativepath");
|
||||
private static String classPathSeparator = System.getProperty("path.separator");
|
||||
|
||||
private static OutputAnalyzer runCommand(File workingDirectory, String... commands) throws Throwable {
|
||||
ProcessBuilder pb = new ProcessBuilder(commands);
|
||||
pb.directory(workingDirectory);
|
||||
System.out.println("COMMAND: " + String.join(" ", commands));
|
||||
return ProcessTools.executeProcess(pb);
|
||||
}
|
||||
|
||||
private static OutputAnalyzer runCommandInTestClassPath(String... commands) throws Throwable {
|
||||
return runCommand(new File(testClassPath), commands);
|
||||
}
|
||||
|
||||
private static OutputAnalyzer genKey() throws Throwable {
|
||||
FileUtils.deleteFileIfExistsWithRetry(
|
||||
Paths.get(testClassPath, KEYSTORE));
|
||||
String keytool = JDKToolFinder.getJDKTool("keytool");
|
||||
return runCommandInTestClassPath(keytool,
|
||||
"-storepass", STOREPASS,
|
||||
"-keypass", KEYPASS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-keyalg", "rsa", "-keysize", "2048",
|
||||
"-genkeypair",
|
||||
"-alias", ALIAS,
|
||||
"-dname", DNAME,
|
||||
"-validity", VALIDITY
|
||||
);
|
||||
}
|
||||
|
||||
private static void createJar(String outputJar, String... classes) throws Throwable {
|
||||
List<String> args = new ArrayList<>();
|
||||
Collections.addAll(args, "cvf", Paths.get(testClassPath, outputJar).toString());
|
||||
for (String c : classes) {
|
||||
Collections.addAll(args, "-C", testClassPath, c);
|
||||
}
|
||||
if (JAR.run(System.out, System.err, args.toArray(new String[0])) != 0) {
|
||||
throw new RuntimeException("jar operation failed");
|
||||
}
|
||||
}
|
||||
|
||||
private static OutputAnalyzer signJar(String jarToSign) throws Throwable {
|
||||
String jarsigner = JDKToolFinder.getJDKTool("jarsigner");
|
||||
return runCommandInTestClassPath(jarsigner,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", STOREPASS,
|
||||
jarToSign, ALIAS
|
||||
);
|
||||
}
|
||||
|
||||
private final static long countLines(OutputAnalyzer output, String string) {
|
||||
return output.asLines()
|
||||
.stream()
|
||||
.filter(s -> s.contains(string))
|
||||
.count();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
genKey()
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
Path aJar = Path.of(testClassPath, "a.jar");
|
||||
Path bJar = Path.of(testClassPath, "b.jar");
|
||||
Path cJar = Path.of(testClassPath, "c.jar");
|
||||
|
||||
FileUtils.deleteFileIfExistsWithRetry(aJar);
|
||||
FileUtils.deleteFileIfExistsWithRetry(bJar);
|
||||
FileUtils.deleteFileIfExistsWithRetry(cJar);
|
||||
|
||||
createJar("a.jar",
|
||||
"LoadLibraryDeadlock.class",
|
||||
"LoadLibraryDeadlock$1.class",
|
||||
"LoadLibraryDeadlock$2.class");
|
||||
|
||||
createJar("b.jar",
|
||||
"Class1.class");
|
||||
|
||||
createJar("c.jar",
|
||||
"p/Class2.class");
|
||||
|
||||
signJar("c.jar")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// load trigger class
|
||||
OutputAnalyzer outputAnalyzer = executeCommand(createTestJavaProcessBuilder("-cp",
|
||||
aJar.toString() + classPathSeparator +
|
||||
bJar.toString() + classPathSeparator +
|
||||
cJar.toString(),
|
||||
"-Djava.library.path=" + testLibraryPath,
|
||||
"LoadLibraryDeadlock"));
|
||||
outputAnalyzer.shouldHaveExitValue(0);
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Java-level deadlock") == 0,
|
||||
"Found a deadlock.");
|
||||
|
||||
// if no deadlock, make sure all components have been loaded
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Class Class1 not found.") == 0,
|
||||
"Unable to load class. Class1 not found.");
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Class Class2 not found.") == 0,
|
||||
"Unable to load class. Class2 not found.");
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Native library loaded.") > 0,
|
||||
"Unable to load native library.");
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Class1 loaded from " + toLocationString(bJar)) > 0,
|
||||
"Unable to load " + toLocationString(bJar));
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Class2 loaded from " + toLocationString(cJar)) > 0,
|
||||
"Unable to load signed " + toLocationString(cJar));
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Signed jar loaded from native library.") > 0,
|
||||
"Unable to load signed jar from native library.");
|
||||
}
|
||||
|
||||
private static String toLocationString(Path path) {
|
||||
// same format as returned by LoadLibraryDeadlock::getLocation
|
||||
return path.toUri().getPath();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "jni.h"
|
||||
|
||||
/*
|
||||
* Native library that loads an arbitrary class from a (signed) jar.
|
||||
* This triggers the search in jars, and the lock in ZipFile is acquired
|
||||
* as a result.
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jclass cl;
|
||||
|
||||
printf("Native library loaded.\n");
|
||||
fflush(stdout);
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
|
||||
return JNI_EVERSION; /* JNI version not supported */
|
||||
}
|
||||
|
||||
// find any class which triggers the search in jars
|
||||
cl = (*env)->FindClass(env, "p/Class2");
|
||||
|
||||
return JNI_VERSION_1_2;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Class2 is loaded from Thread #2 that checks jar signature and from
|
||||
* Thread #1 that loads a native library.
|
||||
*/
|
||||
package p;
|
||||
|
||||
class Class2 {}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LoadLibraryUnload class calls ClassLoader.loadedLibrary from multiple threads
|
||||
*/
|
||||
/*
|
||||
* The driver for this test is LoadLibraryUnloadTest.java.
|
||||
*
|
||||
* @bug 8266310
|
||||
* @summary Loads a native library from multiple class loaders and multiple
|
||||
* threads. This creates a race for loading the library. The winner
|
||||
* loads the library in two threads. All threads except two would fail
|
||||
* with UnsatisfiedLinkError when the class being loaded is already
|
||||
* loaded in a different class loader that won the race. The test
|
||||
* checks that the loaded class is GC'ed, that means the class loader
|
||||
* is GC'ed and the native library is unloaded.
|
||||
*/
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
import java.lang.*;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import jdk.test.lib.util.ForceGC;
|
||||
|
||||
import p.Class1;
|
||||
|
||||
public class LoadLibraryUnload {
|
||||
|
||||
private static class TestLoader extends URLClassLoader {
|
||||
public TestLoader() throws Exception {
|
||||
super(new URL[] { Path.of(System.getProperty("test.classes")).toUri().toURL() });
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
synchronized (getClassLoadingLock(name)) {
|
||||
Class<?> clazz = findLoadedClass(name);
|
||||
if (clazz == null) {
|
||||
try {
|
||||
clazz = findClass(name);
|
||||
} catch (ClassNotFoundException ignore) {
|
||||
}
|
||||
if (clazz == null) {
|
||||
clazz = super.loadClass(name);
|
||||
}
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class LoadLibraryFromClass implements Runnable {
|
||||
Object object;
|
||||
Method method;
|
||||
Object canary;
|
||||
|
||||
public LoadLibraryFromClass(Class<?> fromClass, Object canary) {
|
||||
try {
|
||||
this.object = fromClass.newInstance();
|
||||
this.method = fromClass.getDeclaredMethod("loadLibrary", Object.class);
|
||||
this.canary = canary;
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
throw new RuntimeException(roe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
method.invoke(object, canary);
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
throw new RuntimeException(roe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
int LOADER_COUNT = 5;
|
||||
List<Thread> threads = new ArrayList<>();
|
||||
Object[] canary = new Object[LOADER_COUNT];
|
||||
final WeakReference<Object> wCanary[] = new WeakReference[LOADER_COUNT];
|
||||
|
||||
for (int i = 0 ; i < LOADER_COUNT ; i++) {
|
||||
// LOADER_COUNT loaders and 2X threads in total.
|
||||
// winner loads the library in 2 threads
|
||||
canary[i] = new Object();
|
||||
wCanary[i] = new WeakReference<>(canary[i], null);
|
||||
|
||||
Class<?> clazz = new TestLoader().loadClass("p.Class1");
|
||||
threads.add(new Thread(new LoadLibraryFromClass(clazz, canary[i])));
|
||||
threads.add(new Thread(new LoadLibraryFromClass(clazz, canary[i])));
|
||||
}
|
||||
|
||||
final Set<Throwable> exceptions = ConcurrentHashMap.newKeySet();
|
||||
threads.forEach( t -> {
|
||||
t.setUncaughtExceptionHandler((th, ex) -> {
|
||||
// collect the root cause of each failure
|
||||
Throwable rootCause = ex;
|
||||
while((ex = ex.getCause()) != null) {
|
||||
rootCause = ex;
|
||||
}
|
||||
exceptions.add(rootCause);
|
||||
});
|
||||
t.start();
|
||||
});
|
||||
|
||||
// wait for all threads to finish
|
||||
for (Thread t : threads) {
|
||||
t.join();
|
||||
}
|
||||
|
||||
// expect all errors to be UnsatisfiedLinkError
|
||||
boolean allAreUnsatisfiedLinkError = exceptions
|
||||
.stream()
|
||||
.map(e -> e instanceof UnsatisfiedLinkError)
|
||||
.reduce(true, (i, a) -> i && a);
|
||||
|
||||
// expect exactly 8 errors
|
||||
int expectedErrorCount = (LOADER_COUNT - 1) * 2;
|
||||
Asserts.assertTrue(exceptions.size() == expectedErrorCount,
|
||||
"Expected to see " + expectedErrorCount + " failing threads");
|
||||
|
||||
Asserts.assertTrue(allAreUnsatisfiedLinkError,
|
||||
"All errors have to be UnsatisfiedLinkError");
|
||||
|
||||
// release strong refs
|
||||
threads = null;
|
||||
canary = null;
|
||||
exceptions.clear();
|
||||
|
||||
// Wait for the canary for each of the libraries to be GC'd (cleared)
|
||||
boolean allClear = ForceGC.wait(() -> {
|
||||
for (int i = 0; i < wCanary.length; i++) {
|
||||
if (!wCanary[i].refersTo(null)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
Asserts.assertTrue(allClear, "Not all WeakReferences cleared");
|
||||
|
||||
// Ensure the WeakReferences are strongly referenced until they can be dequeued
|
||||
Reference.reachabilityFence(wCanary);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LoadLibraryUnloadTest ensures all objects (NativeLibrary) are deallocated
|
||||
* when loaded in concurrent mode.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 8266310 8289919 8293282
|
||||
* @summary Checks that JNI_OnLoad is invoked only once when multiple threads
|
||||
* call System.loadLibrary concurrently, and JNI_OnUnload is invoked
|
||||
* when the native library is loaded from a custom class loader.
|
||||
* @library /test/lib
|
||||
* @build LoadLibraryUnload p.Class1
|
||||
* @run main/othervm/native LoadLibraryUnloadTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
import static jdk.test.lib.process.ProcessTools.*;
|
||||
|
||||
public class LoadLibraryUnloadTest {
|
||||
|
||||
private static String testClassPath = System.getProperty("test.classes");
|
||||
private static String testLibraryPath = System.getProperty("test.nativepath");
|
||||
|
||||
private final static long countLines(OutputAnalyzer output, String string) {
|
||||
return output.asLines()
|
||||
.stream()
|
||||
.filter(s -> s.contains(string))
|
||||
.count();
|
||||
}
|
||||
|
||||
private final static void dump(OutputAnalyzer output) {
|
||||
output.asLines()
|
||||
.stream()
|
||||
.forEach(s -> System.out.println(s));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
OutputAnalyzer outputAnalyzer = executeCommand(createTestJavaProcessBuilder(
|
||||
"-Dtest.classes=" + testClassPath,
|
||||
"-Djava.library.path=" + testLibraryPath,
|
||||
"LoadLibraryUnload"));
|
||||
dump(outputAnalyzer);
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Native library loaded from Class1.") == 2,
|
||||
"Native library expected to be loaded in 2 threads.");
|
||||
|
||||
long refCount = countLines(outputAnalyzer, "Native library loaded.");
|
||||
|
||||
Asserts.assertTrue(refCount > 0, "Failed to load native library.");
|
||||
|
||||
System.out.println("Native library loaded in " + refCount + " threads");
|
||||
|
||||
Asserts.assertTrue(refCount == 1, "Native library is loaded more than once.");
|
||||
|
||||
Asserts.assertTrue(
|
||||
countLines(outputAnalyzer, "Native library unloaded.") == refCount,
|
||||
"Failed to unload native library");
|
||||
|
||||
Asserts.assertEquals(0, outputAnalyzer.getExitValue(),
|
||||
"LoadLibraryUnload exit value not zero");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "jni.h"
|
||||
|
||||
static volatile jobject ref = NULL;
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
|
||||
printf("Native library loaded.\n");
|
||||
fflush(stdout);
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
|
||||
return JNI_EVERSION; /* JNI version not supported */
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_2;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_p_Class1_setRef(JNIEnv *env, jobject this, jobject obj) {
|
||||
if (ref == NULL) {
|
||||
// Only create a single GlobalRef
|
||||
ref = (*env)->NewGlobalRef(env, obj);
|
||||
printf("GlobalRef created\n");
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
|
||||
if (ref != NULL) {
|
||||
JNIEnv *env = NULL;
|
||||
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
|
||||
return; /* JNI version not supported */
|
||||
}
|
||||
(*env)->DeleteGlobalRef(env, ref);
|
||||
printf("GlobalRef deleted\n");
|
||||
}
|
||||
printf("Native library unloaded.\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, BELLSOFT. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Class1 loads a native library.
|
||||
*/
|
||||
package p;
|
||||
|
||||
public class Class1 {
|
||||
|
||||
public Class1() {
|
||||
}
|
||||
|
||||
// method called from java threads
|
||||
public void loadLibrary(Object obj) throws Exception {
|
||||
System.loadLibrary("loadLibraryUnload");
|
||||
System.out.println("Native library loaded from Class1.");
|
||||
synchronized (Class1.class) {
|
||||
setRef(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Native method to store an object ref in a native Global reference
|
||||
* to be cleared when the library is unloaded.
|
||||
* @param obj an object
|
||||
*/
|
||||
private static native void setRef(Object obj);
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 8164512 8191360
|
||||
* @requires vm.compMode != "Xcomp"
|
||||
* @comment Under musl, dlclose is a no-op. The static variable 'count' in libnative.c
|
||||
* keeps its value across a GC and the check in Test.java fails.
|
||||
* @requires !vm.musl
|
||||
* @summary verify if the native library is unloaded when the class loader is GC'ed
|
||||
* @library /test/lib/
|
||||
* @build jdk.test.lib.util.ForceGC
|
||||
* @build p.Test
|
||||
* @run main/othervm/native -Xcheck:jni NativeLibraryTest
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jdk.test.lib.util.ForceGC;
|
||||
|
||||
public class NativeLibraryTest {
|
||||
static final Path CLASSES = Paths.get("classes");
|
||||
static int unloadedCount = 0;
|
||||
|
||||
/*
|
||||
* Called by JNI_OnUnload when the native library is unloaded
|
||||
*/
|
||||
static void nativeLibraryUnloaded() {
|
||||
unloadedCount++;
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
setup();
|
||||
|
||||
for (int count=1; count <= 5; count++) {
|
||||
System.out.println("count: " + count);
|
||||
// create a class loader and load a native library
|
||||
runTest();
|
||||
// Unload the class loader and native library, and give the Cleaner
|
||||
// thread a chance to unload the native library.
|
||||
// unloadedCount is incremented when the native library is unloaded.
|
||||
final int finalCount = count;
|
||||
if (!ForceGC.wait(() -> finalCount == unloadedCount)) {
|
||||
throw new RuntimeException("Expected unloaded=" + count +
|
||||
" but got=" + unloadedCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads p.Test class with a new class loader and its static initializer
|
||||
* will load a native library.
|
||||
*
|
||||
* The class loader becomes unreachable when this method returns and
|
||||
* the native library should be unloaded at some point after the class
|
||||
* loader is garbage collected.
|
||||
*/
|
||||
static void runTest() throws Exception {
|
||||
// invoke p.Test.run() that loads the native library
|
||||
Runnable r = newTestRunnable();
|
||||
r.run();
|
||||
|
||||
// reload the native library by the same class loader
|
||||
r.run();
|
||||
|
||||
// load the native library by another class loader
|
||||
Runnable r1 = newTestRunnable();
|
||||
try {
|
||||
r1.run();
|
||||
throw new RuntimeException("should fail to load the native library" +
|
||||
" by another class loader");
|
||||
} catch (UnsatisfiedLinkError e) {}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads p.Test class with a new class loader and returns
|
||||
* a Runnable instance.
|
||||
*/
|
||||
static Runnable newTestRunnable() throws Exception {
|
||||
TestLoader loader = new TestLoader();
|
||||
Class<?> c = Class.forName("p.Test", true, loader);
|
||||
return (Runnable) c.newInstance();
|
||||
}
|
||||
|
||||
static class TestLoader extends URLClassLoader {
|
||||
static URL[] toURLs() {
|
||||
try {
|
||||
return new URL[] { CLASSES.toUri().toURL() };
|
||||
} catch (MalformedURLException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
TestLoader() {
|
||||
super("testloader", toURLs(), ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* move p/Test.class out from classpath to the scratch directory
|
||||
*/
|
||||
static void setup() throws IOException {
|
||||
String dir = System.getProperty("test.classes", ".");
|
||||
Path file = Paths.get("p", "Test.class");
|
||||
Files.createDirectories(CLASSES.resolve("p"));
|
||||
Files.move(Paths.get(dir).resolve(file),
|
||||
CLASSES.resolve("p").resolve("Test.class"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
static jint count = 0;
|
||||
static jclass test_class;
|
||||
static jint current_jni_version = JNI_VERSION_19;
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
JNIEnv *env;
|
||||
jclass cl;
|
||||
|
||||
(*vm)->GetEnv(vm, (void **) &env, current_jni_version);
|
||||
|
||||
cl = (*env)->FindClass(env, "NativeLibraryTest");
|
||||
test_class = (*env)->NewGlobalRef(env, cl);
|
||||
|
||||
// increment the count when JNI_OnLoad is called
|
||||
count++;
|
||||
|
||||
return current_jni_version;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
JNIEnv *env;
|
||||
jmethodID mid;
|
||||
jclass cl;
|
||||
|
||||
(*vm)->GetEnv(vm, (void **) &env, current_jni_version);
|
||||
mid = (*env)->GetStaticMethodID(env, test_class, "nativeLibraryUnloaded", "()V");
|
||||
(*env)->CallStaticVoidMethod(env, test_class, mid);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->FatalError(env, "Exception thrown");
|
||||
}
|
||||
|
||||
cl = (*env)->FindClass(env, "p/Test");
|
||||
if (cl != NULL) {
|
||||
(*env)->FatalError(env, "p/Test class should not be found");
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_p_Test_count
|
||||
(JNIEnv *env, jclass cls) {
|
||||
return count;
|
||||
}
|
||||
37
test/jdk/java/lang/ClassLoader/nativeLibrary/p/Test.java
Normal file
37
test/jdk/java/lang/ClassLoader/nativeLibrary/p/Test.java
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
package p;
|
||||
|
||||
public class Test implements Runnable {
|
||||
public static native int count();
|
||||
|
||||
/**
|
||||
* Tests if the native library is loaded.
|
||||
*/
|
||||
public void run() {
|
||||
System.loadLibrary("nativeLibraryTest");
|
||||
if (count() != 1) {
|
||||
throw new RuntimeException("Expected count = 1 but got " + count());
|
||||
}
|
||||
}
|
||||
}
|
||||
54
test/jdk/java/lang/ClassLoader/package1/Class1.java
Normal file
54
test/jdk/java/lang/ClassLoader/package1/Class1.java
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 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.
|
||||
*/
|
||||
|
||||
package package1;
|
||||
|
||||
public class Class1 {
|
||||
public void testAssert(boolean assertsShouldBeOn) {
|
||||
boolean assertsEnabled = false;
|
||||
assert assertsEnabled = true;
|
||||
if (assertsEnabled != assertsShouldBeOn)
|
||||
throw new RuntimeException("Failure of Asserts Facility.");
|
||||
|
||||
Class1 anonTest = new Class1() {
|
||||
public void testAssert(boolean assertsShouldBeOn) {
|
||||
boolean assertsEnabled2 = false;
|
||||
assert assertsEnabled2 = true;
|
||||
if (assertsEnabled2 != assertsShouldBeOn)
|
||||
throw new RuntimeException("Failure of Asserts Facility.");
|
||||
}
|
||||
};
|
||||
anonTest.testAssert(assertsShouldBeOn);
|
||||
}
|
||||
|
||||
// Named inner class
|
||||
public static class Class11 {
|
||||
public static void testAssert(boolean assertsShouldBeOn) {
|
||||
boolean assertsEnabled3 = false;
|
||||
assert assertsEnabled3 = true;
|
||||
if (assertsEnabled3 != assertsShouldBeOn)
|
||||
throw new RuntimeException("Failure of Asserts Facility.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
53
test/jdk/java/lang/ClassLoader/package1/package3/Class3.java
Normal file
53
test/jdk/java/lang/ClassLoader/package1/package3/Class3.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 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.
|
||||
*/
|
||||
|
||||
package package1.package3;
|
||||
|
||||
public class Class3 {
|
||||
public void testAssert(boolean assertsShouldBeOn) {
|
||||
boolean assertsEnabled = false;
|
||||
assert(assertsEnabled = true);
|
||||
if (assertsEnabled != assertsShouldBeOn)
|
||||
throw new RuntimeException("Failure of Asserts Facility.");
|
||||
|
||||
Class3 anonTest = new Class3() {
|
||||
public void testAssert(boolean assertsShouldBeOn) {
|
||||
boolean assertsEnabled = false;
|
||||
assert(assertsEnabled = true);
|
||||
if (assertsEnabled != assertsShouldBeOn)
|
||||
throw new RuntimeException("Failure of Asserts Facility.");
|
||||
}
|
||||
};
|
||||
anonTest.testAssert(assertsShouldBeOn);
|
||||
}
|
||||
|
||||
// Named inner class
|
||||
public static class Class31 {
|
||||
public static void testAssert(boolean assertsShouldBeOn) {
|
||||
boolean assertsEnabled = false;
|
||||
assert(assertsEnabled = true);
|
||||
if (assertsEnabled != assertsShouldBeOn)
|
||||
throw new RuntimeException("Failure of Asserts Facility.");
|
||||
}
|
||||
}
|
||||
}
|
||||
33
test/jdk/java/lang/ClassLoader/package2/Class2.java
Normal file
33
test/jdk/java/lang/ClassLoader/package2/Class2.java
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 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.
|
||||
*/
|
||||
|
||||
package package2;
|
||||
|
||||
public class Class2 {
|
||||
public void testAssert(boolean assertsShouldBeOn) {
|
||||
boolean assertsEnabled = false;
|
||||
assert(assertsEnabled = true);
|
||||
if (assertsEnabled != assertsShouldBeOn)
|
||||
throw new RuntimeException("Failure of Asserts Facility.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 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
|
||||
* @summary Test java.* class defined by the platform class loader
|
||||
* @modules jdk.zipfs/java.fake
|
||||
* @build jdk.zipfs/java.fake.Fake
|
||||
* @run main DefinePlatformClass
|
||||
*/
|
||||
|
||||
import java.fake.Fake;
|
||||
|
||||
public class DefinePlatformClass {
|
||||
public static void main(String... args) {
|
||||
Fake fake = new Fake();
|
||||
fake.run();
|
||||
ClassLoader loader = fake.getClass().getClassLoader();
|
||||
if (loader != ClassLoader.getPlatformClassLoader()) {
|
||||
throw new RuntimeException("unexpected class loader: " + loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.fake;
|
||||
|
||||
public class Fake {
|
||||
public void run() {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue