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:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View 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();
}
}

View file

@ -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");
}
}
}

View file

@ -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
}
}

View file

@ -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);
}
}
}

View 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");
}
}

View 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");
}
}
}

View 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");
}
}

View 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);
}
}
}

View 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();
}
}
}

View 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;
}
}

View 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);
}
}

View 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();
}
}

View 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);
}
}
}

View 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));
}
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}
}

View 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");
}
}

View file

@ -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);
// }
}
}

View 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();
}
}

View 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");
}
}

View 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 SupBob {
static {
System.out.println("comSA.SupBob loaded");
}
}

View 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");
}
}

View 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 SupAlice {
static {
System.out.println("comSB.SupAlice loaded");
}
}

View file

@ -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 */

View file

@ -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", ""));
}
}

View 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";
}
}

View file

@ -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", ""));
}
}

View 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();
}
}

View file

@ -0,0 +1,2 @@
It really doesn't matter what is in this file, so long as this file is
there.

View 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 + " ...");
}
}

View file

@ -0,0 +1 @@
Fake resource, to test the getResources() variant.

View 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();
}
}
}

View 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);
}
}

View 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);
}
}

View file

@ -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");
}
}

View file

@ -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));
}
});
}
}
}

View 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));
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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 { }

View file

@ -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 { }

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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 { }

View file

@ -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 { }

View file

@ -0,0 +1 @@
# empty resource

View file

@ -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.");
}
}

View file

@ -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);
}
}
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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 {}

View file

@ -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);
}
}

View file

@ -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");
}
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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"));
}
}

View file

@ -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;
}

View 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());
}
}
}

View 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.");
}
}
}

View 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.");
}
}
}

View 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.");
}
}

View file

@ -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);
}
}
}

View file

@ -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() {}
}