undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
179
test/jdk/java/lang/reflect/Proxy/Basic1.java
Normal file
179
test/jdk/java/lang/reflect/Proxy/Basic1.java
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2013, 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 4227192 4487672
|
||||
* @summary This is a basic functional test of the dynamic proxy API (part 1).
|
||||
* @author Peter Jones
|
||||
*
|
||||
* @build Basic1
|
||||
* @run main Basic1
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Basic1 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.err.println(
|
||||
"\nBasic functional test of dynamic proxy API, part 1\n");
|
||||
|
||||
try {
|
||||
Class<?>[] interfaces =
|
||||
new Class<?>[] { Runnable.class, Observer.class };
|
||||
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
|
||||
/*
|
||||
* Generate a proxy class.
|
||||
*/
|
||||
Class<?> proxyClass = Proxy.getProxyClass(loader, interfaces);
|
||||
System.err.println("+ generated proxy class: " + proxyClass);
|
||||
|
||||
/*
|
||||
* Verify that it is public, final, and not abstract.
|
||||
*/
|
||||
int flags = proxyClass.getModifiers();
|
||||
System.err.println(
|
||||
"+ proxy class's modifiers: " + Modifier.toString(flags));
|
||||
if (!Modifier.isPublic(flags)) {
|
||||
throw new RuntimeException("proxy class in not public");
|
||||
}
|
||||
if (!Modifier.isFinal(flags)) {
|
||||
throw new RuntimeException("proxy class in not final");
|
||||
}
|
||||
if (Modifier.isAbstract(flags)) {
|
||||
throw new RuntimeException("proxy class in abstract");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that it is assignable to the proxy interfaces.
|
||||
*/
|
||||
for (Class<?> intf : interfaces) {
|
||||
if (!intf.isAssignableFrom(proxyClass)) {
|
||||
throw new RuntimeException(
|
||||
"proxy class not assignable to proxy interface " +
|
||||
intf.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that it has the given permutation of interfaces.
|
||||
*/
|
||||
List<Class<?>> l1 = Arrays.asList(interfaces);
|
||||
List<Class<?>> l2 = Arrays.asList(proxyClass.getInterfaces());
|
||||
System.err.println("+ proxy class's interfaces: " + l2);
|
||||
if (!l1.equals(l2)) {
|
||||
throw new RuntimeException(
|
||||
"proxy class interfaces are " + l2 +
|
||||
" (expected " + l1 + ")");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that system agress that it is a proxy class.
|
||||
*/
|
||||
if (Proxy.isProxyClass(Object.class)) {
|
||||
throw new RuntimeException(
|
||||
"Proxy.isProxyClass returned true for java.lang.Object");
|
||||
}
|
||||
if (!Proxy.isProxyClass(proxyClass)) {
|
||||
throw new RuntimeException(
|
||||
"Proxy.isProxyClass returned false for proxy class");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that its protection domain is the bootstrap domain.
|
||||
*/
|
||||
ProtectionDomain pd = proxyClass.getProtectionDomain();
|
||||
System.err.println("+ proxy class's protection domain: " + pd);
|
||||
if (!pd.implies(new AllPermission())) {
|
||||
throw new RuntimeException(
|
||||
"proxy class does not have AllPermission");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that it has a constructor that takes an
|
||||
* InvocationHandler instance.
|
||||
*/
|
||||
Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class);
|
||||
|
||||
/*
|
||||
* Test constructor with null InvocationHandler
|
||||
*/
|
||||
try {
|
||||
cons.newInstance(new Object[] { null });
|
||||
throw new RuntimeException("Expected NullPointerException thrown");
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable t = e.getTargetException();
|
||||
if (!(t instanceof NullPointerException)) {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a proxy instance.
|
||||
*/
|
||||
Handler handler = new Handler();
|
||||
Object proxy = cons.newInstance(handler);
|
||||
handler.currentProxy = proxy;
|
||||
|
||||
/*
|
||||
* Invoke a method on a proxy instance.
|
||||
*/
|
||||
Method m = Runnable.class.getMethod("run");
|
||||
((Runnable) proxy).run();
|
||||
if (!handler.lastMethod.equals(m)) {
|
||||
throw new RuntimeException(
|
||||
"proxy method invocation failure (lastMethod = " +
|
||||
handler.lastMethod + ")");
|
||||
}
|
||||
|
||||
System.err.println("\nTEST PASSED");
|
||||
|
||||
} catch (Throwable e) {
|
||||
System.err.println("\nTEST FAILED:");
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("TEST FAILED: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static class Handler implements InvocationHandler {
|
||||
|
||||
Object currentProxy;
|
||||
Method lastMethod;
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args)
|
||||
throws Throwable
|
||||
{
|
||||
if (proxy != currentProxy) {
|
||||
throw new RuntimeException(
|
||||
"wrong proxy instance passed to invoke method");
|
||||
}
|
||||
lastMethod = method;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
156
test/jdk/java/lang/reflect/Proxy/Boxing.java
Normal file
156
test/jdk/java/lang/reflect/Proxy/Boxing.java
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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 4889342
|
||||
* @summary This test verifies that when a primitive boolean value is
|
||||
* passed by a dynamic proxy class to an invocation handler, it is
|
||||
* boxed as one of the canonical Boolean instances (Boolean.TRUE or
|
||||
* Boolean.FALSE). This test also exercises a dynamic proxy class's
|
||||
* boxing of all primitive types.
|
||||
* @author Peter Jones
|
||||
*
|
||||
* @run main Boxing
|
||||
*/
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Random;
|
||||
|
||||
public class Boxing {
|
||||
|
||||
private interface Test {
|
||||
void m(byte b,
|
||||
char c,
|
||||
double d,
|
||||
float f,
|
||||
int i,
|
||||
long j,
|
||||
short s,
|
||||
boolean z);
|
||||
}
|
||||
|
||||
private static final int REPS = 100000;
|
||||
|
||||
private byte b;
|
||||
private char c;
|
||||
private double d;
|
||||
private float f;
|
||||
private int i;
|
||||
private long j;
|
||||
private short s;
|
||||
private boolean z;
|
||||
|
||||
public static void main(String[] args) {
|
||||
(new Boxing()).run();
|
||||
System.err.println("TEST PASSED");
|
||||
}
|
||||
|
||||
private void run() {
|
||||
Random random = new Random(42); // ensure consistent test domain
|
||||
|
||||
Test proxy = (Test) Proxy.newProxyInstance(
|
||||
Test.class.getClassLoader(),
|
||||
new Class<?>[] { Test.class },
|
||||
new TestHandler());
|
||||
|
||||
for (int rep = 0; rep < REPS; rep++) {
|
||||
b = (byte) random.nextInt();
|
||||
c = (char) random.nextInt();
|
||||
d = random.nextDouble();
|
||||
f = random.nextFloat();
|
||||
i = random.nextInt();
|
||||
j = random.nextLong();
|
||||
s = (short) random.nextInt();
|
||||
z = random.nextBoolean();
|
||||
proxy.m(b,c,d,f,i,j,s,z);
|
||||
}
|
||||
}
|
||||
|
||||
private class TestHandler implements InvocationHandler {
|
||||
public Object invoke(Object proxy, Method method, Object[] args)
|
||||
throws Throwable
|
||||
{
|
||||
if (!method.getName().equals("m")) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
byte b2 = ((Byte) args[0]).byteValue();
|
||||
if (b2 != b) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong byte, expected " + b + " but got " + b2);
|
||||
}
|
||||
|
||||
char c2 = ((Character) args[1]).charValue();
|
||||
if (c2 != c) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong char, expected " + c + " but got " + c2);
|
||||
}
|
||||
|
||||
double d2 = ((Double) args[2]).doubleValue();
|
||||
if (d2 != d) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong double, expected " + d + " but got " + d2);
|
||||
}
|
||||
|
||||
float f2 = ((Float) args[3]).floatValue();
|
||||
if (f2 != f) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong float, expected " + f + " but got " + f2);
|
||||
}
|
||||
|
||||
int i2 = ((Integer) args[4]).intValue();
|
||||
if (i2 != i) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong int, expected " + i + " but got " + i2);
|
||||
}
|
||||
|
||||
long j2 = ((Long) args[5]).longValue();
|
||||
if (j2 != j) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong long, expected " + j + " but got " + j2);
|
||||
}
|
||||
|
||||
short s2 = ((Short) args[6]).shortValue();
|
||||
if (s2 != s) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong short, expected " + s + " but got " + s2);
|
||||
}
|
||||
|
||||
Boolean Z = Boolean.valueOf(z);
|
||||
Boolean Z2 = (Boolean) args[7];
|
||||
if (Z2 != Z) {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
"wrong Boolean instance, expected " +
|
||||
identityToString(Z) + " but got " + identityToString(Z2));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String identityToString(Object obj) {
|
||||
return obj.toString() + "@" + System.identityHashCode(obj);
|
||||
}
|
||||
}
|
||||
86
test/jdk/java/lang/reflect/Proxy/BridgeMethodsTest.java
Normal file
86
test/jdk/java/lang/reflect/Proxy/BridgeMethodsTest.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8370839
|
||||
* @summary Behavior of bridge methods in interfaces
|
||||
* @run junit BridgeMethodsTest
|
||||
*/
|
||||
public class BridgeMethodsTest {
|
||||
|
||||
interface StringCallable extends Callable<String> {
|
||||
@Override
|
||||
String call(); // throws no exception
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionTypes() throws Throwable {
|
||||
class MyException extends Exception {}
|
||||
// This proxy has two distinct methods, even though the
|
||||
// Java language would treat the first one as overridden:
|
||||
// Object call() throws Exception; - from Callable
|
||||
// String call(); - from StringCallable
|
||||
var instance = Proxy.newProxyInstance(StringCallable.class.getClassLoader(),
|
||||
new Class[] { StringCallable.class }, (_, _, _) -> { throw new MyException(); });
|
||||
// The exception can't be thrown through StringCallable.call which has no throws
|
||||
var undeclared = assertThrows(UndeclaredThrowableException.class, () -> ((StringCallable) instance).call());
|
||||
assertInstanceOf(MyException.class, undeclared.getCause());
|
||||
// But it can be thrown through Callable.call which permits Exception
|
||||
assertThrows(MyException.class, () -> ((Callable<?>) instance).call());
|
||||
}
|
||||
|
||||
interface SpecificConsumer extends Consumer<String> {
|
||||
@Override
|
||||
void accept(String s);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void testMethodObjects() throws Throwable {
|
||||
List<Method> methods = new ArrayList<>();
|
||||
// This proxy has two distinct methods, even though the
|
||||
// Java language would treat the first one as overridden:
|
||||
// void accept(Object); - from Consumer
|
||||
// void accept(String); - from SpecificConsumer
|
||||
var instance = Proxy.newProxyInstance(SpecificConsumer.class.getClassLoader(),
|
||||
new Class[] { SpecificConsumer.class }, (_, m, _) -> methods.add(m));
|
||||
((Consumer<Object>) instance).accept(null);
|
||||
((SpecificConsumer) instance).accept(null);
|
||||
assertEquals(2, methods.size());
|
||||
// invocation handler gets different method due to covariant parameter types
|
||||
assertNotEquals(methods.getFirst(), methods.getLast());
|
||||
}
|
||||
}
|
||||
50
test/jdk/java/lang/reflect/Proxy/CharType.java
Normal file
50
test/jdk/java/lang/reflect/Proxy/CharType.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4346224
|
||||
* @summary Test against a typo in ProxyGenerator:
|
||||
* "java/lang/Character" should be used instead of
|
||||
* "java/lang/Char".
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class CharType {
|
||||
|
||||
public static void main (String args[]) throws Exception {
|
||||
Proxy.newProxyInstance(CharMethod.class.getClassLoader(), new Class[] {
|
||||
CharMethod.class }, new H());
|
||||
}
|
||||
|
||||
static interface CharMethod {
|
||||
void setChar(char c);
|
||||
}
|
||||
|
||||
static class H implements InvocationHandler {
|
||||
public Object invoke(Object o, Method m, Object[] arr) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
test/jdk/java/lang/reflect/Proxy/ClassRestrictions.java
Normal file
123
test/jdk/java/lang/reflect/Proxy/ClassRestrictions.java
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 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 4227192 8004928 8072656 8319436
|
||||
* @summary This is a test of the restrictions on the parameters that may
|
||||
* be passed to the Proxy.getProxyClass method.
|
||||
* @author Peter Jones
|
||||
*
|
||||
* @build ClassRestrictions
|
||||
* @run junit ClassRestrictions
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
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.jupiter.api.Assertions.*;
|
||||
|
||||
public class ClassRestrictions {
|
||||
|
||||
public interface Bar {
|
||||
int foo();
|
||||
}
|
||||
|
||||
public interface Baz {
|
||||
long foo();
|
||||
}
|
||||
|
||||
interface Bashful {
|
||||
void foo();
|
||||
}
|
||||
|
||||
private static final String TEST_CLASSES = System.getProperty("test.classes", ".");
|
||||
private static final ClassLoader LOADER = ClassRestrictions.class.getClassLoader();
|
||||
|
||||
static Stream<List<Class<?>>> badProxyInterfaces() {
|
||||
return Stream.of(
|
||||
List.of(Object.class), // proxy interface cannot be a class
|
||||
List.of(int.class), // proxy interface can't be primitive type
|
||||
List.of(Bar.class, Bar.class), // cannot have repeated interfaces
|
||||
// two proxy interfaces have the method of same method name but different return type
|
||||
List.of(Bar.class, Baz.class)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test cases for illegal proxy interfaces
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("badProxyInterfaces")
|
||||
void testForName(List<Class<?>> interfaces) {
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(LOADER, interfaces.toArray(Class[]::new)));
|
||||
}
|
||||
|
||||
private static final String nonPublicIntrfaceName = "java.util.zip.ZipConstants";
|
||||
|
||||
/*
|
||||
* All non-public interfaces must be in the same package.
|
||||
*/
|
||||
@Test
|
||||
void testNonPublicIntfs() throws Exception {
|
||||
var nonPublic1 = Bashful.class;
|
||||
var nonPublic2 = Class.forName(nonPublicIntrfaceName);
|
||||
assertFalse(Modifier.isPublic(nonPublic2.getModifiers()),
|
||||
"Interface " + nonPublicIntrfaceName + " is public and need to be changed!");
|
||||
var interfaces = new Class<?>[] { nonPublic1, nonPublic2 };
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(LOADER, interfaces));
|
||||
}
|
||||
|
||||
static Stream<ClassLoader> loaders() {
|
||||
return Stream.of(null,
|
||||
ClassLoader.getPlatformClassLoader(),
|
||||
ClassLoader.getSystemClassLoader(),
|
||||
LOADER);
|
||||
}
|
||||
|
||||
/*
|
||||
* All of the interfaces types must be visible by name though the
|
||||
* specified class loader.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("loaders")
|
||||
void testNonVisibleInterface(ClassLoader loader) throws Exception {
|
||||
String[] cpaths = TEST_CLASSES.split(File.pathSeparator);
|
||||
URL[] urls = new URL[cpaths.length];
|
||||
for (int i = 0; i < cpaths.length; i++) {
|
||||
urls[i] = Paths.get(cpaths[i]).toUri().toURL();
|
||||
}
|
||||
var altLoader = new URLClassLoader(urls, null);
|
||||
var altBarClass = Class.forName(Bar.class.getName(), false, altLoader);
|
||||
var interfaces = new Class<?>[]{ altBarClass };
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(loader, interfaces));
|
||||
}
|
||||
}
|
||||
371
test/jdk/java/lang/reflect/Proxy/DefaultMethods.java
Normal file
371
test/jdk/java/lang/reflect/Proxy/DefaultMethods.java
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2026, 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.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8159746
|
||||
* @run junit DefaultMethods
|
||||
* @summary Basic tests for Proxy::invokeSuper default method
|
||||
*/
|
||||
|
||||
public class DefaultMethods {
|
||||
public interface I1 {
|
||||
default int m() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
public interface I2 {
|
||||
default int m() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
private void privateMethod() {
|
||||
throw new Error("should not reach here");
|
||||
}
|
||||
}
|
||||
|
||||
// I3::m inherits from I2:m
|
||||
public interface I3 extends I2 {
|
||||
default int m3(String... s) {
|
||||
return Arrays.stream(s).mapToInt(String::length).sum();
|
||||
}
|
||||
}
|
||||
|
||||
public interface I4 extends I1, I2 {
|
||||
default int m() {
|
||||
return 40;
|
||||
}
|
||||
|
||||
default int mix(int a, String b) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public interface I12 extends I1, I2 {
|
||||
@Override
|
||||
int m();
|
||||
|
||||
default int sum(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
default Object[] concat(Object first, Object... rest) {
|
||||
Object[] result = new Object[1 + rest.length];
|
||||
result[0] = first;
|
||||
System.arraycopy(rest, 0, result, 1, rest.length);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IX {
|
||||
default void doThrow(Throwable exception) throws Throwable {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method findDefaultMethod(Class<?> refc, Method m) {
|
||||
assertTrue(refc.isInterface());
|
||||
|
||||
Method method = assertDoesNotThrow(() -> refc.getMethod(m.getName(), m.getParameterTypes()));
|
||||
assertTrue(method.isDefault());
|
||||
return method;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
Object proxy = Proxy.newProxyInstance(loader, new Class<?>[] { I1.class, I2.class},
|
||||
(o, method, params) -> {
|
||||
return InvocationHandler.invokeDefault(o, findDefaultMethod(I2.class, method), params);
|
||||
});
|
||||
I1 i1 = (I1) proxy;
|
||||
assertEquals(20, i1.m());
|
||||
}
|
||||
|
||||
// a default method is declared in one of the proxy interfaces
|
||||
private static Object[][] defaultMethods() {
|
||||
return new Object[][]{
|
||||
new Object[]{new Class<?>[]{I1.class, I2.class}, true, 10},
|
||||
new Object[]{new Class<?>[]{I1.class, I3.class}, true, 10},
|
||||
new Object[]{new Class<?>[]{I1.class, I12.class}, true, 10},
|
||||
new Object[]{new Class<?>[]{I2.class, I12.class}, true, 20},
|
||||
new Object[]{new Class<?>[]{I4.class}, true, 40},
|
||||
new Object[]{new Class<?>[]{I4.class, I3.class}, true, 40},
|
||||
new Object[]{new Class<?>[]{I12.class}, false, -1},
|
||||
new Object[]{new Class<?>[]{I12.class, I1.class, I2.class}, false, -1}
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("defaultMethods")
|
||||
public void testDefaultMethod(Class<?>[] intfs, boolean isDefault, int expected) throws Throwable {
|
||||
InvocationHandler ih = (proxy, method, params) -> {
|
||||
System.out.format("invoking %s with parameters: %s%n", method, Arrays.toString(params));
|
||||
switch (method.getName()) {
|
||||
case "m":
|
||||
assertEquals(isDefault, method.isDefault());
|
||||
assertTrue(Arrays.stream(proxy.getClass().getInterfaces())
|
||||
.anyMatch(intf -> method.getDeclaringClass() == intf),
|
||||
Arrays.toString(proxy.getClass().getInterfaces()));
|
||||
if (method.isDefault()) {
|
||||
return InvocationHandler.invokeDefault(proxy, method, params);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException(method.toString());
|
||||
}
|
||||
};
|
||||
|
||||
Object proxy = Proxy.newProxyInstance(DefaultMethods.class.getClassLoader(), intfs, ih);
|
||||
Method m = proxy.getClass().getMethod("m");
|
||||
int result = (int)m.invoke(proxy);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
// a default method may be declared in a proxy interface or
|
||||
// inherited from a superinterface of a proxy interface
|
||||
private static Object[][] supers() {
|
||||
return new Object[][]{
|
||||
// invoke "m" implemented in the first proxy interface
|
||||
// same as the method passed to InvocationHandler::invoke
|
||||
new Object[]{new Class<?>[]{I1.class}, I1.class, 10},
|
||||
new Object[]{new Class<?>[]{I2.class}, I2.class, 20},
|
||||
new Object[]{new Class<?>[]{I1.class, I2.class}, I1.class, 10},
|
||||
// "m" is implemented in I2, an indirect superinterface of I3
|
||||
new Object[]{new Class<?>[]{I3.class}, I3.class, 20},
|
||||
// "m" is implemented in I1, I2 and overridden in I4
|
||||
new Object[]{new Class<?>[]{I4.class}, I4.class, 40},
|
||||
// invoke "m" implemented in the second proxy interface
|
||||
// different from the method passed to InvocationHandler::invoke
|
||||
new Object[]{new Class<?>[]{I1.class, I2.class}, I2.class, 20},
|
||||
new Object[]{new Class<?>[]{I1.class, I3.class}, I3.class, 20},
|
||||
// I2::m is implemented in more than one proxy interface directly or indirectly
|
||||
// I3::m resolves to I2::m (indirect superinterface)
|
||||
// I2 is the superinterface of I4 and I4 overrides m
|
||||
// the proxy class can invoke I4::m and I2::m
|
||||
new Object[]{new Class<?>[]{I3.class, I4.class}, I3.class, 20},
|
||||
new Object[]{new Class<?>[]{I3.class, I4.class}, I4.class, 40},
|
||||
new Object[]{new Class<?>[]{I4.class, I3.class}, I3.class, 20},
|
||||
new Object[]{new Class<?>[]{I4.class, I3.class}, I4.class, 40}
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("supers")
|
||||
public void testSuper(Class<?>[] intfs, Class<?> proxyInterface, int expected) throws Throwable {
|
||||
final InvocationHandler ih = (proxy, method, params) -> {
|
||||
switch (method.getName()) {
|
||||
case "m":
|
||||
assertTrue(method.isDefault());
|
||||
return InvocationHandler.invokeDefault(proxy, findDefaultMethod(proxyInterface, method), params);
|
||||
default:
|
||||
throw new UnsupportedOperationException(method.toString());
|
||||
}
|
||||
};
|
||||
ClassLoader loader = proxyInterface.getClassLoader();
|
||||
Object proxy = Proxy.newProxyInstance(loader, intfs, ih);
|
||||
if (proxyInterface == I1.class) {
|
||||
I1 i1 = (I1) proxy;
|
||||
assertEquals(expected, i1.m());
|
||||
} else if (proxyInterface == I2.class) {
|
||||
I2 i2 = (I2) proxy;
|
||||
assertEquals(expected, i2.m());
|
||||
} else if (proxyInterface == I3.class) {
|
||||
I3 i3 = (I3) proxy;
|
||||
assertEquals(expected, i3.m());
|
||||
} else if (proxyInterface == I4.class) {
|
||||
I4 i4 = (I4) proxy;
|
||||
assertEquals(expected, i4.m());
|
||||
} else {
|
||||
throw new UnsupportedOperationException(proxyInterface.toString());
|
||||
}
|
||||
// invoke via InvocationHandler.invokeDefaultMethod directly
|
||||
assertEquals(expected, InvocationHandler.invokeDefault(proxy, proxyInterface.getMethod("m")));
|
||||
}
|
||||
|
||||
// invoke I12 default methods with parameters and var args
|
||||
@Test
|
||||
public void testI12() throws Throwable {
|
||||
final InvocationHandler ih = (proxy, method, params) -> {
|
||||
System.out.format("invoking %s with parameters: %s%n", method, Arrays.toString(params));
|
||||
switch (method.getName()) {
|
||||
case "sum":
|
||||
case "concat":
|
||||
assertTrue(method.isDefault());
|
||||
return InvocationHandler.invokeDefault(proxy, method, params);
|
||||
default:
|
||||
throw new UnsupportedOperationException(method.toString());
|
||||
}
|
||||
};
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
I12 i12 = (I12) Proxy.newProxyInstance(loader, new Class<?>[] { I12.class }, ih);
|
||||
assertEquals(3, i12.sum(1, 2));
|
||||
assertArrayEquals(new Object[]{1, 2, 3, 4}, i12.concat(1, 2, 3, 4));
|
||||
Method m = I12.class.getMethod("concat", Object.class, Object[].class);
|
||||
assertTrue(m.isDefault());
|
||||
assertArrayEquals(new Object[] {100, "foo", true, "bar"}, (Object[])
|
||||
InvocationHandler.invokeDefault(i12, m, 100, new Object[] {"foo", true, "bar"}));
|
||||
}
|
||||
|
||||
// test a no-arg default method with and without arguments passed in the invocation
|
||||
@Test
|
||||
public void testEmptyArgument() throws Throwable {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
Object proxy = Proxy.newProxyInstance(loader, new Class<?>[]{I4.class}, HANDLER);
|
||||
Method m1 = I4.class.getMethod("m");
|
||||
assertSame(I4.class, m1.getDeclaringClass());
|
||||
assertTrue(m1.isDefault());
|
||||
InvocationHandler.invokeDefault(proxy, m1);
|
||||
InvocationHandler.invokeDefault(proxy, m1, new Object[0]);
|
||||
|
||||
Method m2 = I4.class.getMethod("mix", int.class, String.class);
|
||||
assertSame(I4.class, m1.getDeclaringClass());
|
||||
assertTrue(m1.isDefault());
|
||||
InvocationHandler.invokeDefault(proxy, m2, Integer.valueOf(100), "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarArgs() throws Throwable {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
I3 proxy = (I3)Proxy.newProxyInstance(loader, new Class<?>[]{I3.class}, HANDLER);
|
||||
Method m = I3.class.getMethod("m3", String[].class);
|
||||
assertTrue(m.isVarArgs() && m.isDefault());
|
||||
assertEquals(5, proxy.m3("a", "b", "cde"));
|
||||
assertEquals(3, InvocationHandler.invokeDefault(proxy, m, (Object)new String[] { "a", "bc" }));
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke I12::m which is an abstract method
|
||||
*/
|
||||
@Test
|
||||
public void invokeAbstractMethod() throws Exception {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
I12 proxy = (I12) Proxy.newProxyInstance(loader, new Class<?>[]{I12.class}, HANDLER);
|
||||
Method method = I12.class.getMethod("m");
|
||||
assertSame(I12.class, method.getDeclaringClass());
|
||||
assertFalse(method.isDefault());
|
||||
assertThrows(IllegalArgumentException.class, () -> proxy.m());
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke a non proxy (default) method with parameters
|
||||
*/
|
||||
@Test
|
||||
public void invokeNonProxyMethod() throws Throwable {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
I3 proxy = (I3) Proxy.newProxyInstance(loader, new Class<?>[]{I3.class}, HANDLER);
|
||||
Method m = I4.class.getMethod("mix", int.class, String.class);
|
||||
assertTrue(m.isDefault());
|
||||
assertThrows(IllegalArgumentException.class, () -> InvocationHandler.invokeDefault(proxy, m));
|
||||
}
|
||||
|
||||
// negative cases
|
||||
private static Object[][] negativeCases() {
|
||||
return new Object[][]{
|
||||
// I4::m overrides I1::m and I2::m
|
||||
new Object[] { new Class<?>[]{I4.class}, I1.class, "m" },
|
||||
new Object[] { new Class<?>[]{I4.class}, I2.class, "m" },
|
||||
// I12::m is not a default method
|
||||
new Object[] { new Class<?>[]{I12.class}, I12.class, "m" },
|
||||
// non-proxy default method
|
||||
new Object[] { new Class<?>[]{I3.class}, I1.class, "m" },
|
||||
// not a default method and not a proxy interface
|
||||
new Object[] { new Class<?>[]{I12.class}, DefaultMethods.class, "test" },
|
||||
new Object[] { new Class<?>[]{I12.class}, Runnable.class, "run" },
|
||||
// I2::privateMethod is a private method
|
||||
new Object[] { new Class<?>[]{I3.class}, I2.class, "privateMethod" }
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("negativeCases")
|
||||
public void testNegativeCase(Class<?>[] interfaces, Class<?> defc, String name)
|
||||
throws Throwable {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
Object proxy = Proxy.newProxyInstance(loader, interfaces, HANDLER);
|
||||
Method method = defc.getDeclaredMethod(name);
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
InvocationHandler.invokeDefault(proxy, method));
|
||||
}
|
||||
|
||||
private static Object[] illegalArguments() {
|
||||
return new Object[] {
|
||||
new Object[] { null },
|
||||
new Object[] { new Object[] { 100 }},
|
||||
new Object[] { new Object[] { 100, "foo", 100 }},
|
||||
new Object[] { new Object[] { 100L, "foo" }},
|
||||
new Object[] { new Object[] { "foo", 100 }},
|
||||
new Object[] { new Object[] { null, "foo" }}
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("illegalArguments")
|
||||
public void testIllegalArgument(Object[] args) throws Throwable {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
I4 proxy = (I4)Proxy.newProxyInstance(loader, new Class<?>[]{I4.class}, HANDLER);
|
||||
Method m = I4.class.getMethod("mix", int.class, String.class);
|
||||
assertTrue(m.isDefault());
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
InvocationHandler.invokeDefault(proxy, m, args));
|
||||
}
|
||||
|
||||
private static Object[][] throwables() {
|
||||
return new Object[][] {
|
||||
new Object[] { new IOException() },
|
||||
new Object[] { new IllegalArgumentException() },
|
||||
new Object[] { new ClassCastException() },
|
||||
new Object[] { new NullPointerException() },
|
||||
new Object[] { new AssertionError() },
|
||||
new Object[] { new Throwable() }
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("throwables")
|
||||
public void testInvocationException(Throwable exception) throws Throwable {
|
||||
ClassLoader loader = DefaultMethods.class.getClassLoader();
|
||||
IX proxy = (IX)Proxy.newProxyInstance(loader, new Class<?>[]{IX.class}, HANDLER);
|
||||
Method m = IX.class.getMethod("doThrow", Throwable.class);
|
||||
assertSame(exception, assertThrows(Throwable.class, () ->
|
||||
InvocationHandler.invokeDefault(proxy, m, exception)));
|
||||
}
|
||||
|
||||
private static final InvocationHandler HANDLER = (proxy, method, params) -> {
|
||||
System.out.format("invoking %s with parameters: %s%n", method, Arrays.toString(params));
|
||||
return InvocationHandler.invokeDefault(proxy, method, params);
|
||||
};
|
||||
}
|
||||
63
test/jdk/java/lang/reflect/Proxy/HiddenProxyInterface.java
Normal file
63
test/jdk/java/lang/reflect/Proxy/HiddenProxyInterface.java
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2026, 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 8250219
|
||||
* @run junit HiddenProxyInterface
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class HiddenProxyInterface {
|
||||
private static final Path CLASSES_DIR = Paths.get(System.getProperty("test.classes"));
|
||||
|
||||
interface Intf {
|
||||
void m();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHiddenInterface() throws Exception {
|
||||
Path classFile = CLASSES_DIR.resolve("HiddenProxyInterface$Intf.class");
|
||||
byte[] bytes = Files.readAllBytes(classFile);
|
||||
Class<?> hiddenIntf = MethodHandles.lookup().defineHiddenClass(bytes, false).lookupClass();
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.newProxyInstance(
|
||||
HiddenProxyInterface.class.getClassLoader(),
|
||||
new Class<?>[]{ hiddenIntf },
|
||||
new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
59
test/jdk/java/lang/reflect/Proxy/LazyInitializationTest.java
Normal file
59
test/jdk/java/lang/reflect/Proxy/LazyInitializationTest.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 2026, 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.lang.reflect.Proxy;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8285401
|
||||
* @summary Avoid initialization of parameter types in proxy construction
|
||||
* @run junit LazyInitializationTest
|
||||
*/
|
||||
public final class LazyInitializationTest {
|
||||
private static volatile boolean initialized = false;
|
||||
|
||||
interface Intf {
|
||||
void m(Parameter parameter);
|
||||
}
|
||||
|
||||
static class Parameter {
|
||||
static {
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLazyInitialization() {
|
||||
Intf value = (Intf) Proxy.newProxyInstance(LazyInitializationTest.class.getClassLoader(),
|
||||
new Class<?>[]{ Intf.class },
|
||||
(proxy, method, args) -> null);
|
||||
assertFalse(initialized, "parameter type initialized unnecessarily");
|
||||
|
||||
value.m(new Parameter());
|
||||
assertTrue(initialized, "parameter type initialized after instantiation");
|
||||
}
|
||||
}
|
||||
106
test/jdk/java/lang/reflect/Proxy/NonPublicMethodTypeTest.java
Normal file
106
test/jdk/java/lang/reflect/Proxy/NonPublicMethodTypeTest.java
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 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.
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8333854 8370839
|
||||
* @summary Behavior of methods whose signature has package-private
|
||||
* class or interfaces but the proxy interface is public
|
||||
* @run junit NonPublicMethodTypeTest
|
||||
*/
|
||||
public class NonPublicMethodTypeTest {
|
||||
// Java language and JVM allow using fields and methods with inaccessible
|
||||
// classes or interfaces in its signature, as long as the field or method
|
||||
// is accessible and its declaring class or interface is accessible.
|
||||
// Such inaccessible classes and interfaces are treated as if an arbitrary
|
||||
// subtype of their accessible types, or an arbitrary supertype of their
|
||||
// accessible subtypes.
|
||||
// java.lang.invoke is stricter - MethodType constant pool entry resolution
|
||||
// for such signatures fail, so they can't be used for MethodHandle or indy.
|
||||
enum Internal { INSTANCE }
|
||||
|
||||
public interface InternalParameter {
|
||||
void call(Internal parameter);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNonPublicParameter() throws Throwable {
|
||||
// Creation should be successful
|
||||
// 8333854 - BSM usage fails for looking up such methods
|
||||
InternalParameter instance = (InternalParameter) Proxy.newProxyInstance(
|
||||
InternalParameter.class.getClassLoader(),
|
||||
new Class[] { InternalParameter.class },
|
||||
(_, _, _) -> null);
|
||||
assertNotSame(Internal.class.getPackage(),
|
||||
instance.getClass().getPackage(),
|
||||
"Proxy class should not be able to access method parameter " +
|
||||
"Internal class's package");
|
||||
// Calls should be always successful
|
||||
instance.call(null);
|
||||
instance.call(Internal.INSTANCE);
|
||||
}
|
||||
|
||||
public interface InternalReturn {
|
||||
Internal call();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNonPublicReturn() throws Throwable {
|
||||
AtomicReference<Internal> returnValue = new AtomicReference<>();
|
||||
// Creation should be successful
|
||||
// A lot of annotation interfaces are implemented by such proxy classes,
|
||||
// due to presence of package-private annotation interface or enum-typed
|
||||
// elements in public annotation interfaces.
|
||||
InternalReturn instance = (InternalReturn) Proxy.newProxyInstance(
|
||||
InternalReturn.class.getClassLoader(),
|
||||
new Class[] { InternalReturn.class },
|
||||
(_, _, _) -> returnValue.get());
|
||||
assertNotSame(Internal.class.getPackage(),
|
||||
instance.getClass().getPackage(),
|
||||
"Proxy class should not be able to access method parameter " +
|
||||
"Internal class's package");
|
||||
|
||||
// The generated call() implementation is as follows:
|
||||
// aload0, getfield Proxy.h, aload 0, getstatic (Method), aconst_null,
|
||||
// invokevirtual InvocationHandler::invoke(Object, Method, Object[])Object,
|
||||
// checkcast Internal.class, areturn
|
||||
// In this bytecode, checkcast Internal.class will fail with a
|
||||
// IllegalAccessError as a result of resolution of Internal.class
|
||||
// if and only if the incoming reference is non-null.
|
||||
|
||||
// checkcast does not perform access check for null
|
||||
returnValue.set(null);
|
||||
instance.call();
|
||||
// checkcast fails - proxy class cannot access the return type
|
||||
// See JDK-8349716
|
||||
returnValue.set(Internal.INSTANCE);
|
||||
assertThrows(IllegalAccessError.class, instance::call);
|
||||
}
|
||||
}
|
||||
65
test/jdk/java/lang/reflect/Proxy/NullClassLoader.java
Normal file
65
test/jdk/java/lang/reflect/Proxy/NullClassLoader.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 4227192
|
||||
* @summary This test verifies that a proxy class can be created with
|
||||
* (and defined in) the null class loader.
|
||||
* @author Peter Jones
|
||||
*
|
||||
* @build NullClassLoader
|
||||
* @run main NullClassLoader
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Observer;
|
||||
|
||||
public class NullClassLoader {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.err.println(
|
||||
"\nTest creating proxy class with the null class loader.\n");
|
||||
|
||||
try {
|
||||
ClassLoader ld = null;
|
||||
Class p = Proxy.getProxyClass(ld, new Class[] { Runnable.class, Observer.class });
|
||||
System.err.println("proxy class: " + p);
|
||||
|
||||
ClassLoader loader = p.getClassLoader();
|
||||
System.err.println("proxy class's class loader: " + loader);
|
||||
|
||||
if (loader != null) {
|
||||
throw new RuntimeException(
|
||||
"proxy class not defined in the null class loader");
|
||||
}
|
||||
|
||||
System.err.println("\nTEST PASSED");
|
||||
|
||||
} catch (Throwable e) {
|
||||
System.err.println("\nTEST FAILED:");
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("TEST FAILED: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
190
test/jdk/java/lang/reflect/Proxy/ProtectedObjectMethodsTest.java
Normal file
190
test/jdk/java/lang/reflect/Proxy/ProtectedObjectMethodsTest.java
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8370839
|
||||
* @summary Behavior of protected methods in java.lang.Object
|
||||
* @modules java.base/java.lang:+open
|
||||
* @run junit ProtectedObjectMethodsTest
|
||||
*/
|
||||
public class ProtectedObjectMethodsTest {
|
||||
|
||||
static final MethodHandle OBJECT_CLONE;
|
||||
static final MethodHandle OBJECT_FINALIZE;
|
||||
|
||||
static {
|
||||
try {
|
||||
var lookup = MethodHandles.privateLookupIn(Object.class, MethodHandles.lookup());
|
||||
OBJECT_CLONE = lookup.findVirtual(Object.class, "clone", MethodType.methodType(Object.class));
|
||||
OBJECT_FINALIZE = lookup.findVirtual(Object.class, "finalize", MethodType.methodType(void.class));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new ExceptionInInitializerError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
interface FakeClone {
|
||||
// This method is not related to Object::clone in the JVM, but most
|
||||
// implementations in the Java Language override Object::clone as
|
||||
// covariant overrides
|
||||
FakeClone clone();
|
||||
}
|
||||
|
||||
interface TrueClone {
|
||||
// This method is identical to Object::clone in the JVM, that calls
|
||||
// to Object::clone can always call an implementation of this method
|
||||
// if it exists
|
||||
Object clone();
|
||||
}
|
||||
|
||||
interface PrimitiveClone {
|
||||
// This method is not related to Object::clone in the JVM, but it can't
|
||||
// be implemented in the Java Language unless using a lambda expression,
|
||||
// due to the Java language covariant override restrictions.
|
||||
int clone();
|
||||
}
|
||||
|
||||
// Does not duplicate with Object::clone so it is not proxied
|
||||
@Test
|
||||
void testDistinctClone() throws Throwable {
|
||||
{
|
||||
// This proxy declares FakeClone clone(); which cannot be
|
||||
// invoked through Object::clone.
|
||||
var fake = (FakeClone) Proxy.newProxyInstance(FakeClone.class.getClassLoader(), new Class[] { FakeClone.class }, (p, _, _) -> p);
|
||||
assertSame(fake, fake.clone());
|
||||
// Verify the default Object::clone behavior (this is not Cloneable)
|
||||
assertThrows(CloneNotSupportedException.class, () -> {
|
||||
var _ = (Object) OBJECT_CLONE.invoke((Object) fake);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// This proxy declares FakeClone clone(); which cannot be
|
||||
// invoked through Object::clone.
|
||||
var fake = (FakeClone) Proxy.newProxyInstance(FakeClone.class.getClassLoader(), new Class[] { FakeClone.class, Cloneable.class }, (p, _, _) -> p);
|
||||
assertSame(fake, fake.clone());
|
||||
// Verify the default Object::clone behavior (this is Cloneable)
|
||||
var fakeClone = (Object) OBJECT_CLONE.invoke((Object) fake);
|
||||
assertNotSame(fake, fakeClone);
|
||||
assertSame(fake.getClass(), fakeClone.getClass());
|
||||
assertSame(fakeClone, ((FakeClone) fakeClone).clone());
|
||||
}
|
||||
|
||||
{
|
||||
// This proxy declares int clone(); which cannot be
|
||||
// invoked through Object::clone.
|
||||
var instance = (PrimitiveClone) Proxy.newProxyInstance(PrimitiveClone.class.getClassLoader(), new Class[] { PrimitiveClone.class }, (_, _, _) -> 42);
|
||||
assertEquals(42, instance.clone());
|
||||
// Verify the default Object::clone behavior (this is not Cloneable)
|
||||
assertThrows(CloneNotSupportedException.class, () -> {
|
||||
var _ = (Object) OBJECT_CLONE.invoke((Object) instance);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// This proxy declares int clone(); which cannot be
|
||||
// invoked through Object::clone
|
||||
var instance = (PrimitiveClone) Proxy.newProxyInstance(PrimitiveClone.class.getClassLoader(), new Class[] { PrimitiveClone.class, Cloneable.class }, (_, _, _) -> 76);
|
||||
assertEquals(76, instance.clone());
|
||||
// Verify the default Object::clone behavior (this is Cloneable)
|
||||
var clone = (Object) OBJECT_CLONE.invoke((Object) instance);
|
||||
assertNotSame(instance, clone);
|
||||
assertSame(instance.getClass(), clone.getClass());
|
||||
assertEquals(76, ((PrimitiveClone) clone).clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Duplicates with Object::clone so it is proxied
|
||||
@Test
|
||||
void testDuplicateClone() throws Throwable {
|
||||
{
|
||||
// This proxy declares Object clone();, which
|
||||
// accidentally overrides Object::clone
|
||||
var instance = (TrueClone) Proxy.newProxyInstance(TrueClone.class.getClassLoader(), new Class[] { TrueClone.class }, (p, _, _) -> p);
|
||||
assertSame(instance, instance.clone());
|
||||
// Verify Object::clone is overridden
|
||||
assertSame(instance, (Object) OBJECT_CLONE.invoke((Object) instance));
|
||||
}
|
||||
|
||||
{
|
||||
// This proxy declares Object clone(); and FakeClone clone();.
|
||||
// They are considered duplicate methods and dispatched equivalently.
|
||||
// Object clone() accidentally overrides Object::clone, so now
|
||||
// FakeClone clone() can be called through Object::clone
|
||||
var instance = Proxy.newProxyInstance(TrueClone.class.getClassLoader(), new Class[] { TrueClone.class, FakeClone.class }, (p, _, _) -> p);
|
||||
assertSame(instance, ((FakeClone) instance).clone());
|
||||
assertSame(instance, ((TrueClone) instance).clone());
|
||||
// Verify Object::clone is overridden
|
||||
assertSame(instance, (Object) OBJECT_CLONE.invoke((Object) instance));
|
||||
}
|
||||
}
|
||||
|
||||
interface FalseFinalize {
|
||||
// This method is not related to Object::finalize in the JVM, but it can't
|
||||
// be implemented in the Java Language unless using a lambda expression,
|
||||
// due to the Java language covariant override restrictions.
|
||||
int finalize();
|
||||
}
|
||||
|
||||
interface TrueFinalize {
|
||||
// This method is identical to Object::finalize in the JVM, that calls
|
||||
// to Object::finalize can always call an implementation of this method
|
||||
// if it exists
|
||||
void finalize();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDistinctFinalize() throws Throwable {
|
||||
AtomicInteger invokeCount = new AtomicInteger();
|
||||
// This proxy declares int finalize(), which cannot be
|
||||
// invoked through Object::finalize.
|
||||
var instance = Proxy.newProxyInstance(FalseFinalize.class.getClassLoader(), new Class[] { FalseFinalize.class }, (_, _, _) -> invokeCount.incrementAndGet());
|
||||
// Verify the default Object::finalize behavior
|
||||
OBJECT_FINALIZE.invoke(instance);
|
||||
assertEquals(0, invokeCount.get());
|
||||
assertEquals(1, ((FalseFinalize) instance).finalize());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDuplicateFinalize() throws Throwable {
|
||||
AtomicInteger invokeCount = new AtomicInteger();
|
||||
// This proxy declares void finalize(), which can be
|
||||
// invoked through Object::finalize.
|
||||
var instance = Proxy.newProxyInstance(TrueFinalize.class.getClassLoader(), new Class[] { TrueFinalize.class }, (_, _, _) -> invokeCount.incrementAndGet());
|
||||
// Verify the overridden Object::finalize behavior
|
||||
OBJECT_FINALIZE.invoke(instance);
|
||||
assertEquals(1, invokeCount.get());
|
||||
((TrueFinalize) instance).finalize();
|
||||
assertEquals(2, invokeCount.get());
|
||||
}
|
||||
}
|
||||
70
test/jdk/java/lang/reflect/Proxy/ProxyClashTest.java
Normal file
70
test/jdk/java/lang/reflect/Proxy/ProxyClashTest.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 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 8188240
|
||||
* @summary This is a test to ensure that proxies do not try to intercept interface static methods.
|
||||
*
|
||||
* @build ProxyClashTest
|
||||
* @run main ProxyClashTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Observer;
|
||||
|
||||
public class ProxyClashTest {
|
||||
|
||||
public interface ClashWithRunnable {
|
||||
static int run() { return 123; }
|
||||
|
||||
static void foo() {}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.err.println(
|
||||
"\nDynamic proxy API static method clash test\n");
|
||||
|
||||
Class<?>[] interfaces =
|
||||
new Class<?>[] { ClashWithRunnable.class, Runnable.class, Observer.class };
|
||||
|
||||
ClassLoader loader = ProxyClashTest.class.getClassLoader();
|
||||
|
||||
/*
|
||||
* Generate a proxy class.
|
||||
*/
|
||||
Class<?> proxyClass = Proxy.getProxyClass(loader, interfaces);
|
||||
System.err.println("+ generated proxy class: " + proxyClass);
|
||||
|
||||
for (Method method : proxyClass.getDeclaredMethods()) {
|
||||
if (method.getName().equals("run") && method.getReturnType() == int.class) {
|
||||
throw new RuntimeException("proxy intercept a static method");
|
||||
}
|
||||
if (method.getName().equals("foo")) {
|
||||
throw new RuntimeException("proxy intercept a static method");
|
||||
}
|
||||
}
|
||||
|
||||
System.err.println("\nTEST PASSED");
|
||||
}
|
||||
}
|
||||
114
test/jdk/java/lang/reflect/Proxy/ProxyClassAccessTest.java
Normal file
114
test/jdk/java/lang/reflect/Proxy/ProxyClassAccessTest.java
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2026, 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.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
import static jdk.test.lib.process.ProcessTools.executeTestJava;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @modules jdk.compiler
|
||||
* @build ProxyClassAccessTest q.NP
|
||||
* jdk.test.lib.compiler.CompilerUtils
|
||||
* @run junit ProxyClassAccessTest
|
||||
* @summary Driver for testing proxy class doesn't have access to
|
||||
* types referenced by proxy interfaces
|
||||
*/
|
||||
|
||||
public class ProxyClassAccessTest {
|
||||
|
||||
private static final String TEST_SRC = System.getProperty("test.src");
|
||||
private static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||
|
||||
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
|
||||
private static final Path MODS_DIR = Paths.get("mods");
|
||||
|
||||
// the names of the modules in this test
|
||||
private static List<String> modules = Arrays.asList("m1", "m2", "m3", "test");
|
||||
|
||||
/**
|
||||
* Compiles all modules used by the test
|
||||
*/
|
||||
@BeforeAll
|
||||
public static void compileAll() throws Exception {
|
||||
for (String mn : modules) {
|
||||
Path msrc = SRC_DIR.resolve(mn);
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the modular test
|
||||
*/
|
||||
@Test
|
||||
public void runTest() throws Exception {
|
||||
int exitValue = executeTestJava("--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.ProxyClassAccess")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.getExitValue();
|
||||
|
||||
assertEquals(0, exitValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test unnamed module has no access to other proxy interface
|
||||
*/
|
||||
@Test
|
||||
public void testNoReadAccess() throws Throwable {
|
||||
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
|
||||
ModuleLayer bootLayer = ModuleLayer.boot();
|
||||
Configuration cf = bootLayer
|
||||
.configuration()
|
||||
.resolveAndBind(ModuleFinder.of(), finder, modules);
|
||||
ClassLoader parentLoader = this.getClass().getClassLoader();
|
||||
ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, parentLoader);
|
||||
|
||||
ClassLoader loader = layer.findLoader("m1");
|
||||
Class<?>[] interfaces = new Class<?>[] {
|
||||
Class.forName("p.one.I", false, loader),
|
||||
Class.forName("q.NP", false, loader) // non-public interface in unnamed module
|
||||
};
|
||||
checkIAE(loader, interfaces);
|
||||
}
|
||||
|
||||
private void checkIAE(ClassLoader loader, Class<?>[] interfaces) throws Throwable {
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(loader, interfaces));
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.newProxyInstance(loader, interfaces,
|
||||
(proxy, m, params) -> { throw new RuntimeException(m.toString()); }));
|
||||
}
|
||||
|
||||
}
|
||||
568
test/jdk/java/lang/reflect/Proxy/ProxyGeneratorCombo.java
Normal file
568
test/jdk/java/lang/reflect/Proxy/ProxyGeneratorCombo.java
Normal file
|
|
@ -0,0 +1,568 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 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
|
||||
* @summary Proxy Generator Combo tests
|
||||
* @library /test/langtools/tools/javac/lib .
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.code
|
||||
* jdk.compiler/com.sun.tools.javac.comp
|
||||
* jdk.compiler/com.sun.tools.javac.file
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
* jdk.compiler/com.sun.tools.javac.tree
|
||||
* jdk.compiler/com.sun.tools.javac.util
|
||||
* @build combo.ComboTestHelper
|
||||
* @run main/othervm ProxyGeneratorCombo
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import combo.ComboInstance;
|
||||
import combo.ComboParameter;
|
||||
import combo.ComboTask.Result;
|
||||
import combo.ComboTestHelper;
|
||||
|
||||
public class ProxyGeneratorCombo extends ComboInstance<ProxyGeneratorCombo> {
|
||||
|
||||
// The unique number to qualify interface names, unique across multiple runs
|
||||
private static int uniqueId = 0;
|
||||
|
||||
/**
|
||||
* Class Access kinds.
|
||||
*/
|
||||
enum ClassAccessKind implements ComboParameter {
|
||||
PUBLIC("public"),
|
||||
PACKAGE(""),
|
||||
;
|
||||
|
||||
String classAccessTemplate;
|
||||
|
||||
ClassAccessKind(String classAccessTemplate) {
|
||||
this.classAccessTemplate = classAccessTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String expand(String optParameter) {
|
||||
return classAccessTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signatures of methods to be tested.
|
||||
*/
|
||||
enum MethodsKind implements ComboParameter {
|
||||
NONE(""),
|
||||
ZERO("#{METHODACCESS} void zero() #{EXCEPTION};"),
|
||||
ONE("#{METHODACCESS} void one(#{ARG[0]} a) #{EXCEPTION};"),
|
||||
TWO("#{METHODACCESS} void one(#{ARG[0]} b);\n" +
|
||||
"#{METHODACCESS} void two(#{ARG[0]} a, #{ARG[1]} b);"),
|
||||
THREE("#{METHODACCESS} void one(#{ARG[0]} a);\n" +
|
||||
"#{METHODACCESS} void two(#{ARG[0]} a, #{ARG[1]} b);\n" +
|
||||
"#{METHODACCESS} void three(#{ARG[0]} a, #{ARG[1]} b, #{ARG[0]} c);");
|
||||
|
||||
String methodsKindTemplate;
|
||||
|
||||
MethodsKind(String methodsKindTemplate) {
|
||||
this.methodsKindTemplate = methodsKindTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String expand(String optParameter) {
|
||||
return methodsKindTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of arguments to insert in method signatures
|
||||
*/
|
||||
enum ArgumentKind implements ComboParameter {
|
||||
BOOLEAN("boolean"),
|
||||
BYTE("byte"),
|
||||
CHAR("char"),
|
||||
SHORT("short"),
|
||||
INT("int"),
|
||||
LONG("long"),
|
||||
FLOAT("float"),
|
||||
DOUBLE("double"),
|
||||
STRING("String");
|
||||
|
||||
String argumentsKindTemplate;
|
||||
|
||||
ArgumentKind(String argumentsKindTemplate) {
|
||||
this.argumentsKindTemplate = argumentsKindTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String expand(String optParameter) {
|
||||
return argumentsKindTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptions to be added to zero and one methods.
|
||||
*/
|
||||
enum ExceptionKind implements ComboParameter {
|
||||
NONE(null),
|
||||
EXCEPTION(java.lang.Exception.class),
|
||||
RUNTIME_EXCEPTION(java.lang.RuntimeException.class),
|
||||
ILLEGAL_ARGUMENT_EXCEPTION(java.lang.IllegalArgumentException.class),
|
||||
IOEXCEPTION(java.io.IOException.class),
|
||||
/**
|
||||
* Used only for throw testing, is empty for throws clause in the source,
|
||||
*/
|
||||
UNDECLARED_EXCEPTION(Exception1.class),
|
||||
;
|
||||
|
||||
Class<? extends Throwable> exceptionKindClass;
|
||||
|
||||
ExceptionKind(Class<? extends Throwable> exceptionKindClass) {
|
||||
this.exceptionKindClass = exceptionKindClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String expand(String optParameter) {
|
||||
return exceptionKindClass == null || exceptionKindClass == Exception1.class
|
||||
? "" : "throws " + exceptionKindClass.getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra interfaces to be added.
|
||||
*/
|
||||
enum MultiInterfacesKind implements ComboParameter {
|
||||
NONE(new Class<?>[0]),
|
||||
INTERFACE_WITH_EXCEPTION(new Class<?>[] {InterfaceWithException.class}),
|
||||
;
|
||||
|
||||
Class<?>[] multiInterfaceClasses;
|
||||
|
||||
MultiInterfacesKind(Class<?>[] multiInterfaceClasses) {
|
||||
this.multiInterfaceClasses = multiInterfaceClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
// Not used for expansion only execution
|
||||
public String expand(String optParameter) {
|
||||
throw new RuntimeException("NYI");
|
||||
}
|
||||
|
||||
Class<?>[] classes() {
|
||||
return multiInterfaceClasses;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ++uniqueId;
|
||||
}
|
||||
|
||||
protected void fail(String msg, Throwable thrown) {
|
||||
super.fail(msg);
|
||||
thrown.printStackTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interface with a "one(int)" method.
|
||||
*/
|
||||
interface InterfaceWithException {
|
||||
// The signature must match the ONE MethodsKind above
|
||||
void one(int a) throws RuntimeException, IOException;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main to generate combinations and run the tests.
|
||||
* @param args unused
|
||||
* @throws Exception In case of failure
|
||||
*/
|
||||
public static void main(String... args) throws Exception {
|
||||
|
||||
// Test variations of access declarations
|
||||
new ComboTestHelper<ProxyGeneratorCombo>()
|
||||
.withDimension("CLASSACCESS", ClassAccessKind.values())
|
||||
.withDimension("METHODACCESS", new ClassAccessKind[]{ClassAccessKind.PUBLIC})
|
||||
.withDimension("METHODS", ProxyGeneratorCombo::saveMethod,
|
||||
new MethodsKind[] {MethodsKind.NONE, MethodsKind.ZERO, MethodsKind.ONE})
|
||||
.withDimension("ARG[0]", new ArgumentKind[] {ArgumentKind.INT})
|
||||
.withDimension("EXCEPTION", ProxyGeneratorCombo::saveException,
|
||||
new ExceptionKind[]{ExceptionKind.NONE})
|
||||
.run(ProxyGeneratorCombo::new);
|
||||
|
||||
// Test variations of argument types
|
||||
new ComboTestHelper<ProxyGeneratorCombo>()
|
||||
.withDimension("CLASSACCESS", new ClassAccessKind[]{ClassAccessKind.PUBLIC})
|
||||
.withDimension("METHODACCESS", new ClassAccessKind[]{ClassAccessKind.PUBLIC})
|
||||
.withDimension("METHODS", ProxyGeneratorCombo::saveMethod,
|
||||
MethodsKind.values())
|
||||
.withArrayDimension("ARG", ProxyGeneratorCombo::saveArg, 2,
|
||||
ArgumentKind.values())
|
||||
.withDimension("EXCEPTION", ProxyGeneratorCombo::saveException,
|
||||
new ExceptionKind[]{ExceptionKind.NONE})
|
||||
.withFilter(ProxyGeneratorCombo::filter)
|
||||
.run(ProxyGeneratorCombo::new);
|
||||
|
||||
// Test for conflicts in Exceptions on methods with the same signatures
|
||||
new ComboTestHelper<ProxyGeneratorCombo>()
|
||||
.withDimension("CLASSACCESS", new ClassAccessKind[]{ClassAccessKind.PUBLIC})
|
||||
.withDimension("METHODACCESS", new ClassAccessKind[]{ClassAccessKind.PUBLIC})
|
||||
.withDimension("METHODS", ProxyGeneratorCombo::saveMethod, new MethodsKind[] {
|
||||
MethodsKind.ZERO})
|
||||
.withDimension("EXCEPTION", ProxyGeneratorCombo::saveException,
|
||||
ExceptionKind.values())
|
||||
.withDimension("MULTI_INTERFACES", ProxyGeneratorCombo::saveInterface,
|
||||
new MultiInterfacesKind[] {MultiInterfacesKind.NONE})
|
||||
.run(ProxyGeneratorCombo::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic template.
|
||||
*/
|
||||
String template = "#{CLASSACCESS} interface #{TESTNAME} {\n" +
|
||||
"#{METHODS}" +
|
||||
"}";
|
||||
|
||||
// Saved values of Combo values
|
||||
private MultiInterfacesKind currInterface = MultiInterfacesKind.NONE;
|
||||
private MethodsKind currMethod = MethodsKind.NONE;
|
||||
private ExceptionKind currException = ExceptionKind.NONE;
|
||||
private ArgumentKind[] currArgs = new ArgumentKind[0];
|
||||
|
||||
void saveInterface(ComboParameter s) {
|
||||
currInterface = (MultiInterfacesKind)s;
|
||||
}
|
||||
|
||||
void saveMethod(ComboParameter s) {
|
||||
currMethod = (MethodsKind)s;
|
||||
}
|
||||
|
||||
void saveException(ComboParameter s) {
|
||||
currException = (ExceptionKind)s;
|
||||
}
|
||||
|
||||
void saveArg(ComboParameter s, int index) {
|
||||
if (index >= currArgs.length) {
|
||||
currArgs = Arrays.copyOf(currArgs, index + 1);
|
||||
}
|
||||
currArgs[index] = (ArgumentKind)s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out needless tests (mostly with more variations of arguments than needed).
|
||||
* @return true to run the test, false if not
|
||||
*/
|
||||
boolean filter() {
|
||||
if ((currMethod == MethodsKind.NONE || currMethod == MethodsKind.ZERO) &&
|
||||
currArgs.length >= 2) {
|
||||
return currArgs[0] == ArgumentKind.INT &&
|
||||
currArgs[1] == ArgumentKind.INT;
|
||||
}
|
||||
if (currMethod == MethodsKind.ONE &&
|
||||
currArgs.length >= 2 ) {
|
||||
return currArgs[0] == currArgs[1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the source file and compile.
|
||||
* Generate a proxy for the interface and test the resulting Proxy
|
||||
* for the methods, exceptions and handling of a thrown exception
|
||||
* @throws IOException catch all IOException
|
||||
*/
|
||||
@Override
|
||||
public void doWork() throws IOException {
|
||||
String cp = System.getProperty("test.classes");
|
||||
String ifaceName = "Interface_" + this.id();
|
||||
newCompilationTask()
|
||||
.withSourceFromTemplate(ifaceName, template.replace("#{TESTNAME}", ifaceName))
|
||||
.withOption("-d")
|
||||
.withOption(cp)
|
||||
.generate(this::checkCompile);
|
||||
try {
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
Class<?> tc = Class.forName(ifaceName);
|
||||
InvocationHandler handler =
|
||||
new ProxyHandler(currException.exceptionKindClass);
|
||||
|
||||
// Construct array of interfaces for the proxy
|
||||
Class<?>[] interfaces = new Class<?>[currInterface.classes().length + 1];
|
||||
interfaces[0] = tc;
|
||||
System.arraycopy(currInterface.classes(), 0,
|
||||
interfaces, 1,
|
||||
currInterface.classes().length);
|
||||
|
||||
Object proxy = Proxy.newProxyInstance(loader, interfaces, handler);
|
||||
if (!Proxy.isProxyClass(proxy.getClass())) {
|
||||
fail("generated proxy is not a proxy class");
|
||||
return;
|
||||
}
|
||||
for (Class<?> i : interfaces) {
|
||||
if (!i.isAssignableFrom(proxy.getClass())) {
|
||||
fail("proxy is not assignable to " + i.getName());
|
||||
}
|
||||
}
|
||||
try {
|
||||
String s = proxy.toString();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
fail("proxy.toString() threw an exception");
|
||||
}
|
||||
|
||||
checkDeclaredProxyExceptions(proxy, interfaces);
|
||||
|
||||
if (currMethod == MethodsKind.ZERO && currException != ExceptionKind.NONE) {
|
||||
checkThrowsException(proxy, interfaces);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("doWork unexpected", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the exceptions declared on the proxy match the declarations for
|
||||
* exceptions from the interfaces.
|
||||
*
|
||||
* @param proxy a proxy object
|
||||
* @param interfaces the interfaces that defined it
|
||||
*/
|
||||
void checkDeclaredProxyExceptions(Object proxy, Class<?>[] interfaces) {
|
||||
var allMethods = allMethods(Arrays.asList(interfaces));
|
||||
Method[] methods = proxy.getClass().getDeclaredMethods();
|
||||
for (Method m : methods) {
|
||||
String sig = toShortSignature(m);
|
||||
var imethods = allMethods.get(sig);
|
||||
if (imethods != null) {
|
||||
var expectedEx = Set.copyOf(Arrays.asList(m.getExceptionTypes()));
|
||||
var exs = Set.copyOf(extractExceptions(imethods));
|
||||
if (!expectedEx.equals(exs)) {
|
||||
System.out.printf("mismatch on exceptions for method %s:%nExpected: " +
|
||||
"%s%nActual: %s%n",
|
||||
sig, expectedEx, exs);
|
||||
fail("Exceptions declared on proxy don't match interface methods");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkThrowsException(Object proxy, Class<?>[] interfaces) {
|
||||
ProxyHandler ph = (ProxyHandler)(Proxy.getInvocationHandler(proxy));
|
||||
try {
|
||||
Method m = proxy.getClass().getDeclaredMethod("zero");
|
||||
m.invoke(proxy);
|
||||
fail("Missing exception: " + ph.exceptionClass);
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
System.out.printf("No method 'zero()' to test exceptions with%n");
|
||||
for (var cl : interfaces) {
|
||||
System.out.printf(" i/f %s: %s%n", cl, Arrays.toString(cl.getMethods()));
|
||||
}
|
||||
Method[] methods = proxy.getClass().getMethods();
|
||||
System.out.printf(" Proxy methods: %s%n", Arrays.toString(methods));
|
||||
fail("No such method test bug", nsme);
|
||||
} catch (InvocationTargetException actual) {
|
||||
ph.checkThrownException(actual.getTargetException());
|
||||
} catch (IllegalAccessException iae) {
|
||||
fail("IllegalAccessException", iae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptions known to be supported by all methods with the same signature.
|
||||
* @return a list of universal exception types
|
||||
*/
|
||||
private static List<Class<?>> extractExceptions(List<Method> methods) {
|
||||
// for all methods with the same signature
|
||||
// start with the exceptions from the first method
|
||||
// while there are any exceptions remaining
|
||||
// look at the next method
|
||||
List<Class<?>> exceptions = null;
|
||||
for (Method m : methods) {
|
||||
var e = m.getExceptionTypes();
|
||||
if (e.length == 0)
|
||||
return emptyClassList();
|
||||
List<Class<?>> elist = Arrays.asList(e);
|
||||
if (exceptions == null) {
|
||||
exceptions = elist; // initialize to first method exceptions
|
||||
} else {
|
||||
// for each exception
|
||||
// if it is compatible (both ways) with any of the existing exceptions continue
|
||||
// else remove the current exception
|
||||
var okExceptions = new HashSet<Class<?>>();
|
||||
for (int j = 0; j < exceptions.size(); j++) {
|
||||
var ex = exceptions.get(j);
|
||||
for (int i = 0; i < elist.size();i++) {
|
||||
var ci = elist.get(i);
|
||||
|
||||
if (ci.isAssignableFrom(ex)) {
|
||||
okExceptions.add(ex);
|
||||
}
|
||||
if (ex.isAssignableFrom(ci)) {
|
||||
okExceptions.add(ci);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exceptions.isEmpty()) {
|
||||
// The empty set terminates the search for a common set of exceptions
|
||||
return emptyClassList();
|
||||
}
|
||||
// Use the new set for the next iteration
|
||||
exceptions = List.copyOf(okExceptions);
|
||||
}
|
||||
}
|
||||
return (exceptions == null) ? emptyClassList() : exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* An empty correctly typed list of classes.
|
||||
* @return An empty typed list of classes
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Class<?>> emptyClassList() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate all of the unique methods.
|
||||
*
|
||||
* @param interfaces a list of interfaces
|
||||
* @return a map from signature to List of methods, unique by signature
|
||||
*/
|
||||
private static Map<String, List<Method>> allMethods(List<Class<?>> interfaces) {
|
||||
Map<String, List<Method>> methods = new HashMap<>();
|
||||
for (Class<?> c : interfaces) {
|
||||
for (Method m : c.getMethods()) {
|
||||
if (!Modifier.isStatic(m.getModifiers())) {
|
||||
String sig = toShortSignature(m);
|
||||
methods.computeIfAbsent(sig, s -> new ArrayList<Method>())
|
||||
.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* The signature of a method without the return type.
|
||||
* @param m a Method
|
||||
* @return the signature with method name and parameters
|
||||
*/
|
||||
static String toShortSignature(Method m) {
|
||||
StringJoiner sj = new StringJoiner(",", m.getName() + "(", ")");
|
||||
for (Class<?> parameterType : m.getParameterTypes()) {
|
||||
sj.add(parameterType.getTypeName());
|
||||
}
|
||||
return sj.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Report any compilation errors.
|
||||
* @param res the result
|
||||
*/
|
||||
void checkCompile(Result<?> res) {
|
||||
if (res.hasErrors()) {
|
||||
fail("invalid diagnostics for source:\n" +
|
||||
res.compilationInfo() +
|
||||
"\nFound error: " + res.hasErrors());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Handler for the proxy includes the method to invoke the proxy
|
||||
* and the expected exception, if any.
|
||||
*/
|
||||
class ProxyHandler implements InvocationHandler {
|
||||
|
||||
private final Class<? extends Throwable> exceptionClass;
|
||||
|
||||
ProxyHandler(Class<? extends Throwable> throwable) {
|
||||
this.exceptionClass = throwable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a method on the proxy or return a value.
|
||||
* @param proxy the proxy instance that the method was invoked on
|
||||
* @param method a method
|
||||
* @param args some args
|
||||
* @return
|
||||
* @throws Throwable a throwable
|
||||
*/
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getName().equals("toString")) {
|
||||
return "Proxy" + System.identityHashCode(proxy);
|
||||
}
|
||||
if (method.getName().equals("zero")) {
|
||||
if (exceptionClass != null) {
|
||||
throw exceptionClass.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
}
|
||||
return "meth: " + method.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the expected exception was thrown.
|
||||
* Special case is handled for Exception1 which does not appear in the
|
||||
* throws clause of the method so UndeclaredThrowableException is expected.
|
||||
*/
|
||||
void checkThrownException(Throwable thrown) {
|
||||
if (exceptionClass == Exception1.class &&
|
||||
thrown instanceof UndeclaredThrowableException &&
|
||||
((UndeclaredThrowableException)thrown).getUndeclaredThrowable() instanceof Exception1) {
|
||||
// Exception1 caused UndeclaredThrowableException
|
||||
return;
|
||||
} else if (exceptionClass == Exception1.class) {
|
||||
fail("UndeclaredThrowableException", thrown);
|
||||
}
|
||||
|
||||
if (exceptionClass != null &&
|
||||
!exceptionClass.equals(thrown.getClass())) {
|
||||
throw new RuntimeException("Wrong exception thrown: expected: " + exceptionClass +
|
||||
", actual: " + thrown.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception to be thrown as a test of InvocationTarget.
|
||||
*/
|
||||
static class Exception1 extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
Exception1() {}
|
||||
}
|
||||
}
|
||||
175
test/jdk/java/lang/reflect/Proxy/ProxyLayerTest.java
Normal file
175
test/jdk/java/lang/reflect/Proxy/ProxyLayerTest.java
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2026, 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.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
import static jdk.test.lib.process.ProcessTools.executeTestJava;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @modules jdk.compiler
|
||||
* @build ProxyTest jdk.test.lib.process.ProcessTools
|
||||
* jdk.test.lib.compiler.CompilerUtils
|
||||
* @run junit ProxyLayerTest
|
||||
* @summary Test proxies to implement interfaces in a layer
|
||||
*/
|
||||
|
||||
public class ProxyLayerTest {
|
||||
|
||||
private static final String TEST_SRC = System.getProperty("test.src");
|
||||
private static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||
|
||||
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
|
||||
private static final Path MODS_DIR = Paths.get("mods");
|
||||
private static final Path CPATH_DIR = Paths.get(TEST_CLASSES);
|
||||
|
||||
// the names of the modules in this test
|
||||
private static String[] modules = new String[] {"m1", "m2", "m3"};
|
||||
|
||||
|
||||
/**
|
||||
* Compiles all modules used by the test
|
||||
*/
|
||||
@BeforeAll
|
||||
public static void compileAll() throws Exception {
|
||||
for (String mn : modules) {
|
||||
Path msrc = SRC_DIR.resolve(mn);
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test proxy implementing interfaces in a layer defined in
|
||||
* an unnamed module
|
||||
*/
|
||||
@Test
|
||||
public void testProxyInUnnamed() throws Exception {
|
||||
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
|
||||
ModuleLayer bootLayer = ModuleLayer.boot();
|
||||
Configuration cf = bootLayer
|
||||
.configuration()
|
||||
.resolveAndBind(ModuleFinder.of(), finder, Arrays.asList(modules));
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
|
||||
|
||||
ClassLoader loader = layer.findLoader("m1");
|
||||
|
||||
assertTrue(layer.findModule("m1").isPresent());
|
||||
assertTrue(layer.findModule("m2").isPresent());
|
||||
assertTrue(layer.findModule("m3").isPresent());
|
||||
|
||||
Class<?>[] interfaces = new Class<?>[] {
|
||||
Class.forName("p.one.I", false, loader),
|
||||
Class.forName("p.two.A", false, loader),
|
||||
Class.forName("p.three.P", false, loader),
|
||||
};
|
||||
Object o = Proxy.newProxyInstance(loader, interfaces, handler);
|
||||
|
||||
Class<?> proxyClass = o.getClass();
|
||||
Package pkg = proxyClass.getPackage();
|
||||
assertTrue(proxyClass.getModule().isNamed());
|
||||
assertTrue(pkg.isSealed());
|
||||
assertTrue(proxyClass.getModule().isExported(pkg.getName()));
|
||||
assertNull(proxyClass.getModule().getLayer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test proxy implementing interfaces in a Layer and defined in a
|
||||
* dynamic module
|
||||
*/
|
||||
@Test
|
||||
public void testProxyInDynamicModule() throws Exception {
|
||||
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
|
||||
ModuleLayer bootLayer = ModuleLayer.boot();
|
||||
Configuration cf = bootLayer
|
||||
.configuration()
|
||||
.resolveAndBind(ModuleFinder.of(), finder, Arrays.asList(modules));
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
|
||||
|
||||
ClassLoader loader = layer.findLoader("m1");
|
||||
|
||||
assertTrue(layer.findModule("m1").isPresent());
|
||||
assertTrue(layer.findModule("m2").isPresent());
|
||||
assertTrue(layer.findModule("m3").isPresent());
|
||||
|
||||
Class<?>[] interfaces = new Class<?>[] {
|
||||
Class.forName("p.one.internal.J", false, loader),
|
||||
};
|
||||
Object o = Proxy.newProxyInstance(loader, interfaces, handler);
|
||||
Class<?> proxyClass = o.getClass();
|
||||
Package pkg = proxyClass.getPackage();
|
||||
assertTrue(proxyClass.getModule().isNamed());
|
||||
assertTrue(pkg.isSealed());
|
||||
assertFalse(proxyClass.getModule().isExported(pkg.getName()));
|
||||
assertNull(proxyClass.getModule().getLayer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test proxy implementing interfaces that the target module has no access
|
||||
*/
|
||||
@Test
|
||||
public void testNoReadAccess() throws Exception {
|
||||
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
|
||||
ModuleLayer bootLayer = ModuleLayer.boot();
|
||||
Configuration cf = bootLayer
|
||||
.configuration()
|
||||
.resolveAndBind(ModuleFinder.of(), finder, Arrays.asList(modules));
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
|
||||
|
||||
ClassLoader loader = layer.findLoader("m1");
|
||||
|
||||
assertTrue(layer.findModule("m1").isPresent());
|
||||
assertTrue(layer.findModule("m2").isPresent());
|
||||
assertTrue(layer.findModule("m3").isPresent());
|
||||
|
||||
Class<?>[] interfaces = new Class<?>[] {
|
||||
Class.forName("p.one.I", false, loader),
|
||||
Class.forName("p.two.B", false, loader) // non-public interface but exported package
|
||||
};
|
||||
checkIAE(loader, interfaces);
|
||||
}
|
||||
|
||||
private void checkIAE(ClassLoader loader, Class<?>[] interfaces) {
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(loader, interfaces));
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.newProxyInstance(loader, interfaces, handler));
|
||||
}
|
||||
|
||||
private final static InvocationHandler handler =
|
||||
(proxy, m, params) -> { throw new RuntimeException(m.toString()); };
|
||||
|
||||
}
|
||||
106
test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java
Normal file
106
test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Basic test of proxy module mapping and the access to Proxy class
|
||||
* @modules java.base/jdk.internal.misc
|
||||
*/
|
||||
|
||||
public class ProxyModuleMapping {
|
||||
public static void main(String... args) throws Exception {
|
||||
ClassLoader ld = ProxyModuleMapping.class.getClassLoader();
|
||||
Module unnamed = ld.getUnnamedModule();
|
||||
new ProxyModuleMapping(Runnable.class).test();
|
||||
|
||||
// unnamed module gets access to jdk.internal.misc package (e.g. via --add-exports)
|
||||
new ProxyModuleMapping(jdk.internal.misc.VM.BufferPool.class).test();
|
||||
|
||||
Class<?> modulePrivateIntf = Class.forName("sun.net.PlatformSocketImpl");
|
||||
new ProxyModuleMapping(modulePrivateIntf).test();
|
||||
}
|
||||
|
||||
final Module target;
|
||||
final ClassLoader loader;
|
||||
final Class<?>[] interfaces;
|
||||
ProxyModuleMapping(Module m, Class<?>... interfaces) {
|
||||
this.target = m;
|
||||
this.loader = m.getClassLoader();
|
||||
this.interfaces = interfaces;
|
||||
}
|
||||
|
||||
ProxyModuleMapping(Class<?>... interfaces) {
|
||||
this.target = null; // expected to be dynamic module
|
||||
this.loader = interfaces[0].getClassLoader(); // same class loader
|
||||
this.interfaces = interfaces;
|
||||
}
|
||||
|
||||
void test() throws Exception {
|
||||
verifyProxyClass();
|
||||
verifyNewProxyInstance();
|
||||
}
|
||||
|
||||
void verifyProxyClass() throws Exception {
|
||||
Class<?> c = Proxy.getProxyClass(loader, interfaces);
|
||||
Module m = c.getModule();
|
||||
if (target != null && m != target) {
|
||||
throw new RuntimeException(c.getModule() + " not expected: " + target);
|
||||
}
|
||||
// expect dynamic module
|
||||
if (target == null && (!m.isNamed() || !m.getName().startsWith("jdk.proxy"))) {
|
||||
throw new RuntimeException("Unexpected:" + m);
|
||||
}
|
||||
|
||||
Module module = c.getModule();
|
||||
try {
|
||||
Constructor<?> cons = c.getConstructor(InvocationHandler.class);
|
||||
cons.newInstance(ih);
|
||||
// the exported package name is same as the module name
|
||||
if (!c.getPackageName().equals(module.getName())) {
|
||||
throw new RuntimeException("expected IAE not thrown");
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
// non-exported package from the dynamic module
|
||||
if (c.getPackageName().equals(module.getName())) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void verifyNewProxyInstance() throws Exception {
|
||||
Object o = Proxy.newProxyInstance(loader, interfaces, ih);
|
||||
Module m = o.getClass().getModule();
|
||||
if (target != null && m != target) {
|
||||
throw new RuntimeException(m + " not expected: " + target);
|
||||
}
|
||||
if (target == null && (!m.isNamed() || !m.getName().startsWith("jdk.proxy"))) {
|
||||
throw new RuntimeException(m + " not expected: dynamic module");
|
||||
}
|
||||
}
|
||||
private final static InvocationHandler ih =
|
||||
(proxy, m, params) -> { System.out.println(m); return null; };
|
||||
}
|
||||
59
test/jdk/java/lang/reflect/Proxy/ProxyNullCheckTest.java
Normal file
59
test/jdk/java/lang/reflect/Proxy/ProxyNullCheckTest.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 8371953
|
||||
* @summary Basic API null checks for Proxy.
|
||||
* @run junit ProxyNullCheckTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ProxyNullCheckTest {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
void nullChecks() throws ReflectiveOperationException {
|
||||
InvocationHandler h = (_, _, _) -> null;
|
||||
// newProxyInstance
|
||||
assertDoesNotThrow(() -> Proxy.newProxyInstance(null, new Class[0], h));
|
||||
assertThrows(NullPointerException.class, () -> Proxy.newProxyInstance(null, null, h));
|
||||
assertThrows(NullPointerException.class, () -> Proxy.newProxyInstance(null, new Class[] { null }, h));
|
||||
assertThrows(NullPointerException.class, () -> Proxy.newProxyInstance(null, new Class[0], null));
|
||||
// getProxyClass
|
||||
assertDoesNotThrow(() -> Proxy.getProxyClass(null, new Class[0]));
|
||||
assertThrows(NullPointerException.class, () -> Proxy.getProxyClass(null, (Class[]) null));
|
||||
assertThrows(NullPointerException.class, () -> Proxy.getProxyClass(null, new Class[] { null }));
|
||||
// isProxyClass
|
||||
assertFalse(Proxy.isProxyClass(Object.class));
|
||||
assertThrows(NullPointerException.class, () -> Proxy.isProxyClass(null));
|
||||
// getInvocationHandler
|
||||
assertThrows(NullPointerException.class, () -> Proxy.getInvocationHandler(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.getInvocationHandler(42));
|
||||
}
|
||||
}
|
||||
100
test/jdk/java/lang/reflect/Proxy/ProxyTest.java
Normal file
100
test/jdk/java/lang/reflect/Proxy/ProxyTest.java
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2026, 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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
import static jdk.test.lib.process.ProcessTools.executeTestJava;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @modules jdk.compiler
|
||||
* @build ProxyTest q.U
|
||||
* jdk.test.lib.compiler.CompilerUtils
|
||||
* @run junit ProxyTest
|
||||
* @summary Driver for testing proxies accessing interfaces in named modules
|
||||
*/
|
||||
|
||||
public class ProxyTest {
|
||||
|
||||
private static final String TEST_SRC = System.getProperty("test.src");
|
||||
private static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||
|
||||
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
|
||||
private static final Path MODS_DIR = Paths.get("mods");
|
||||
private static final Path CPATH_DIR = Paths.get(TEST_CLASSES);
|
||||
|
||||
// the names of the modules in this test
|
||||
private static List<String> modules = Arrays.asList("test", "m1", "m2", "m3");
|
||||
|
||||
|
||||
/**
|
||||
* Compiles all modules used by the test
|
||||
*/
|
||||
@BeforeAll
|
||||
public static void compileAll() throws Exception {
|
||||
for (String mn : modules) {
|
||||
Path msrc = SRC_DIR.resolve(mn);
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the modular test
|
||||
*/
|
||||
@Test
|
||||
public void runTest() throws Exception {
|
||||
int exitValue = executeTestJava("-cp", CPATH_DIR.toString(),
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.Main")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.getExitValue();
|
||||
|
||||
assertEquals(0, exitValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests invocation of default methods in exported and non-exported types
|
||||
* in a named module
|
||||
*/
|
||||
@Test
|
||||
public void runDefaultMethodsTest() throws Exception {
|
||||
int exitValue = executeTestJava("-cp", CPATH_DIR.toString(),
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.DefaultMethods")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.getExitValue();
|
||||
|
||||
assertEquals(0, exitValue);
|
||||
}
|
||||
}
|
||||
70
test/jdk/java/lang/reflect/Proxy/SealedInterfaceTest.java
Normal file
70
test/jdk/java/lang/reflect/Proxy/SealedInterfaceTest.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2026, 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 8269351
|
||||
* @run junit SealedInterfaceTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SealedInterfaceTest {
|
||||
sealed interface Intf permits NonSealedInterface {
|
||||
void m1();
|
||||
}
|
||||
|
||||
non-sealed interface NonSealedInterface extends Intf {
|
||||
void m2();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSealedInterface() {
|
||||
assertThrows(IllegalArgumentException.class, () -> Proxy.newProxyInstance(
|
||||
SealedInterfaceTest.class.getClassLoader(),
|
||||
new Class<?>[]{ Intf.class },
|
||||
new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonSealedInterface() {
|
||||
Proxy.newProxyInstance(SealedInterfaceTest.class.getClassLoader(),
|
||||
new Class<?>[]{ NonSealedInterface.class },
|
||||
new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
114
test/jdk/java/lang/reflect/Proxy/TestVarArgs.java
Normal file
114
test/jdk/java/lang/reflect/Proxy/TestVarArgs.java
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2026, 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 8022795
|
||||
* @run junit TestVarArgs
|
||||
* @summary Verify if a method defined in a proxy interface has ACC_VARARGS set
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class TestVarArgs {
|
||||
interface I {
|
||||
Object call(Object... values);
|
||||
}
|
||||
interface J {
|
||||
Object call(Object[] values);
|
||||
}
|
||||
|
||||
public static Object[][] proxyInterfaces() {
|
||||
return new Object[][] {
|
||||
{ new Class<?>[] { I.class }, true},
|
||||
{ new Class<?>[] { J.class }, false},
|
||||
{ new Class<?>[] { I.class, J.class }, true},
|
||||
{ new Class<?>[] { J.class, I.class }, false},
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("proxyInterfaces")
|
||||
public void testMethod(Class<?>[] proxyInterfaces, boolean isVarArgs) throws Throwable {
|
||||
// check if the first proxy interface with the method named "call" declares var result
|
||||
Method m = proxyInterfaces[0].getMethod("call", Object[].class);
|
||||
assertEquals(isVarArgs, m.isVarArgs());
|
||||
|
||||
// the method in the generated proxy class should match the method
|
||||
// declared in the proxy interface
|
||||
Object proxy = Proxy.newProxyInstance(TestVarArgs.class.getClassLoader(),
|
||||
proxyInterfaces, IH);
|
||||
Class<?> proxyClass = proxy.getClass();
|
||||
assertTrue(Proxy.isProxyClass(proxyClass));
|
||||
Method method = proxyClass.getMethod("call", Object[].class);
|
||||
assertEquals(isVarArgs, method.isVarArgs());
|
||||
|
||||
Object[] params = new Object[] { "foo", "bar", "goo" };
|
||||
Object[] result;
|
||||
|
||||
// test reflection
|
||||
result = (Object[]) method.invoke(proxy, new Object[] {params});
|
||||
assertEquals(params, result);
|
||||
|
||||
// test method handle
|
||||
MethodHandle mh = MethodHandles.lookup().findVirtual(proxyClass, "call",
|
||||
MethodType.methodType(Object.class, Object[].class));
|
||||
assertEquals(isVarArgs, mh.isVarargsCollector());
|
||||
MethodHandle mhVarArity = mh;
|
||||
MethodHandle mhFixedArity = mh;
|
||||
if (isVarArgs) {
|
||||
mhFixedArity = mh.asFixedArity();
|
||||
} else {
|
||||
mhVarArity = mh.asVarargsCollector(Object[].class);
|
||||
}
|
||||
result = (Object[]) mhVarArity.invoke(proxy, "foo", "bar", "goo");
|
||||
assertArrayEquals(params, result);
|
||||
|
||||
result = (Object[]) mhFixedArity.invoke(proxy, params);
|
||||
assertArrayEquals(params, result);
|
||||
|
||||
if (!isVarArgs) {
|
||||
MethodType mt = MethodType.methodType(Object.class, Object.class, String.class, String.class, String.class);
|
||||
mh = mh.asVarargsCollector(Object[].class).asType(mt);
|
||||
}
|
||||
result = (Object[]) mh.invoke(proxy, "foo", "bar", "goo");
|
||||
assertArrayEquals(params, result);
|
||||
}
|
||||
|
||||
private static final InvocationHandler IH = new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return args[0];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
81
test/jdk/java/lang/reflect/Proxy/nonJavaNames/Test.java
Normal file
81
test/jdk/java/lang/reflect/Proxy/nonJavaNames/Test.java
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 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 4978925
|
||||
* @summary This test verifies that java.lang.reflect.Proxy will work
|
||||
* with a proxy interface that contains names that are not valid Java
|
||||
* identifiers but that are legal at runtime as of version 49.0 of the
|
||||
* class file format.
|
||||
* @author Peter Jones
|
||||
*
|
||||
* @build Test
|
||||
* @run main Test
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
public class Test {
|
||||
|
||||
private static final String CLASS_NAME = "Test+Interface";
|
||||
|
||||
/**
|
||||
* class file for empty interface named "Test+Interface"
|
||||
*/
|
||||
private static final byte[] CLASS_FILE = {
|
||||
(byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe,
|
||||
0x00, 0x00, 0x00, 0x31,
|
||||
0x00, 0x07, 0x07, 0x00, 0x05, 0x07, 0x00, 0x06,
|
||||
0x01, 0x00, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63,
|
||||
0x65, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x00, 0x13,
|
||||
0x54, 0x65, 0x73, 0x74, 0x2b, 0x49, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2e, 0x6a,
|
||||
0x61, 0x76, 0x61, 0x01, 0x00, 0x0e, 0x54, 0x65,
|
||||
0x73, 0x74, 0x2b, 0x49, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x66, 0x61, 0x63, 0x65, 0x01, 0x00, 0x10, 0x6a,
|
||||
0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67,
|
||||
0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x06,
|
||||
0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00,
|
||||
0x00, 0x00, 0x02, 0x00, 0x04
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ClassLoader l = new Loader();
|
||||
Class i = Class.forName(CLASS_NAME, false, l);
|
||||
System.out.println(i);
|
||||
Class p = Proxy.getProxyClass(i.getClassLoader(), new Class[] { i });
|
||||
System.out.println(p);
|
||||
}
|
||||
|
||||
private static class Loader extends ClassLoader {
|
||||
Loader() { }
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
if (name.equals(CLASS_NAME)) {
|
||||
return defineClass(name, CLASS_FILE, 0, CLASS_FILE.length);
|
||||
} else {
|
||||
return super.findClass(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2026, 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.lang.reflect.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8159746
|
||||
* @summary Test invoking a default method in a non-public proxy interface
|
||||
* @build p.Foo p.Bar p.ProxyMaker
|
||||
* @run junit DefaultMethodProxy
|
||||
*/
|
||||
public class DefaultMethodProxy {
|
||||
public interface I {
|
||||
default String m() { return "I"; }
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publicInterface() throws ReflectiveOperationException {
|
||||
// create a proxy instance of a public proxy interface should succeed
|
||||
Proxy proxy = (Proxy)Proxy.newProxyInstance(DefaultMethodProxy.class.getClassLoader(),
|
||||
new Class<?>[] { I.class }, IH);
|
||||
|
||||
testDefaultMethod(proxy, "I");
|
||||
|
||||
// can get the invocation handler
|
||||
assertSame(IH, Proxy.getInvocationHandler(proxy));
|
||||
}
|
||||
|
||||
private static Object[][] nonPublicIntfs() throws ClassNotFoundException {
|
||||
Class<?> fooClass = Class.forName("p.Foo");
|
||||
Class<?> barClass = Class.forName("p.Bar");
|
||||
return new Object[][]{
|
||||
new Object[]{new Class<?>[]{ fooClass }, "foo"},
|
||||
new Object[]{new Class<?>[]{ barClass, fooClass }, "bar"},
|
||||
new Object[]{new Class<?>[]{ barClass }, "bar"},
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("nonPublicIntfs")
|
||||
public void hasPackageAccess(Class<?>[] intfs, String expected) throws ReflectiveOperationException {
|
||||
Proxy proxy = (Proxy)Proxy.newProxyInstance(DefaultMethodProxy.class.getClassLoader(), intfs, IH);
|
||||
testDefaultMethod(proxy, expected);
|
||||
|
||||
// proxy instance is created successfully even invocation handler has no access
|
||||
Proxy.newProxyInstance(DefaultMethodProxy.class.getClassLoader(), intfs, IH_NO_ACCESS);
|
||||
}
|
||||
|
||||
// IAE thrown at invocation time
|
||||
@ParameterizedTest
|
||||
@MethodSource("nonPublicIntfs")
|
||||
public void noPackageAccess(Class<?>[] intfs, String ignored) throws Throwable {
|
||||
Proxy proxy = (Proxy)Proxy.newProxyInstance(DefaultMethodProxy.class.getClassLoader(), intfs, IH_NO_ACCESS);
|
||||
InvocationTargetException ite = assertThrows(InvocationTargetException.class, () -> testDefaultMethod(proxy, "dummy"));
|
||||
var ute = assertInstanceOf(UndeclaredThrowableException.class, ite.getCause(), "unwrap the InvocationTargetException");
|
||||
assertInstanceOf(IllegalAccessException.class, ute.getCause(), "unwrap the UndeclaredThrowableException");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify if a default method "m" can be invoked successfully
|
||||
*/
|
||||
static void testDefaultMethod(Proxy proxy, String expected) throws ReflectiveOperationException {
|
||||
Method m = proxy.getClass().getDeclaredMethod("m");
|
||||
m.setAccessible(true);
|
||||
String name = (String) m.invoke(proxy);
|
||||
if (!expected.equals(name)) {
|
||||
throw new RuntimeException("return value: " + name + " expected: " + expected);
|
||||
}
|
||||
}
|
||||
|
||||
// invocation handler with access to the non-public interface in package p
|
||||
private static final InvocationHandler IH = (proxy, method, params) -> {
|
||||
System.out.format("Proxy for %s: invoking %s%n",
|
||||
Arrays.stream(proxy.getClass().getInterfaces())
|
||||
.map(Class::getName)
|
||||
.collect(Collectors.joining(", ")), method.getName());
|
||||
if (method.isDefault()) {
|
||||
return p.ProxyMaker.invoke(proxy, method, params);
|
||||
}
|
||||
throw new UnsupportedOperationException(method.toString());
|
||||
};
|
||||
|
||||
// invocation handler with no access to the non-public interface in package p
|
||||
// expect IllegalAccessException thrown
|
||||
private static final InvocationHandler IH_NO_ACCESS = (proxy, method, params) -> {
|
||||
System.out.format("Proxy for %s: invoking %s%n",
|
||||
Arrays.stream(proxy.getClass().getInterfaces())
|
||||
.map(Class::getName)
|
||||
.collect(Collectors.joining(", ")), method.getName());
|
||||
if (method.isDefault()) {
|
||||
InvocationHandler.invokeDefault(proxy, method, params);
|
||||
}
|
||||
throw new UnsupportedOperationException(method.toString());
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8004260 8189291
|
||||
* @summary Test proxy classes that implement non-public interface
|
||||
*
|
||||
* @build p.Foo
|
||||
* @run main/othervm NonPublicProxyClass
|
||||
*/
|
||||
public class NonPublicProxyClass {
|
||||
|
||||
public interface PublicInterface {
|
||||
void foo();
|
||||
}
|
||||
interface NonPublicInterface {
|
||||
void bar();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
Class<?> zipConstantsClass = Class.forName("java.util.zip.ZipConstants", false, null);
|
||||
Class<?> fooClass = Class.forName("p.Foo");
|
||||
|
||||
NonPublicProxyClass test1 =
|
||||
new NonPublicProxyClass(loader, PublicInterface.class, NonPublicInterface.class);
|
||||
NonPublicProxyClass test2 =
|
||||
new NonPublicProxyClass(loader, fooClass, PublicInterface.class);
|
||||
NonPublicProxyClass test3 =
|
||||
new NonPublicProxyClass(null, zipConstantsClass);
|
||||
|
||||
test1.run();
|
||||
test2.run();
|
||||
test3.run();
|
||||
}
|
||||
|
||||
private final ClassLoader loader;
|
||||
private final Class<?>[] interfaces;
|
||||
private final InvocationHandler handler = newInvocationHandler();
|
||||
private Class<?> proxyClass;
|
||||
public NonPublicProxyClass(ClassLoader loader, Class<?> ... intfs) {
|
||||
this.loader = loader;
|
||||
this.interfaces = intfs;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
proxyClass = Proxy.getProxyClass(loader, interfaces);
|
||||
if (Modifier.isPublic(proxyClass.getModifiers())) {
|
||||
throw new RuntimeException(proxyClass + " must be non-public");
|
||||
}
|
||||
newProxyInstance();
|
||||
newInstanceFromConstructor(proxyClass);
|
||||
}
|
||||
|
||||
private void newProxyInstance() {
|
||||
// expect newProxyInstance to succeed if it's in the same runtime package
|
||||
int i = proxyClass.getName().lastIndexOf('.');
|
||||
String pkg = (i != -1) ? proxyClass.getName().substring(0, i) : "";
|
||||
Proxy.newProxyInstance(loader, interfaces, handler);
|
||||
}
|
||||
|
||||
private void newInstanceFromConstructor(Class<?> proxyClass)
|
||||
throws Exception
|
||||
{
|
||||
// expect newInstance to succeed if it's in the same runtime package
|
||||
boolean isSamePackage = proxyClass.getName().lastIndexOf('.') == -1;
|
||||
try {
|
||||
Constructor cons = proxyClass.getConstructor(InvocationHandler.class);
|
||||
cons.newInstance(newInvocationHandler());
|
||||
if (!isSamePackage) {
|
||||
throw new RuntimeException("ERROR: Constructor.newInstance should not succeed");
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
if (isSamePackage) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static InvocationHandler newInvocationHandler() {
|
||||
return new InvocationHandler() {
|
||||
public Object invoke(Object proxy, Method method, Object[] args)
|
||||
throws Throwable {
|
||||
Class<?>[] intfs = proxy.getClass().getInterfaces();
|
||||
System.out.println("Proxy for " + Arrays.toString(intfs)
|
||||
+ " " + method.getName() + " is being invoked");
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.lang.reflect.*;
|
||||
import java.security.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8004260
|
||||
* @summary Test making a proxy instance that implements a non-public interface
|
||||
* @build p.Foo p.Bar
|
||||
* @run main/othervm SimpleProxy
|
||||
*/
|
||||
public class SimpleProxy {
|
||||
public static void main(String[] args) throws Exception {
|
||||
ClassLoader loader = SimpleProxy.class.getClassLoader();
|
||||
Class<?> fooClass = Class.forName("p.Foo");
|
||||
Class<?> barClass = Class.forName("p.Bar");
|
||||
|
||||
makeProxy(loader, fooClass);
|
||||
}
|
||||
|
||||
private static void makeProxy(ClassLoader loader, Class<?> cls) {
|
||||
Class<?>[] intfs = new Class<?>[] { cls };
|
||||
Proxy.newProxyInstance(loader, intfs, new InvocationHandler() {
|
||||
public Object invoke(Object proxy, Method method, Object[] args)
|
||||
throws Throwable {
|
||||
Class<?>[] intfs = proxy.getClass().getInterfaces();
|
||||
System.out.println("Proxy for " + Arrays.toString(intfs)
|
||||
+ " " + method.getName() + " is being invoked");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
|
||||
package p;
|
||||
interface Bar {
|
||||
default String m() { return "bar"; }
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
|
||||
package p;
|
||||
interface Foo {
|
||||
default String m() { return "foo"; }
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package p;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class ProxyMaker {
|
||||
public static Object invoke(Object proxy, Method method, Object... args)
|
||||
throws Throwable {
|
||||
return InvocationHandler.invokeDefault(proxy, method, args);
|
||||
}
|
||||
|
||||
// get the invocation handler associated with the proxy
|
||||
public static InvocationHandler getInvocationHandler(Object proxy) {
|
||||
return Proxy.getInvocationHandler(proxy);
|
||||
}
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/q/NP.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/q/NP.java
Normal 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.
|
||||
*/
|
||||
|
||||
package q;
|
||||
|
||||
interface NP {
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/q/U.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/q/U.java
Normal 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.
|
||||
*/
|
||||
|
||||
package q;
|
||||
|
||||
public interface U {
|
||||
}
|
||||
26
test/jdk/java/lang/reflect/Proxy/returnTypes/GetArray.java
Normal file
26
test/jdk/java/lang/reflect/Proxy/returnTypes/GetArray.java
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 interface GetArray {
|
||||
Object[] get(double[][][] x);
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 interface GetCloneable {
|
||||
Cloneable get(double[][][] x);
|
||||
}
|
||||
26
test/jdk/java/lang/reflect/Proxy/returnTypes/GetObject.java
Normal file
26
test/jdk/java/lang/reflect/Proxy/returnTypes/GetObject.java
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 interface GetObject {
|
||||
Object get(double[][][] x);
|
||||
}
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface GetSerializable {
|
||||
Serializable get(double[][][] x);
|
||||
}
|
||||
91
test/jdk/java/lang/reflect/Proxy/returnTypes/Test.java
Normal file
91
test/jdk/java/lang/reflect/Proxy/returnTypes/Test.java
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 4838310
|
||||
* @summary This test verifies that the restrictions on proxy interface
|
||||
* methods with the same signature but different return types are
|
||||
* correctly enforced.
|
||||
* @author Peter Jones
|
||||
*
|
||||
* @build GetObject GetSerializable GetCloneable GetArray
|
||||
* @run main Test
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class Test {
|
||||
|
||||
// additional test cases may be added to both of these lists:
|
||||
|
||||
private static final Class<?>[][] GOOD = {
|
||||
{ Collection.class },
|
||||
{ Iterable.class, Collection.class },
|
||||
{ Iterable.class, Collection.class, List.class },
|
||||
{ GetSerializable.class, GetCloneable.class, GetArray.class },
|
||||
{ GetObject.class, GetSerializable.class, GetCloneable.class,
|
||||
GetArray.class }
|
||||
};
|
||||
|
||||
private static final Class<?>[][] BAD = {
|
||||
{ Runnable.class, PrivilegedAction.class },
|
||||
{ GetSerializable.class, GetCloneable.class },
|
||||
{ GetObject.class, GetSerializable.class, GetCloneable.class }
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.err.println("\nRegression test for bug 4838310\n");
|
||||
|
||||
ClassLoader loader = Test.class.getClassLoader();
|
||||
|
||||
System.err.println("Testing GOOD combinations:");
|
||||
|
||||
for (int i = 0; i < GOOD.length; i++) {
|
||||
Class<?>[] interfaces = GOOD[i];
|
||||
System.err.println(Arrays.asList(interfaces));
|
||||
Proxy.getProxyClass(loader, interfaces);
|
||||
System.err.println("--- OK.");
|
||||
}
|
||||
|
||||
System.err.println("Testing BAD combinations:");
|
||||
|
||||
for (int i = 0; i < BAD.length; i++) {
|
||||
Class<?>[] interfaces = BAD[i];
|
||||
System.err.println(Arrays.asList(interfaces));
|
||||
try {
|
||||
Proxy.getProxyClass(loader, interfaces);
|
||||
throw new RuntimeException(
|
||||
"TEST FAILED: bad combination succeeded");
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("--- OK.");
|
||||
}
|
||||
}
|
||||
|
||||
System.err.println("TEST PASSED");
|
||||
}
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/src/m1/module-info.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/src/m1/module-info.java
Normal 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 p.one;
|
||||
exports p.one.internal to test;
|
||||
}
|
||||
30
test/jdk/java/lang/reflect/Proxy/src/m1/p/one/I.java
Normal file
30
test/jdk/java/lang/reflect/Proxy/src/m1/p/one/I.java
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package p.one;
|
||||
|
||||
public interface I {
|
||||
void run();
|
||||
|
||||
default int m() { return 1; }
|
||||
}
|
||||
|
|
@ -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.
|
||||
*/
|
||||
|
||||
package p.one.internal;
|
||||
|
||||
public interface J {
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/src/m2/module-info.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/src/m2/module-info.java
Normal 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 m2 {
|
||||
exports p.two;
|
||||
exports p.two.internal to test;
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/src/m2/p/two/A.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/src/m2/p/two/A.java
Normal 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.
|
||||
*/
|
||||
|
||||
package p.two;
|
||||
|
||||
public interface A {
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/src/m2/p/two/B.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/src/m2/p/two/B.java
Normal 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.
|
||||
*/
|
||||
|
||||
package p.two;
|
||||
|
||||
interface B {
|
||||
}
|
||||
34
test/jdk/java/lang/reflect/Proxy/src/m2/p/two/Bar.java
Normal file
34
test/jdk/java/lang/reflect/Proxy/src/m2/p/two/Bar.java
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 p.two;
|
||||
|
||||
public class Bar {
|
||||
public Bar() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package p.two.internal;
|
||||
|
||||
public interface C {
|
||||
default int m() { return 2; }
|
||||
}
|
||||
27
test/jdk/java/lang/reflect/Proxy/src/m3/module-info.java
Normal file
27
test/jdk/java/lang/reflect/Proxy/src/m3/module-info.java
Normal 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 m3 {
|
||||
requires transitive m2;
|
||||
exports p.three;
|
||||
}
|
||||
32
test/jdk/java/lang/reflect/Proxy/src/m3/p/three/P.java
Normal file
32
test/jdk/java/lang/reflect/Proxy/src/m3/p/three/P.java
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 p.three;
|
||||
|
||||
import p.two.Bar;
|
||||
|
||||
public interface P {
|
||||
public Bar bar();
|
||||
|
||||
public Bar[][][] barArrays();
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package p.three.internal;
|
||||
|
||||
public interface Q {
|
||||
default int m() {
|
||||
throw new UnsupportedOperationException("Q::m is in a non-exported package");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package jdk.test;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
|
||||
/**
|
||||
* Tests invocation of default methods in exported types and inaccessible types
|
||||
* in a named module
|
||||
*/
|
||||
public class DefaultMethods {
|
||||
private final static Module TEST_MODULE = DefaultMethods.class.getModule();
|
||||
private final static InvocationHandler IH = (proxy, method, params) -> {
|
||||
return InvocationHandler.invokeDefault(proxy, method, params);
|
||||
};
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
// exported types from m1
|
||||
testDefaultMethod(new Class<?>[] { p.one.I.class, p.two.A.class}, 1);
|
||||
// qualified-exported type from m2
|
||||
testDefaultMethod(new Class<?>[] { p.two.internal.C.class, p.two.A.class }, 2);
|
||||
// module-private type from test module
|
||||
testDefaultMethod(new Class<?>[] { jdk.test.internal.R.class }, 10);
|
||||
// non-public interface in the same runtime package
|
||||
testDefaultMethod(new Class<?>[] { Class.forName("jdk.test.NP") }, 100);
|
||||
|
||||
// inaccessible type - not exported to test module
|
||||
Class<?> qType = Class.forName("p.three.internal.Q");
|
||||
inaccessibleDefaultMethod(qType);
|
||||
// non-public interface in the same runtime package
|
||||
Class<?> nonPublicType = Class.forName("jdk.test.internal.NP");
|
||||
inaccessibleDefaultMethod(nonPublicType);
|
||||
}
|
||||
|
||||
static void testDefaultMethod(Class<?>[] intfs, int expected) throws Exception {
|
||||
Object proxy = Proxy.newProxyInstance(TEST_MODULE.getClassLoader(), intfs, IH);
|
||||
if (!proxy.getClass().getModule().isNamed()) {
|
||||
throw new RuntimeException(proxy.getClass() + " expected to be in a named module");
|
||||
}
|
||||
Method m = intfs[0].getMethod("m");
|
||||
int result = (int)m.invoke(proxy);
|
||||
if (result != expected) {
|
||||
throw new RuntimeException("return value: " + result + " expected: " + expected);
|
||||
}
|
||||
}
|
||||
|
||||
static void inaccessibleDefaultMethod(Class<?> intf) throws Throwable {
|
||||
Object proxy = Proxy.newProxyInstance(TEST_MODULE.getClassLoader(), new Class<?>[] { intf }, IH);
|
||||
if (!proxy.getClass().getModule().isNamed()) {
|
||||
throw new RuntimeException(proxy.getClass() + " expected to be in a named module");
|
||||
}
|
||||
Method m = intf.getMethod("m");
|
||||
try {
|
||||
InvocationHandler.invokeDefault(proxy, m, null);
|
||||
throw new RuntimeException("IAE not thrown invoking: " + m);
|
||||
} catch (IllegalAccessException e) {}
|
||||
|
||||
if (m.trySetAccessible()) {
|
||||
try {
|
||||
m.invoke(proxy);
|
||||
throw new RuntimeException("IAE not thrown invoking: " + m);
|
||||
} catch (InvocationTargetException e) {
|
||||
// IAE wrapped by InvocationHandler::invoke with UndeclaredThrowableException
|
||||
// then wrapped by Method::invoke with InvocationTargetException
|
||||
assert e.getCause() instanceof UndeclaredThrowableException;
|
||||
Throwable cause = e.getCause().getCause();
|
||||
if (!(cause instanceof IllegalAccessException))
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
160
test/jdk/java/lang/reflect/Proxy/src/test/jdk/test/Main.java
Normal file
160
test/jdk/java/lang/reflect/Proxy/src/test/jdk/test/Main.java
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.test;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import static jdk.test.ProxyTest.*;
|
||||
|
||||
public class Main {
|
||||
public static void main(String... args) {
|
||||
ProxyTest ptest = new jdk.test.ProxyTest();
|
||||
for (Data d : proxiesForExportedTypes()) {
|
||||
ptest.test(d);
|
||||
}
|
||||
|
||||
for (Data d : proxiesForPackagePrivateTypes()) {
|
||||
ptest.test(d);
|
||||
}
|
||||
|
||||
for (Data d : proxiesForModulePrivateTypes()) {
|
||||
ptest.test(d);
|
||||
}
|
||||
|
||||
for (Data d : proxiesWithAddReads()) {
|
||||
ptest.test(d);
|
||||
}
|
||||
|
||||
for (Data d : proxiesWithAddExports()) {
|
||||
ptest.test(d);
|
||||
}
|
||||
}
|
||||
|
||||
private final static Module m1 = p.one.I.class.getModule();
|
||||
private final static Module m2 = p.two.A.class.getModule();
|
||||
private final static Module m3 = p.three.P.class.getModule();
|
||||
private final static Module test = Main.class.getModule();
|
||||
private final static Class<?> unnamedModuleClass = classForName("q.U");
|
||||
private final static Class<?> m3InternalType = classForName("p.three.internal.Q");
|
||||
|
||||
/*
|
||||
* Test cases for proxy class to implement exported proxy interfaces
|
||||
* will result in the unnamed module.
|
||||
*
|
||||
* The proxy class is accessible to unnamed module.
|
||||
*/
|
||||
static Data[] proxiesForExportedTypes() {
|
||||
ClassLoader ld = Main.class.getClassLoader();
|
||||
ClassLoader ld2 = new URLClassLoader(new URL[0], ld);
|
||||
|
||||
return new Data[] {
|
||||
new Data(ld, Runnable.class),
|
||||
new Data(ld, p.one.I.class),
|
||||
new Data(ld, p.one.I.class, p.two.A.class),
|
||||
new Data(ld, p.one.I.class, unnamedModuleClass),
|
||||
new Data(ld2, Runnable.class),
|
||||
new Data(ld2, p.one.I.class),
|
||||
new Data(ld2, p.one.I.class, p.two.A.class),
|
||||
new Data(ld2, p.one.I.class, unnamedModuleClass),
|
||||
new Data(m1.getClassLoader(), p.one.I.class),
|
||||
new Data(m2.getClassLoader(), p.two.A.class),
|
||||
new Data(m3.getClassLoader(), p.three.P.class),
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Test cases for proxy class to implement package-private proxy interface
|
||||
* will result in same runtime package and same module as the proxy interface
|
||||
*
|
||||
* The proxy class is accessible to classes in the same runtime package
|
||||
*/
|
||||
static Data[] proxiesForPackagePrivateTypes() {
|
||||
Class<?> bClass = classForName("p.two.B"); // package-private type
|
||||
|
||||
return new Data[] {
|
||||
new Data(m2, m2.getClassLoader(), p.two.A.class, bClass),
|
||||
new Data(m2, m2.getClassLoader(), p.two.A.class, bClass, p.two.internal.C.class)
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Test cases for proxy class to implement one or more module-private types.
|
||||
*
|
||||
* This will result in a dynamic module which can read the modules of the interfaces
|
||||
* and their dependences and also qualified exports to the module-private packages.
|
||||
* The proxy class is not accessible to any module.
|
||||
*/
|
||||
static Data[] proxiesForModulePrivateTypes() {
|
||||
ClassLoader ld = Main.class.getClassLoader();
|
||||
ClassLoader customLoader = new URLClassLoader(new URL[0], ld);
|
||||
return new Data[] {
|
||||
// different loaders
|
||||
new Data(m1.getClassLoader(), p.one.internal.J.class),
|
||||
new Data(customLoader, p.one.internal.J.class),
|
||||
new Data(m2.getClassLoader(), p.two.internal.C.class, Runnable.class),
|
||||
// interfaces from m2 only
|
||||
new Data(m2.getClassLoader(), p.two.internal.C.class, p.two.A.class),
|
||||
// p.two.A is accessible to m3
|
||||
new Data(m3.getClassLoader(), m3InternalType, p.two.A.class),
|
||||
new Data(customLoader, unnamedModuleClass, jdk.test.internal.R.class, p.one.I.class),
|
||||
// two module-private types in two different modules
|
||||
new Data(m3.getClassLoader(), p.two.internal.C.class, m3InternalType),
|
||||
new Data(m3.getClassLoader(), p.three.P.class, m3InternalType, jdk.test.internal.R.class),
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Test cases for proxy class to implement accessible proxy interfaces
|
||||
* after addReads. That does not change the target module.
|
||||
*/
|
||||
static Data[] proxiesWithAddReads() {
|
||||
Module unnamed = test.getClassLoader().getUnnamedModule();
|
||||
test.addReads(unnamed);
|
||||
return new Data[] {
|
||||
new Data(test.getClassLoader(),
|
||||
unnamedModuleClass, p.one.I.class,
|
||||
jdk.test.internal.R.class), // module-private interface in test
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Test cases for proxy class to implement accessible proxy interfaces
|
||||
* after addExports. That does not change the target module.
|
||||
*/
|
||||
static Data[] proxiesWithAddExports() {
|
||||
return new Data[] {
|
||||
new Data(test.getClassLoader(),
|
||||
p.one.internal.J.class,
|
||||
p.two.internal.C.class), // module-private interfaces in m2 and m3
|
||||
};
|
||||
}
|
||||
|
||||
static Class<?> classForName(String cn) {
|
||||
try {
|
||||
return Class.forName(cn);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
test/jdk/java/lang/reflect/Proxy/src/test/jdk/test/NP.java
Normal file
35
test/jdk/java/lang/reflect/Proxy/src/test/jdk/test/NP.java
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.test;
|
||||
|
||||
/*
|
||||
* Non-public interface
|
||||
*/
|
||||
interface NP {
|
||||
void test();
|
||||
|
||||
default int m() {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 jdk.test;
|
||||
|
||||
import jdk.test.internal.*;
|
||||
import jdk.test.internal.foo.*;
|
||||
import p.two.Bar;
|
||||
import p.three.P;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* Test proxy class to have access to types referenced in the public methods.
|
||||
*/
|
||||
public class ProxyClassAccess {
|
||||
public static void main(String... args) throws Exception {
|
||||
testImplClass();
|
||||
testProxyClass1();
|
||||
testProxyClass2();
|
||||
testNonPublicProxy();
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke methods from implementation class
|
||||
*/
|
||||
static void testImplClass() {
|
||||
R impl = new RImpl();
|
||||
impl.foo();
|
||||
Bar[][] bars = new Bar[0][0];
|
||||
impl.setBarArray(bars);
|
||||
try {
|
||||
impl.throwException();
|
||||
throw new RuntimeException("FooException not thrown");
|
||||
} catch (FooException e) { }
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke methods via proxy
|
||||
*/
|
||||
static void testProxyClass1() {
|
||||
R proxy = (R) Proxy.newProxyInstance(R.class.getClassLoader(),
|
||||
new Class<?>[] { R.class }, handler);
|
||||
proxy.foo();
|
||||
Bar[][] bars = new Bar[0][0];
|
||||
proxy.setBarArray(bars);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke methods via proxy defined with a custom class loader
|
||||
*/
|
||||
static void testProxyClass2() {
|
||||
URLClassLoader loader = new URLClassLoader(new URL[0]);
|
||||
P proxy = (P) Proxy.newProxyInstance(loader,
|
||||
new Class<?>[] { R.class, P.class }, handler);
|
||||
proxy.bar();
|
||||
proxy.barArrays();
|
||||
}
|
||||
|
||||
static void testNonPublicProxy() {
|
||||
NP proxy = (NP) Proxy.newProxyInstance(NP.class.getClassLoader(),
|
||||
new Class<?>[]{NP.class}, handler);
|
||||
proxy.test();
|
||||
|
||||
try {
|
||||
URLClassLoader loader = new URLClassLoader(new URL[0]);
|
||||
proxy = (NP) Proxy.newProxyInstance(loader,
|
||||
new Class<?>[]{NP.class}, handler);
|
||||
throw new RuntimeException("IllegalArgumentException not thrown");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
static InvocationHandler handler = new InvocationHandler() {
|
||||
final R impl = new RImpl();
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getDeclaringClass() == R.class) {
|
||||
return method.invoke(impl, args);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.test;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ProxyTest {
|
||||
public static class Data {
|
||||
private static int count = 0;
|
||||
final int testcase;
|
||||
final ClassLoader loader;
|
||||
final Module module;
|
||||
final Class<?>[] interfaces;
|
||||
// Expected the proxy class in the specified module
|
||||
public Data(Module m, ClassLoader loader, Class<?>... interfaces) {
|
||||
this.module = m;
|
||||
this.loader = loader;
|
||||
this.interfaces = interfaces;
|
||||
this.testcase = ++count;
|
||||
}
|
||||
// Expected the proxy class in a dynamic module
|
||||
public Data(ClassLoader loader, Class<?>... interfaces) {
|
||||
this(null, loader, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String expected = module != null
|
||||
? (module.isNamed() ? module.getName() : "unnamed")
|
||||
: "dynamic";
|
||||
return String.format("%2d: Expected: %s %s loader: %s", testcase, expected,
|
||||
Arrays.toString(interfaces), loader);
|
||||
}
|
||||
}
|
||||
|
||||
public void test(Data d) {
|
||||
System.out.println(d);
|
||||
|
||||
if (d.module != null) {
|
||||
testProxyClass(d.module, d.loader, d.interfaces);
|
||||
} else {
|
||||
testDynamicModule(d);
|
||||
}
|
||||
}
|
||||
|
||||
private void testDynamicModule(Data d) {
|
||||
Class<?> proxyClass = Proxy.getProxyClass(d.loader, d.interfaces);
|
||||
assertDynamicModule(proxyClass.getModule(), d.loader, proxyClass);
|
||||
|
||||
Object proxy = Proxy.newProxyInstance(d.loader, d.interfaces, handler);
|
||||
assertDynamicModule(proxy.getClass().getModule(), d.loader, proxy.getClass());
|
||||
}
|
||||
|
||||
private static void testProxyClass(Module module, ClassLoader ld, Class<?>... interfaces) {
|
||||
Class<?> proxyClass = Proxy.getProxyClass(ld, interfaces);
|
||||
assertEquals(proxyClass.getModule(), module);
|
||||
|
||||
Object proxy = Proxy.newProxyInstance(ld, interfaces, handler);
|
||||
assertEquals(proxy.getClass().getModule(), module);
|
||||
}
|
||||
|
||||
public static void assertDynamicModule(Module m, ClassLoader ld, Class<?> proxyClass) {
|
||||
if (!m.isNamed() || !m.getName().startsWith("jdk.proxy")) {
|
||||
throw new RuntimeException(m.getName() + " not dynamic module");
|
||||
}
|
||||
|
||||
if (ld != m.getClassLoader() || proxyClass.getClassLoader() != ld) {
|
||||
throw new RuntimeException("unexpected class loader");
|
||||
}
|
||||
|
||||
try {
|
||||
Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class);
|
||||
cons.newInstance(handler);
|
||||
// the exported package has the same name as the dynamic module
|
||||
if (!proxyClass.getPackageName().equals(m.getName())) {
|
||||
throw new RuntimeException("Expected IllegalAccessException: " + proxyClass);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
// expected
|
||||
} catch (NoSuchMethodException|InstantiationException|InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertEquals(Object o1, Object o2) {
|
||||
if (o1 != o2) {
|
||||
throw new RuntimeException(o1 + " != " + o2);
|
||||
}
|
||||
}
|
||||
private final static InvocationHandler handler =
|
||||
(proxy, m, params) -> { throw new RuntimeException(m.toString()); };
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package jdk.test.internal;
|
||||
|
||||
/*
|
||||
* Non-public interface
|
||||
*/
|
||||
interface NP {
|
||||
default int m() {
|
||||
throw new UnsupportedOperationException("non-public interface: " + NP.class.getName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.test.internal;
|
||||
|
||||
import jdk.test.internal.foo.*;
|
||||
import p.two.Bar;
|
||||
|
||||
public interface R {
|
||||
public Foo foo();
|
||||
public void throwException() throws FooException;
|
||||
|
||||
public void setBarArray(Bar[][] array);
|
||||
|
||||
default int m() { return 10; }
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 jdk.test.internal;
|
||||
|
||||
import jdk.test.internal.foo.*;
|
||||
import p.two.Bar;
|
||||
|
||||
public class RImpl implements R {
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
public void throwException() throws FooException {
|
||||
throw new FooException();
|
||||
}
|
||||
public void setBarArray(Bar[][] array) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 jdk.test.internal.foo;
|
||||
|
||||
public class Foo {
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 jdk.test.internal.foo;
|
||||
|
||||
public class FooException extends RuntimeException {
|
||||
public FooException() {
|
||||
}
|
||||
}
|
||||
29
test/jdk/java/lang/reflect/Proxy/src/test/module-info.java
Normal file
29
test/jdk/java/lang/reflect/Proxy/src/test/module-info.java
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 test {
|
||||
requires m1;
|
||||
requires m3; // requires transitive m2
|
||||
|
||||
exports jdk.test;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue