From 831c529a98608d656e24268eba9f5f7f6a7ccaf6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 28 Aug 2014 16:59:06 -0600 Subject: [PATCH 1/2] make Class.getMethod (and getConstructor) more strict about parameter types This matches the JDK behavior. --- classpath/avian/Classes.java | 12 +++++++++++- src/builtin.cpp | 7 +++++++ test/Reflection.java | 19 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index f912971688..17b7d864a8 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -43,6 +43,8 @@ public class Classes { public static native VMClass getVMClass(Object o); + public static native VMClass toVMClass(Class c); + private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec) throws ClassNotFoundException; @@ -391,10 +393,18 @@ public class Classes { return new String(array, 0, array.length - 1); } + private static boolean match(VMClass a, VMClass b) { + if (a.arrayDimensions > 0) { + return match(a.arrayElementClass, b.arrayElementClass); + } else { + return a == b; + } + } + public static boolean match(Class[] a, Class[] b) { if (a.length == b.length) { for (int i = 0; i < a.length; ++i) { - if (! a[i].isAssignableFrom(b[i])) { + if (! match(toVMClass(a[i]), toVMClass(b[i]))) { return false; } } diff --git a/src/builtin.cpp b/src/builtin.cpp index a91e9d7df0..ef535e74fd 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -106,6 +106,13 @@ GcField* fieldForOffset(Thread* t, object o, unsigned offset) } // namespace +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_avian_Classes_toVMClass(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast( + cast(t, reinterpret_cast(arguments[0]))->vmClass()); +} + extern "C" AVIAN_EXPORT void JNICALL Avian_avian_Classes_initialize(Thread* t, object, uintptr_t* arguments) { diff --git a/test/Reflection.java b/test/Reflection.java index 592c266c99..8a9f4de1cc 100644 --- a/test/Reflection.java +++ b/test/Reflection.java @@ -260,6 +260,15 @@ public class Reflection { .getEnclosingMethod().equals (Reflection.class.getMethod ("main", new Class[] { String[].class }))); + + Slithy.class.getMethod("tove", Gybe.class); + + try { + Slithy.class.getMethod("tove", Bandersnatch.class); + expect(false); + } catch (NoSuchMethodException e) { + // cool + } } protected static class Baz { @@ -267,6 +276,16 @@ public class Reflection { } } +class Bandersnatch { } + +class Gybe extends Bandersnatch { } + +class Slithy { + public static void tove(Gybe gybe) { + // ignore + } +} + class Foo { static { if (true) throw new MyException(); From a81879129a5887061cbcd6739e7c98888d8c4c28 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 3 Sep 2014 16:24:15 -0600 Subject: [PATCH 2/2] add a TODO comment about class comparison --- classpath/avian/Classes.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index 17b7d864a8..0bd05310fb 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -394,6 +394,13 @@ public class Classes { } private static boolean match(VMClass a, VMClass b) { + // TODO: in theory we should be able to just do an == comparison + // here instead of recursively comparing array element types. + // However, the VM currently can create multiple array classes for + // the same element type. We should fix that so that there's only + // ever one of each per classloader, eliminating the need for a + // recursive comparison. See also the native implementation of + // isAssignableFrom. if (a.arrayDimensions > 0) { return match(a.arrayElementClass, b.arrayElementClass); } else {