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.
This commit is contained in:
Joel Dice
2011-04-09 21:20:56 -06:00
parent 1476243662
commit 00b829b8e8
3 changed files with 40 additions and 25 deletions

View File

@ -13,4 +13,5 @@ package avian;
public class ClassAddendum extends Addendum { public class ClassAddendum extends Addendum {
public Object[] interfaceTable; public Object[] interfaceTable;
public Object[] innerClassTable; public Object[] innerClassTable;
public Object[] methodTable;
} }

View File

@ -1865,10 +1865,23 @@ interceptFileOperations(Thread* t)
voidPointer(getBootstrapResources)); 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 unsigned
countMethods(Thread* t, object c, bool publicOnly) countMethods(Thread* t, object c, bool publicOnly)
{ {
object table = classMethodTable(t, c); object table = getClassMethodTable(t, c);
unsigned count = 0; unsigned count = 0;
for (unsigned i = 0; i < arrayLength(t, table); ++i) { for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object vmMethod = arrayBody(t, table, i); object vmMethod = arrayBody(t, table, i);
@ -1902,7 +1915,7 @@ countFields(Thread* t, object c, bool publicOnly)
unsigned unsigned
countConstructors(Thread* t, object c, bool publicOnly) countConstructors(Thread* t, object c, bool publicOnly)
{ {
object table = classMethodTable(t, c); object table = getClassMethodTable(t, c);
unsigned count = 0; unsigned count = 0;
for (unsigned i = 0; i < arrayLength(t, table); ++i) { for (unsigned i = 0; i < arrayLength(t, table); ++i) {
object vmMethod = arrayBody(t, table, i); object vmMethod = arrayBody(t, table, i);
@ -4054,7 +4067,7 @@ jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments)
jclass c = reinterpret_cast<jclass>(arguments[0]); jclass c = reinterpret_cast<jclass>(arguments[0]);
jboolean publicOnly = arguments[1]; jboolean publicOnly = arguments[1];
object table = classMethodTable(t, jclassVmClass(t, *c)); object table = getClassMethodTable(t, jclassVmClass(t, *c));
if (table) { if (table) {
PROTECT(t, table); PROTECT(t, table);
@ -4249,7 +4262,7 @@ jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments)
jclass c = reinterpret_cast<jclass>(arguments[0]); jclass c = reinterpret_cast<jclass>(arguments[0]);
jboolean publicOnly = arguments[1]; jboolean publicOnly = arguments[1];
object table = classMethodTable(t, jclassVmClass(t, *c)); object table = getClassMethodTable(t, jclassVmClass(t, *c));
if (table) { if (table) {
PROTECT(t, table); PROTECT(t, table);

View File

@ -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 void
parseInterfaceTable(Thread* t, Stream& s, object class_, object pool, parseInterfaceTable(Thread* t, Stream& s, object class_, object pool,
Machine::Type throwType) Machine::Type throwType)
@ -989,10 +1000,9 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool,
if (count) { if (count) {
table = makeArray(t, count); table = makeArray(t, count);
if (classAddendum(t, class_) == 0) {
object addendum = makeClassAddendum(t, pool, 0, 0, table, 0); object addendum = getClassAddendum(t, class_, pool);
set(t, class_, ClassAddendum, addendum); set(t, addendum, ClassAddendumInterfaceTable, table);
}
} }
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
@ -1644,6 +1654,10 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (abstractVirtuals) { if (abstractVirtuals) {
PROTECT(t, vtable); PROTECT(t, vtable);
object addendum = getClassAddendum(t, class_, pool);
set(t, addendum, ClassAddendumMethodTable,
classMethodTable(t, class_));
unsigned oldLength = arrayLength(t, classMethodTable(t, class_)); unsigned oldLength = arrayLength(t, classMethodTable(t, class_));
object newMethodTable = makeArray object newMethodTable = makeArray
(t, oldLength + listSize(t, abstractVirtuals)); (t, oldLength + listSize(t, abstractVirtuals));
@ -1707,9 +1721,6 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
PROTECT(t, class_); PROTECT(t, class_);
PROTECT(t, pool); PROTECT(t, pool);
object addendum = classAddendum(t, class_);
PROTECT(t, addendum);
unsigned attributeCount = s.read2(); unsigned attributeCount = s.read2();
for (unsigned j = 0; j < attributeCount; ++j) { for (unsigned j = 0; j < attributeCount; ++j) {
object name = singletonObject(t, pool, s.read2() - 1); 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<const int8_t*>("Signature"), } else if (vm::strcmp(reinterpret_cast<const int8_t*>("Signature"),
&byteArrayBody(t, name, 0)) == 0) &byteArrayBody(t, name, 0)) == 0)
{ {
if (addendum == 0) { object addendum = getClassAddendum(t, class_, pool);
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0);
}
set(t, addendum, AddendumSignature, set(t, addendum, AddendumSignature,
singletonObject(t, pool, s.read2() - 1)); singletonObject(t, pool, s.read2() - 1));
} else if (vm::strcmp(reinterpret_cast<const int8_t*>("InnerClasses"), } else if (vm::strcmp(reinterpret_cast<const int8_t*>("InnerClasses"),
&byteArrayBody(t, name, 0)) == 0) &byteArrayBody(t, name, 0)) == 0)
{ {
if (addendum == 0) {
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0);
}
unsigned innerClassCount = s.read2(); unsigned innerClassCount = s.read2();
object table = makeArray(t, innerClassCount); object table = makeArray(t, innerClassCount);
PROTECT(t, table); PROTECT(t, table);
@ -1754,25 +1758,22 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool)
set(t, table, ArrayBody + (i * BytesPerWord), reference); set(t, table, ArrayBody + (i * BytesPerWord), reference);
} }
object addendum = getClassAddendum(t, class_, pool);
set(t, addendum, ClassAddendumInnerClassTable, table); set(t, addendum, ClassAddendumInnerClassTable, table);
} else if (vm::strcmp(reinterpret_cast<const int8_t*> } else if (vm::strcmp(reinterpret_cast<const int8_t*>
("RuntimeVisibleAnnotations"), ("RuntimeVisibleAnnotations"),
&byteArrayBody(t, name, 0)) == 0) &byteArrayBody(t, name, 0)) == 0)
{ {
if (addendum == 0) {
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0);
}
object body = makeByteArray(t, length); object body = makeByteArray(t, length);
PROTECT(t, body);
s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), length); s.read(reinterpret_cast<uint8_t*>(&byteArrayBody(t, body, 0)), length);
object addendum = getClassAddendum(t, class_, pool);
set(t, addendum, AddendumAnnotationTable, body); set(t, addendum, AddendumAnnotationTable, body);
} else { } else {
s.skip(length); s.skip(length);
} }
} }
set(t, class_, ClassAddendum, addendum);
} }
void void