8213907: [JVMCI] avoid Class.getDeclared* methods when converting JVMCI objects to reflection objects

Reviewed-by: kvn, never
This commit is contained in:
Doug Simon 2018-11-21 22:02:17 +01:00
parent 1a6b429e9a
commit 4512750fbe
12 changed files with 175 additions and 114 deletions

View file

@ -1498,6 +1498,38 @@ C2V_VMENTRY(void, compileToBytecode, (JNIEnv*, jobject, jobject lambda_form_hand
}
C2V_END
C2V_VMENTRY(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method))
methodHandle m = CompilerToVM::asMethod(jvmci_method);
oop executable;
if (m->is_initializer()) {
if (m->is_static_initializer()) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
"Cannot create java.lang.reflect.Method for class initializer");
}
executable = Reflection::new_constructor(m, CHECK_NULL);
} else {
executable = Reflection::new_method(m, false, CHECK_NULL);
}
return JNIHandles::make_local(thread, executable);
}
C2V_VMENTRY(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index))
Klass* klass = CompilerToVM::asKlass(jvmci_type);
if (!klass->is_instance_klass()) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Expected non-primitive type, got %s", klass->external_name()));
}
InstanceKlass* iklass = InstanceKlass::cast(klass);
Array<u2>* fields = iklass->fields();
if (index < 0 || index > fields->length()) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Field index %d out of bounds for %s", index, klass->external_name()));
}
fieldDescriptor fd(iklass, index);
oop reflected = Reflection::new_field(&fd, CHECK_NULL);
return JNIHandles::make_local(env, reflected);
}
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@ -1519,6 +1551,8 @@ C2V_END
#define HS_METADATA "Ljdk/vm/ci/hotspot/HotSpotMetaData;"
#define HS_STACK_FRAME_REF "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;"
#define HS_SPECULATION_LOG "Ljdk/vm/ci/hotspot/HotSpotSpeculationLog;"
#define REFLECTION_EXECUTABLE "Ljava/lang/reflect/Executable;"
#define REFLECTION_FIELD "Ljava/lang/reflect/Field;"
#define METASPACE_METHOD_DATA "J"
JNINativeMethod CompilerToVM::methods[] = {
@ -1586,6 +1620,8 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)},
{CC "compileToBytecode", CC "(" OBJECT ")V", FN_PTR(compileToBytecode)},
{CC "getFlagValue", CC "(" STRING ")" OBJECT, FN_PTR(getFlagValue)},
{CC "asReflectionExecutable", CC "(" HS_RESOLVED_METHOD ")" REFLECTION_EXECUTABLE, FN_PTR(asReflectionExecutable)},
{CC "asReflectionField", CC "(" HS_RESOLVED_KLASS "I)" REFLECTION_FIELD, FN_PTR(asReflectionField)},
};
int CompilerToVM::methods_count() {

View file

@ -91,6 +91,7 @@ class CompilerToVM {
static HeapWord** _heap_end_addr;
static HeapWord* volatile* _heap_top_addr;
static int _max_oop_map_stack_offset;
static int _fields_annotations_base_offset;
static jbyte* cardtable_start_address;
static int cardtable_shift;
@ -101,7 +102,6 @@ class CompilerToVM {
static int sizeof_ExceptionTableElement;
static int sizeof_LocalVariableTableElement;
static int sizeof_ConstantPool;
static int sizeof_SymbolPointer;
static int sizeof_narrowKlass;
static int sizeof_arrayOopDesc;
static int sizeof_BasicLock;

View file

@ -61,6 +61,7 @@ bool CompilerToVM::Data::_supports_inline_contig_alloc;
HeapWord** CompilerToVM::Data::_heap_end_addr;
HeapWord* volatile* CompilerToVM::Data::_heap_top_addr;
int CompilerToVM::Data::_max_oop_map_stack_offset;
int CompilerToVM::Data::_fields_annotations_base_offset;
jbyte* CompilerToVM::Data::cardtable_start_address;
int CompilerToVM::Data::cardtable_shift;
@ -71,7 +72,6 @@ int CompilerToVM::Data::sizeof_vtableEntry = sizeof(vtableEntry);
int CompilerToVM::Data::sizeof_ExceptionTableElement = sizeof(ExceptionTableElement);
int CompilerToVM::Data::sizeof_LocalVariableTableElement = sizeof(LocalVariableTableElement);
int CompilerToVM::Data::sizeof_ConstantPool = sizeof(ConstantPool);
int CompilerToVM::Data::sizeof_SymbolPointer = sizeof(Symbol*);
int CompilerToVM::Data::sizeof_narrowKlass = sizeof(narrowKlass);
int CompilerToVM::Data::sizeof_arrayOopDesc = sizeof(arrayOopDesc);
int CompilerToVM::Data::sizeof_BasicLock = sizeof(BasicLock);
@ -122,6 +122,8 @@ void CompilerToVM::Data::initialize(TRAPS) {
symbol_init = (address) vmSymbols::object_initializer_name();
symbol_clinit = (address) vmSymbols::class_initializer_name();
_fields_annotations_base_offset = Array<AnnotationArray*>::base_offset_in_bytes();
BarrierSet* bs = BarrierSet::barrier_set();
if (bs->is_a(BarrierSet::CardTableBarrierSet)) {
jbyte* base = ci_card_table_address();

View file

@ -76,6 +76,7 @@
static_field(CompilerToVM::Data, _heap_top_addr, HeapWord* volatile*) \
\
static_field(CompilerToVM::Data, _max_oop_map_stack_offset, int) \
static_field(CompilerToVM::Data, _fields_annotations_base_offset, int) \
\
static_field(CompilerToVM::Data, cardtable_start_address, jbyte*) \
static_field(CompilerToVM::Data, cardtable_shift, int) \
@ -86,7 +87,6 @@
static_field(CompilerToVM::Data, sizeof_ExceptionTableElement, int) \
static_field(CompilerToVM::Data, sizeof_LocalVariableTableElement, int) \
static_field(CompilerToVM::Data, sizeof_ConstantPool, int) \
static_field(CompilerToVM::Data, sizeof_SymbolPointer, int) \
static_field(CompilerToVM::Data, sizeof_narrowKlass, int) \
static_field(CompilerToVM::Data, sizeof_arrayOopDesc, int) \
static_field(CompilerToVM::Data, sizeof_BasicLock, int) \
@ -104,6 +104,8 @@
\
static_field(Abstract_VM_Version, _features, uint64_t) \
\
nonstatic_field(Annotations, _fields_annotations, Array<AnnotationArray*>*) \
\
nonstatic_field(Array<int>, _length, int) \
unchecked_nonstatic_field(Array<u1>, _data, sizeof(u1)) \
unchecked_nonstatic_field(Array<u2>, _data, sizeof(u2)) \
@ -164,6 +166,7 @@
nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
nonstatic_field(InstanceKlass, _init_state, u1) \
nonstatic_field(InstanceKlass, _misc_flags, u2) \
nonstatic_field(InstanceKlass, _annotations, Annotations*) \
\
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_sp, intptr_t*) \
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_pc, address) \
@ -462,6 +465,8 @@
declare_constant(ConstMethod::_has_linenumber_table) \
declare_constant(ConstMethod::_has_localvariable_table) \
declare_constant(ConstMethod::_has_exception_table) \
declare_constant(ConstMethod::_has_method_annotations) \
declare_constant(ConstMethod::_has_parameter_annotations) \
\
declare_constant(CounterData::count_off) \
\

View file

@ -42,6 +42,8 @@ typedef Array<u1> AnnotationArray;
// a type_annotation instance.
class Annotations: public MetaspaceObj {
friend class JVMCIVMStructs;
// If you add a new field that points to any metaspace object, you
// must add this field to Annotations::metaspace_pointers_do().

View file

@ -27,6 +27,7 @@ import static jdk.vm.ci.common.InitTimer.timer;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.InstalledCode;
@ -657,4 +658,17 @@ final class CompilerToVM {
* Gets the host class for {@code type}.
*/
native HotSpotResolvedObjectTypeImpl getHostClass(HotSpotResolvedObjectTypeImpl type);
/**
* Gets a {@link Executable} corresponding to {@code method}.
*/
native Executable asReflectionExecutable(HotSpotResolvedJavaMethodImpl method);
/**
* Gets a {@link Field} denoted by {@code holder} and {@code index}.
*
* @param holder the class in which the requested field is declared
* @param fieldIndex the {@code fieldDescriptor::index()} denoting the field
*/
native Field asReflectionField(HotSpotResolvedObjectTypeImpl holder, int fieldIndex);
}

View file

@ -22,11 +22,15 @@
*/
package jdk.vm.ci.hotspot;
import static jdk.internal.misc.Unsafe.ADDRESS_SIZE;
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers;
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaType;
@ -156,41 +160,65 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
return (config().jvmAccFieldStable & modifiers) != 0;
}
private boolean hasAnnotations() {
if (!isInternal()) {
HotSpotVMConfig config = config();
final long metaspaceAnnotations = UNSAFE.getAddress(holder.getMetaspaceKlass() + config.instanceKlassAnnotationsOffset);
if (metaspaceAnnotations != 0) {
long fieldsAnnotations = UNSAFE.getAddress(metaspaceAnnotations + config.annotationsFieldAnnotationsOffset);
if (fieldsAnnotations != 0) {
long fieldAnnotations = UNSAFE.getAddress(fieldsAnnotations + config.fieldsAnnotationsBaseOffset + (ADDRESS_SIZE * index));
return fieldAnnotations != 0;
}
}
}
return false;
}
@Override
public Annotation[] getAnnotations() {
Field javaField = toJava();
if (javaField != null) {
return javaField.getAnnotations();
if (!hasAnnotations()) {
return new Annotation[0];
}
return new Annotation[0];
return toJava().getAnnotations();
}
@Override
public Annotation[] getDeclaredAnnotations() {
Field javaField = toJava();
if (javaField != null) {
return javaField.getDeclaredAnnotations();
if (!hasAnnotations()) {
return new Annotation[0];
}
return new Annotation[0];
return toJava().getDeclaredAnnotations();
}
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Field javaField = toJava();
if (javaField != null) {
return javaField.getAnnotation(annotationClass);
if (!hasAnnotations()) {
return null;
}
return null;
return toJava().getAnnotation(annotationClass);
}
/**
* Gets a {@link Field} object corresponding to this object. This method always returns the same
* {@link Field} object for a given {@link HotSpotResolvedJavaFieldImpl}. This ensures
* {@link #getDeclaredAnnotations()}, {@link #getAnnotations()} and
* {@link #getAnnotation(Class)} are stable with respect to the identity of the
* {@link Annotation} objects they return.
*/
private Field toJava() {
if (isInternal()) {
return null;
}
try {
return holder.mirror().getDeclaredField(getName());
} catch (NoSuchFieldException e) {
return null;
synchronized (holder) {
HashMap<HotSpotResolvedJavaFieldImpl, Field> cache = holder.reflectionFieldCache;
if (cache == null) {
cache = new HashMap<>();
holder.reflectionFieldCache = cache;
}
Field reflect = cache.get(this);
if (reflect == null) {
reflect = compilerToVM().asReflectionField(holder, index);
cache.put(this, reflect);
}
return reflect;
}
}
}

View file

@ -33,10 +33,8 @@ import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -54,7 +52,6 @@ import jdk.vm.ci.meta.LocalVariableTable;
import jdk.vm.ci.meta.ProfilingInfo;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Signature;
import jdk.vm.ci.meta.SpeculationLog;
import jdk.vm.ci.meta.TriState;
@ -75,11 +72,9 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
private byte[] code;
/**
* Cache for {@link #toJava()}. Set to {@link #signature} when resolving reflection object fails
* due to reflection filtering (see {@code Reflection.fieldFilterMap} and
* {@code Reflection.methodFilterMap}).
* Cache for {@link #toJava()}.
*/
private Object toJavaCache;
private volatile Executable toJavaCache;
/**
* Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
@ -492,12 +487,10 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
@Override
public Parameter[] getParameters() {
Executable javaMethod = toJava();
if (javaMethod == null) {
return null;
if (signature.getParameterCount(false) == 0) {
return new ResolvedJavaMethod.Parameter[0];
}
java.lang.reflect.Parameter[] javaParameters = javaMethod.getParameters();
java.lang.reflect.Parameter[] javaParameters = toJava().getParameters();
Parameter[] res = new Parameter[javaParameters.length];
for (int i = 0; i < res.length; i++) {
java.lang.reflect.Parameter src = javaParameters[i];
@ -509,32 +502,34 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
@Override
public Annotation[][] getParameterAnnotations() {
Executable javaMethod = toJava();
return javaMethod == null ? new Annotation[signature.getParameterCount(false)][0] : javaMethod.getParameterAnnotations();
if ((getConstMethodFlags() & config().constMethodHasParameterAnnotations) == 0) {
return new Annotation[signature.getParameterCount(false)][0];
}
return toJava().getParameterAnnotations();
}
@Override
public Annotation[] getAnnotations() {
Executable javaMethod = toJava();
if (javaMethod != null) {
return javaMethod.getAnnotations();
if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
return new Annotation[0];
}
return new Annotation[0];
return toJava().getAnnotations();
}
@Override
public Annotation[] getDeclaredAnnotations() {
Executable javaMethod = toJava();
if (javaMethod != null) {
return javaMethod.getDeclaredAnnotations();
if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
return new Annotation[0];
}
return new Annotation[0];
return toJava().getDeclaredAnnotations();
}
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Executable javaMethod = toJava();
return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass);
if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
return null;
}
return toJava().getAnnotation(annotationClass);
}
@Override
@ -561,60 +556,22 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
@Override
public Type[] getGenericParameterTypes() {
Executable javaMethod = toJava();
return javaMethod == null ? null : javaMethod.getGenericParameterTypes();
}
public Class<?>[] signatureToTypes() {
Signature sig = getSignature();
int count = sig.getParameterCount(false);
Class<?>[] result = new Class<?>[count];
for (int i = 0; i < result.length; ++i) {
JavaType parameterType = sig.getParameterType(i, holder);
HotSpotResolvedJavaType resolvedParameterType = (HotSpotResolvedJavaType) parameterType.resolve(holder);
result[i] = resolvedParameterType.mirror();
if (isClassInitializer()) {
return new Type[0];
}
return result;
}
private static Method searchMethods(Method[] methods, String name, Class<?> returnType, Class<?>[] parameterTypes) {
for (Method m : methods) {
if (m.getName().equals(name) && returnType.equals(m.getReturnType()) && Arrays.equals(m.getParameterTypes(), parameterTypes)) {
return m;
}
}
return null;
return toJava().getGenericParameterTypes();
}
private Executable toJava() {
if (toJavaCache != null) {
if (toJavaCache == signature) {
return null;
}
return (Executable) toJavaCache;
}
Class<?>[] parameterTypes = signatureToTypes();
Class<?> returnType = ((HotSpotResolvedJavaType) getSignature().getReturnType(holder).resolve(holder)).mirror();
Executable result;
if (isConstructor()) {
try {
result = holder.mirror().getDeclaredConstructor(parameterTypes);
} catch (NoSuchMethodException e) {
toJavaCache = signature;
return null;
}
} else {
// Do not use Method.getDeclaredMethod() as it can return a bridge method
// when this.isBridge() is false and vice versa.
result = searchMethods(holder.mirror().getDeclaredMethods(), getName(), returnType, parameterTypes);
if (result == null) {
toJavaCache = signature;
return null;
if (toJavaCache == null) {
assert !isClassInitializer() : this;
synchronized (this) {
if (toJavaCache == null) {
toJavaCache = compilerToVM().asReflectionExecutable(this);
}
}
}
toJavaCache = result;
return result;
return toJavaCache;
}
@Override

View file

@ -33,6 +33,7 @@ import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.ByteOrder;
@ -74,6 +75,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
final HotSpotJVMCIMetaAccessContext context;
private HotSpotResolvedObjectType arrayOfType;
/**
* Managed exclusively by {@link HotSpotResolvedJavaFieldImpl#toJava}.
*/
HashMap<HotSpotResolvedJavaFieldImpl, Field> reflectionFieldCache;
/**
* Gets the JVMCI mirror for a {@link Class} object.
*

View file

@ -94,6 +94,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
final int instanceKlassAnnotationsOffset = getFieldOffset("InstanceKlass::_annotations", Integer.class, "Annotations*");
final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags", Integer.class, "u2");
final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
final int klassVtableLengthOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_length_offset", Integer.class, "int");
@ -102,6 +103,9 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
final int instanceKlassMiscIsUnsafeAnonymous = getConstant("InstanceKlass::_misc_is_unsafe_anonymous", Integer.class);
final int annotationsFieldAnnotationsOffset = getFieldOffset("Annotations::_fields_annotations", Integer.class, "Array<AnnotationArray*>*");
final int fieldsAnnotationsBaseOffset = getFieldValue("CompilerToVM::Data::_fields_annotations_base_offset", Integer.class, "int");
final int arrayU1LengthOffset = getFieldOffset("Array<int>::_length", Integer.class, "int");
final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
final int arrayU2DataOffset = getFieldOffset("Array<u2>::_data", Integer.class);
@ -195,6 +199,8 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int constMethodHasLineNumberTable = getConstant("ConstMethod::_has_linenumber_table", Integer.class);
final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_table", Integer.class);
final int constMethodHasMethodAnnotations = getConstant("ConstMethod::_has_method_annotations", Integer.class);
final int constMethodHasParameterAnnotations = getConstant("ConstMethod::_has_parameter_annotations", Integer.class);
final int constMethodHasExceptionTable = getConstant("ConstMethod::_has_exception_table", Integer.class);
final int exceptionTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_ExceptionTableElement", Integer.class, "int");
@ -244,8 +250,6 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int heapWordSize = getConstant("HeapWordSize", Integer.class);
final int symbolPointerSize = getFieldValue("CompilerToVM::Data::sizeof_SymbolPointer", Integer.class, "int");
final long vmSymbolsSymbols = getFieldAddress("vmSymbols::_symbols[0]", "Symbol*");
final int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", Integer.class);
final int vmSymbolsSIDLimit = getConstant("vmSymbols::SID_LIMIT", Integer.class);
@ -263,8 +267,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
String symbolAt(int index) {
HotSpotJVMCIRuntime runtime = runtime();
assert vmSymbolsFirstSID <= index && index < vmSymbolsSIDLimit : "index " + index + " is out of bounds";
assert symbolPointerSize == Unsafe.ADDRESS_SIZE : "the following address read is broken";
int offset = index * symbolPointerSize;
int offset = index * Unsafe.ADDRESS_SIZE;
return runtime.getCompilerToVM().getSymbol(UNSAFE.getAddress(vmSymbolsSymbols + offset));
}

View file

@ -142,16 +142,15 @@ public class TestResolvedJavaField extends FieldUniverse {
}
}
}
private static final String NON_EXISTENT_CLASS_NAME = "XXXXXXXXXXX";
static class TestClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(final String name) {
protected Class<?> findClass(final String name) throws ClassNotFoundException {
if (!name.equals(TypeWithUnresolvedFieldType.class.getName())) {
try {
return super.findClass(name);
} catch (ClassNotFoundException e) {
throw new AssertionError("unexpected: " + e);
}
return super.findClass(name);
}
// copy classfile to byte array
byte[] classData = null;
@ -176,7 +175,7 @@ public class TestResolvedJavaField extends FieldUniverse {
int index = -1;
while ((index = indexOf(classData, index + 1, "PrintStream")) != -1) {
replace(classData, index, "XXXXXXXXXXX");
replace(classData, index, NON_EXISTENT_CLASS_NAME);
}
Class<?> c = defineClass(null, classData, 0, classData.length);
@ -211,13 +210,14 @@ public class TestResolvedJavaField extends FieldUniverse {
* type of the field is not resolvable.
*/
@Test
public void testGetType() {
public void testGetType() throws ClassNotFoundException {
Class<?> c = new TestClassLoader().findClass(TypeWithUnresolvedFieldType.class.getName());
ResolvedJavaType type = metaAccess.lookupJavaType(c);
for (ResolvedJavaField field : type.getInstanceFields(false)) {
assertTrue(field.getName().equals("fieldWithUnresolvableType"));
field.getType();
field.toString();
field.getAnnotations();
}
}
}

View file

@ -855,17 +855,25 @@ public class TestResolvedJavaType extends TypeUniverse {
}
private static ResolvedJavaMethod getClassInitializer(Class<?> c) {
ResolvedJavaMethod clinit = metaAccess.lookupJavaType(c).getClassInitializer();
if (clinit != null) {
assertEquals(0, clinit.getAnnotations().length);
assertEquals(0, clinit.getDeclaredAnnotations().length);
}
return clinit;
}
@Test
public void getClassInitializerTest() {
assertNotNull(metaAccess.lookupJavaType(A.class).getClassInitializer());
assertNotNull(metaAccess.lookupJavaType(D.class).getClassInitializer());
assertNull(metaAccess.lookupJavaType(B.class).getClassInitializer());
assertNull(metaAccess.lookupJavaType(C.class).getClassInitializer());
assertNull(metaAccess.lookupJavaType(int.class).getClassInitializer());
assertNull(metaAccess.lookupJavaType(void.class).getClassInitializer());
assertNotNull(getClassInitializer(A.class));
assertNotNull(getClassInitializer(D.class));
assertNull(getClassInitializer(B.class));
assertNull(getClassInitializer(C.class));
assertNull(getClassInitializer(int.class));
assertNull(getClassInitializer(void.class));
for (Class<?> c : classes) {
ResolvedJavaType type = metaAccess.lookupJavaType(c);
type.getClassInitializer();
getClassInitializer(c);
}
}