MethodHandles: Track libcore change cc4ded.
Track increase in vtable size of java.lang.Class, and add additional
tests for the method that resulted in the increase as well as its
caller.
Bug: 30550796
Test: make test-art-host
Change-Id: I0ea6cbf8840d45b74f3a50e4c9df2af5397d41e3
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 5793795..1261b0a 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -561,7 +561,7 @@
// The size of java.lang.Class.class.
static uint32_t ClassClassSize(PointerSize pointer_size) {
// The number of vtable entries in java.lang.Class.
- uint32_t vtable_entries = Object::kVTableLength + 72;
+ uint32_t vtable_entries = Object::kVTableLength + 73;
return ComputeClassSize(true, vtable_entries, 0, 0, 4, 1, 0, pointer_size);
}
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index 58ba55d..44c0447 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -58,6 +58,7 @@
testfindSpecial_invokeSuperBehaviour();
testfindSpecial_invokeDirectBehaviour();
testExceptionDetailMessages();
+ testfindVirtual();
}
public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
@@ -140,6 +141,127 @@
System.out.println("Received exception: " + ex.getMessage());
}
}
+
+ public interface Foo {
+ public String foo();
+ }
+
+ public interface Bar extends Foo {
+ public String bar();
+ }
+
+ public static class BarSuper {
+ public String superPublicMethod() {
+ return "superPublicMethod";
+ }
+
+ public String superProtectedMethod() {
+ return "superProtectedMethod";
+ }
+
+ String superPackageMethod() {
+ return "superPackageMethod";
+ }
+ }
+
+ public static class BarImpl extends BarSuper implements Bar {
+ public BarImpl() {
+ }
+
+ @Override
+ public String foo() {
+ return "foo";
+ }
+
+ @Override
+ public String bar() {
+ return "bar";
+ }
+
+ private String privateMethod() { return "privateMethod"; }
+
+ public static String staticMethod() { return null; }
+
+ static final MethodHandles.Lookup lookup = MethodHandles.lookup();
+ }
+
+ public static void testfindVirtual() throws Throwable {
+ // Virtual lookups on static methods should not succeed.
+ try {
+ MethodHandles.lookup().findVirtual(
+ BarImpl.class, "staticMethod", MethodType.methodType(String.class));
+ System.out.println("findVirtual(staticMethod) unexpectedly succeeded");
+ } catch (IllegalAccessException expected) {
+ }
+
+ // Virtual lookups on private methods should not succeed, unless the Lookup
+ // context had sufficient privileges.
+ try {
+ MethodHandles.lookup().findVirtual(
+ BarImpl.class, "privateMethod", MethodType.methodType(String.class));
+ System.out.println("findVirtual(privateMethod) unexpectedly succeeded");
+ } catch (IllegalAccessException expected) {
+ }
+
+ // Virtual lookup on a private method with a context that *does* have sufficient
+ // privileges.
+ MethodHandle mh = BarImpl.lookup.findVirtual(
+ BarImpl.class, "privateMethod", MethodType.methodType(String.class));
+ String str = (String) mh.invoke(new BarImpl());
+ if (!"privateMethod".equals(str)) {
+ System.out.println("Unexpected return value for BarImpl#privateMethod: " + str);
+ }
+
+ // Find virtual must find interface methods defined by interfaces implemented
+ // by the class.
+ mh = MethodHandles.lookup().findVirtual(BarImpl.class, "foo",
+ MethodType.methodType(String.class));
+ str = (String) mh.invoke(new BarImpl());
+ if (!"foo".equals(str)) {
+ System.out.println("Unexpected return value for BarImpl#foo: " + str);
+ }
+
+ // .. and their super-interfaces.
+ mh = MethodHandles.lookup().findVirtual(BarImpl.class, "bar",
+ MethodType.methodType(String.class));
+ str = (String) mh.invoke(new BarImpl());
+ if (!"bar".equals(str)) {
+ System.out.println("Unexpected return value for BarImpl#bar: " + str);
+ }
+
+ // TODO(narayan): Fix this case, we're using the wrong ArtMethod for the
+ // invoke resulting in a failing check in the interpreter.
+ //
+ // mh = MethodHandles.lookup().findVirtual(Bar.class, "bar",
+ // MethodType.methodType(String.class));
+ // str = (String) mh.invoke(new BarImpl());
+ // if (!"bar".equals(str)) {
+ // System.out.println("Unexpected return value for BarImpl#bar: " + str);
+ // }
+
+ // We should also be able to lookup public / protected / package methods in
+ // the super class, given sufficient access privileges.
+ mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superPublicMethod",
+ MethodType.methodType(String.class));
+ str = (String) mh.invoke(new BarImpl());
+ if (!"superPublicMethod".equals(str)) {
+ System.out.println("Unexpected return value for BarImpl#superPublicMethod: " + str);
+ }
+
+ mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superProtectedMethod",
+ MethodType.methodType(String.class));
+ str = (String) mh.invoke(new BarImpl());
+ if (!"superProtectedMethod".equals(str)) {
+ System.out.println("Unexpected return value for BarImpl#superProtectedMethod: " + str);
+ }
+
+ mh = MethodHandles.lookup().findVirtual(BarImpl.class, "superPackageMethod",
+ MethodType.methodType(String.class));
+ str = (String) mh.invoke(new BarImpl());
+ if (!"superPackageMethod".equals(str)) {
+ System.out.println("Unexpected return value for BarImpl#superPackageMethod: " + str);
+ }
+ }
}