From 00b829b8e8135fa0b62a04212b5fe67b9baf57e5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 9 Apr 2011 21:20:56 -0600 Subject: [PATCH] fix Class.getDeclaredMethods Internally, the VM augments the method tables for abstract classes with any inherited abstract methods to make code simpler elsewhere, but that means we can't use that table to construct the result of Class.getDeclaredMethods since it would include methods not actually declared in the class. This commit ensures that we preserve and use the original, un-augmented table for that purpose. --- classpath/avian/ClassAddendum.java | 1 + src/classpath-openjdk.cpp | 21 ++++++++++++--- src/machine.cpp | 43 +++++++++++++++--------------- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/classpath/avian/ClassAddendum.java b/classpath/avian/ClassAddendum.java index ff11591046..276be33fe9 100644 --- a/classpath/avian/ClassAddendum.java +++ b/classpath/avian/ClassAddendum.java @@ -13,4 +13,5 @@ package avian; public class ClassAddendum extends Addendum { public Object[] interfaceTable; public Object[] innerClassTable; + public Object[] methodTable; } diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 569bf4693d..89648f15de 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1865,10 +1865,23 @@ interceptFileOperations(Thread* t) voidPointer(getBootstrapResources)); } +object +getClassMethodTable(Thread* t, object c) +{ + object addendum = classAddendum(t, c); + if (addendum) { + object table = classAddendumMethodTable(t, addendum); + if (table) { + return table; + } + } + return classMethodTable(t, c); +} + unsigned countMethods(Thread* t, object c, bool publicOnly) { - object table = classMethodTable(t, c); + object table = getClassMethodTable(t, c); unsigned count = 0; for (unsigned i = 0; i < arrayLength(t, table); ++i) { object vmMethod = arrayBody(t, table, i); @@ -1902,7 +1915,7 @@ countFields(Thread* t, object c, bool publicOnly) unsigned countConstructors(Thread* t, object c, bool publicOnly) { - object table = classMethodTable(t, c); + object table = getClassMethodTable(t, c); unsigned count = 0; for (unsigned i = 0; i < arrayLength(t, table); ++i) { object vmMethod = arrayBody(t, table, i); @@ -4054,7 +4067,7 @@ jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments) jclass c = reinterpret_cast(arguments[0]); jboolean publicOnly = arguments[1]; - object table = classMethodTable(t, jclassVmClass(t, *c)); + object table = getClassMethodTable(t, jclassVmClass(t, *c)); if (table) { PROTECT(t, table); @@ -4249,7 +4262,7 @@ jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments) jclass c = reinterpret_cast(arguments[0]); jboolean publicOnly = arguments[1]; - object table = classMethodTable(t, jclassVmClass(t, *c)); + object table = getClassMethodTable(t, jclassVmClass(t, *c)); if (table) { PROTECT(t, table); diff --git a/src/machine.cpp b/src/machine.cpp index 2f7f896e2f..d01abec796 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -969,6 +969,17 @@ addInterfaces(Thread* t, object class_, object map) } } +object +getClassAddendum(Thread* t, object class_, object pool) +{ + object addendum = classAddendum(t, class_); + if (addendum == 0) { + addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, 0); + set(t, class_, ClassAddendum, addendum); + } + return addendum; +} + void parseInterfaceTable(Thread* t, Stream& s, object class_, object pool, Machine::Type throwType) @@ -989,10 +1000,9 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool, if (count) { table = makeArray(t, count); - if (classAddendum(t, class_) == 0) { - object addendum = makeClassAddendum(t, pool, 0, 0, table, 0); - set(t, class_, ClassAddendum, addendum); - } + + object addendum = getClassAddendum(t, class_, pool); + set(t, addendum, ClassAddendumInterfaceTable, table); } for (unsigned i = 0; i < count; ++i) { @@ -1644,6 +1654,10 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) if (abstractVirtuals) { PROTECT(t, vtable); + object addendum = getClassAddendum(t, class_, pool); + set(t, addendum, ClassAddendumMethodTable, + classMethodTable(t, class_)); + unsigned oldLength = arrayLength(t, classMethodTable(t, class_)); object newMethodTable = makeArray (t, oldLength + listSize(t, abstractVirtuals)); @@ -1707,9 +1721,6 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) PROTECT(t, class_); PROTECT(t, pool); - object addendum = classAddendum(t, class_); - PROTECT(t, addendum); - unsigned attributeCount = s.read2(); for (unsigned j = 0; j < attributeCount; ++j) { object name = singletonObject(t, pool, s.read2() - 1); @@ -1722,19 +1733,12 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) } else if (vm::strcmp(reinterpret_cast("Signature"), &byteArrayBody(t, name, 0)) == 0) { - if (addendum == 0) { - addendum = makeClassAddendum(t, pool, 0, 0, 0, 0); - } - + object addendum = getClassAddendum(t, class_, pool); set(t, addendum, AddendumSignature, singletonObject(t, pool, s.read2() - 1)); } else if (vm::strcmp(reinterpret_cast("InnerClasses"), &byteArrayBody(t, name, 0)) == 0) { - if (addendum == 0) { - addendum = makeClassAddendum(t, pool, 0, 0, 0, 0); - } - unsigned innerClassCount = s.read2(); object table = makeArray(t, innerClassCount); PROTECT(t, table); @@ -1754,25 +1758,22 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) set(t, table, ArrayBody + (i * BytesPerWord), reference); } + object addendum = getClassAddendum(t, class_, pool); set(t, addendum, ClassAddendumInnerClassTable, table); } else if (vm::strcmp(reinterpret_cast ("RuntimeVisibleAnnotations"), &byteArrayBody(t, name, 0)) == 0) { - if (addendum == 0) { - addendum = makeClassAddendum(t, pool, 0, 0, 0, 0); - } - object body = makeByteArray(t, length); + PROTECT(t, body); s.read(reinterpret_cast(&byteArrayBody(t, body, 0)), length); + object addendum = getClassAddendum(t, class_, pool); set(t, addendum, AddendumAnnotationTable, body); } else { s.skip(length); } } - - set(t, class_, ClassAddendum, addendum); } void