Implement Class#getDeclaredClasses

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin 2013-10-31 17:01:33 -05:00
parent efb3ef9b51
commit dba8d39e63
5 changed files with 63 additions and 6 deletions

View File

@ -12,7 +12,7 @@ package avian;
public class ClassAddendum extends Addendum {
public Object[] interfaceTable;
public Object[] innerClassTable;
public InnerClassReference[] innerClassTable;
public Object[] methodTable;
public Object enclosingClass;
public Object enclosingMethod;

View File

@ -0,0 +1,18 @@
/* Copyright (c) 2008-2013, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
package avian;
public class InnerClassReference {
public byte[] inner;
public byte[] outer;
public byte[] name;
public short flags;
}

View File

@ -15,6 +15,7 @@ import avian.ClassAddendum;
import avian.AnnotationInvocationHandler;
import avian.SystemClassLoader;
import avian.Classes;
import avian.InnerClassReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@ -402,6 +403,37 @@ public final class Class <T> implements Type, AnnotatedElement {
}
}
public Class[] getDeclaredClasses() {
if (vmClass.addendum == null || vmClass.addendum.innerClassTable == null) {
return new Class[0];
}
InnerClassReference[] table = vmClass.addendum.innerClassTable;
Class[] result = new Class[table.length];
int counter = 0;
String prefix = getName().replace('.', '/') + "$";
for (int i = 0; i < table.length; ++i) try {
byte[] inner = table[i].inner;
if (inner != null && inner.length > 1) {
String name = new String(inner, 0, inner.length - 1);
if (name.startsWith(prefix)) {
Class innerClass = getClassLoader().loadClass(name);
result[counter++] = innerClass;
}
}
} catch (ClassNotFoundException e) {
throw new Error(e);
}
if (counter == result.length) {
return result;
}
if (counter == 0) {
return new Class[0];
}
Class[] result2 = new Class[counter];
System.arraycopy(result, 0, result2, 0, counter);
return result2;
}
public ClassLoader getClassLoader() {
return vmClass.loader;
}

View File

@ -156,11 +156,7 @@
(void* value)
(object next))
(type innerClassReference
(object inner)
(object outer)
(object name)
(int16_t flags))
(type innerClassReference avian/InnerClassReference)
(type continuationContext
(object next)

View File

@ -38,7 +38,18 @@ public class Reflection {
if (! v) throw new RuntimeException();
}
private static class Hello { }
private static void innerClasses() throws Exception {
Class c = Reflection.class;
Class[] inner = c.getDeclaredClasses();
expect(1 == inner.length);
expect(Hello.class == inner[0]);
}
public static void main(String[] args) throws Exception {
innerClasses();
Class system = Class.forName("java.lang.System");
Field out = system.getDeclaredField("out");
Class output = Class.forName("java.io.PrintStream");