7cc1371059
Co-authored-by: Lois Foltan <lois.foltan@oracle.com> Co-authored-by: David Holmes <david.holmes@oracle.com> Co-authored-by: Harold Seigel <harold.seigel@oracle.com> Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com> Co-authored-by: Alex Buckley <alex.buckley@oracle.com> Co-authored-by: Jamsheed Mohammed C M <jamsheed.c.m@oracle.com> Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com> Co-authored-by: Amy Lu <amy.lu@oracle.com> Reviewed-by: alanb, cjplummer, coleenp, dholmes, dlong, forax, jlahoda, psandoz, plevart, sspitsyn, vromero
163 lines
5.9 KiB
Java
163 lines
5.9 KiB
Java
/*
|
|
* 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
|
|
* @summary Test the rules for dynamic nest membership using the Lookup.defineHiddenClass API
|
|
* @compile OtherPackage.java
|
|
* @run main/othervm TestDynamicNestmateMembership
|
|
*/
|
|
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Paths;
|
|
import java.nio.file.Path;
|
|
import java.lang.invoke.MethodHandles;
|
|
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
|
|
|
|
/* package */ class DynamicNestmate { }
|
|
|
|
/* package */ class DynamicNestmate2 { }
|
|
|
|
/* package */ class StaticHost {
|
|
static class StaticMember {
|
|
}
|
|
}
|
|
|
|
public class TestDynamicNestmateMembership {
|
|
|
|
static class Member {
|
|
static MethodHandles.Lookup getLookup() {
|
|
return MethodHandles.lookup();
|
|
}
|
|
}
|
|
|
|
static final String CLASSES = System.getProperty("test.classes");
|
|
static final Path CLASSES_DIR = Paths.get(CLASSES);
|
|
|
|
static byte[] getBytesForClass(String name) throws IOException {
|
|
Path classFile;
|
|
if (name.indexOf('.') > 0) {
|
|
// it's in a package
|
|
String[] paths = name.split("\\.");
|
|
classFile = CLASSES_DIR.resolve(paths[0]);
|
|
classFile = classFile.resolve(paths[1] + ".class");
|
|
}
|
|
else {
|
|
classFile = CLASSES_DIR.resolve(name + ".class");
|
|
}
|
|
return Files.readAllBytes(classFile);
|
|
}
|
|
|
|
static final Class<?> cls = TestDynamicNestmateMembership.class;
|
|
static final MethodHandles.Lookup main_lookup = MethodHandles.lookup();
|
|
|
|
public static void main(String[] args) throws Throwable {
|
|
test_validInjection();
|
|
test_hostIsMember();
|
|
test_otherPackage();
|
|
test_alreadyNestMember();
|
|
test_alreadyNestHost();
|
|
}
|
|
|
|
// Inject a valid class into the nest of the current class
|
|
static void test_validInjection() {
|
|
String name = "DynamicNestmate";
|
|
inject(name, null);
|
|
}
|
|
|
|
// Try to inject a class into a "host" that is itself a member.
|
|
// This is redirected at the defineClass level to the member's
|
|
// host and so will succeed.
|
|
static void test_hostIsMember() {
|
|
String name = "DynamicNestmate2";
|
|
inject(name, Member.getLookup(), null);
|
|
}
|
|
|
|
// Try to inject a class that has a static NestHost attribute
|
|
// No error since the nest host has been set when it's created.
|
|
// Static nest membership is effectively ignored.
|
|
static void test_alreadyNestMember() {
|
|
String name = "StaticHost$StaticMember";
|
|
inject(name, null);
|
|
}
|
|
|
|
// Try to inject a class that has the NestMembers attribute.
|
|
// No error since the nest host has been set when it's created.
|
|
// Static nest membership is effectively ignored.
|
|
static void test_alreadyNestHost() {
|
|
String name = "StaticHost";
|
|
inject(name, null);
|
|
}
|
|
|
|
// Try to inject a class that is in another package
|
|
static void test_otherPackage() {
|
|
String name = "test.OtherPackage";
|
|
inject(name, IllegalArgumentException.class);
|
|
}
|
|
|
|
static void inject(String name, Class<? extends Throwable> ex) {
|
|
inject(name, main_lookup, ex);
|
|
}
|
|
|
|
static void inject(String name, MethodHandles.Lookup lookup,
|
|
Class<? extends Throwable> ex) {
|
|
Class<?> target = lookup.lookupClass();
|
|
String action = "Injecting " + name + " into the nest of " +
|
|
target.getSimpleName();
|
|
try {
|
|
byte[] bytes = getBytesForClass(name);
|
|
Class<?> nestmate = lookup.defineHiddenClass(bytes, false, NESTMATE).lookupClass();
|
|
if (ex != null) {
|
|
throw new RuntimeException(action + " was expected to throw " +
|
|
ex.getSimpleName());
|
|
}
|
|
Class<?> actualHost = nestmate.getNestHost();
|
|
Class<?> expectedHost = target.getNestHost();
|
|
if (actualHost != expectedHost) {
|
|
throw new RuntimeException(action + " expected a nest-host of "
|
|
+ expectedHost.getSimpleName() +
|
|
" but got " + actualHost.getSimpleName());
|
|
}
|
|
System.out.print("Ok: " + action + " succeeded: ");
|
|
if (actualHost != target) {
|
|
System.out.print("(re-directed to target's nest-host) ");
|
|
}
|
|
System.out.println("Nesthost of " + nestmate.getName() +
|
|
" is " + actualHost.getName());
|
|
} catch (Throwable t) {
|
|
if (t.getClass() == ex) {
|
|
System.out.println("Ok: " + action + " got expected exception: " +
|
|
t.getClass().getSimpleName() + ":" +
|
|
t.getMessage());
|
|
}
|
|
else {
|
|
throw new RuntimeException(action + " got unexpected exception " +
|
|
t.getClass().getSimpleName(), t);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|