I traced the current troubles to some reflection stuff in class.c, which was checked into Japhar on February 1! Has it really been that long since Classpath has worked with Japhar? At any rate, I have current Classpath and Japhar CVS working together with the attached patch. Basically, class.c was passing around a whole bunch of unnecessary fieldIDs and methodIDs, and they happened to be fields and methods that Classpath doesn't have. I have verified that Classpath and Blackdown JDK 1.1.7v3 can perform Hello World. The test in java.lang.reflect does not succeed with either Classpath or Blackdown, with or without the patch, so the best I can say is it's failing in the same way (finding a private field when it's only supposed to look for public ones). I investigated the Reflection problems, running ReflectionTest, and found and fixed one problem, and diagnosed another. The first problem, which I fixed, was that it was returning *any* field or method it found, rather than just public ones or just declared ones. The second problem appears to be with the ClazzFile itself, or at least my understanding of it: the static fields in the interfaces the class implements don't appear to have been copied to the ClazzFile. While debugging, I put in a few debugging statements into fill_field_array(), so that it printed out all the fields in the fields struct of the object. It came up with some weird results. This was the output of running Japhar ReflectionTest: Checking public members of class ReflectionTest --> Checking field c ...OK --> Checking field a ...Nope --> Checking field b ...OK --> Checking field d ...Nope --> Checking field class$LReflectionTest ...Nope --> Checking field class$LTestFailedException ...Nope --> Checking field class$Ljava$lang$RuntimeException ...Nope --> Checking field class$Ljava$lang$Exception ...Nope --> Checking field class$Ljava$lang$reflect$Member ...Nope --> Checking field class$LReflectionTest_D ...Nope --> Checking field class$Ljava$lang$String ...Nope --> Checking field class$LReflectionTest_B ...Nope --> Checking field class$Ljava$lang$Object ...Nope --> Checking field class$Ljava$lang$Integer ...Nope --> Checking field class$Ljava$lang$Long ...Nope --> Checking field class$Ljava$lang$Double ...Nope --> Checking field A_a ...Nope --> Checking field A_b ...OK It turns out that, first, static fields in the interface are not copied into the fields structure (can't tell whether it's because they're static or in an interface), and second, a bunch of Classes *are*. It is my suspicion that whatever thing is trying to copy the static (or interface) field ends up copying something else, but I am not sure of that. I have included two different diffs; in case you don't like the second fix, you can selectively apply the first one that makes Classpath work. The diffs are cumulative. --John
Index: class.c =================================================================== RCS file: /cvsroot/hungry/java/japhar/lib/libnative/java.lang/class.c,v retrieving revision 1.64 diff -u -r1.64 class.c --- class.c 1999/10/25 07:10:17 1.64 +++ class.c 1999/12/18 19:22:28 @@ -43,24 +43,6 @@ jfieldID Member_DECLARED; jfieldID Member_PUBLIC; -jfieldID Field_slot; -jfieldID Field_type; -jfieldID Field_name; -jfieldID Field_clazz; -jmethodID Field_ctor; - -jfieldID Method_slot; -jfieldID Method_name; -jfieldID Method_clazz; -jfieldID Method_returnType; -jfieldID Method_parameterTypes; -jfieldID Method_exceptionTypes; -jmethodID Method_ctor; - -jfieldID Constructor_slot; -jfieldID Constructor_clazz; -jmethodID Constructor_ctor; - jint MEMBER_PUBLIC; jint MEMBER_DECLARED; @@ -80,24 +62,6 @@ Member_PUBLIC = (*env)->GetStaticFieldID(env, jlrMember, "PUBLIC", "I"); MEMBER_DECLARED = (*env)->GetStaticIntField(env, jlrMember, Member_DECLARED); MEMBER_PUBLIC = (*env)->GetStaticIntField(env, jlrMember, Member_PUBLIC); - - Field_slot = (*env)->GetFieldID(env, jlrField, "slot", "I"); - Field_type = (*env)->GetFieldID(env, jlrField, "type", "Ljava/lang/Class;"); - Field_name = (*env)->GetFieldID(env, jlrField, "name", "Ljava/lang/String;"); - Field_clazz = (*env)->GetFieldID(env, jlrField, "clazz", "Ljava/lang/Class;"); - Field_ctor = (*env)->GetMethodID(env, jlrField, "<init>", "()V"); - - Method_clazz = (*env)->GetFieldID(env, jlrMethod, "clazz", "Ljava/lang/Class;"); - Method_slot = (*env)->GetFieldID(env, jlrMethod, "slot", "I"); - Method_name = (*env)->GetFieldID(env, jlrMethod, "name", "Ljava/lang/String;"); - Method_returnType = (*env)->GetFieldID(env, jlrMethod, "returnType", "Ljava/lang/Class;"); - Method_parameterTypes = (*env)->GetFieldID(env, jlrMethod, "parameterTypes", "[Ljava/lang/Class;"); - Method_exceptionTypes = (*env)->GetFieldID(env, jlrMethod, "exceptionTypes", "[Ljava/lang/Class;"); - Method_ctor = (*env)->GetMethodID(env, jlrMethod, "<init>", "()V"); - - Constructor_clazz = (*env)->GetFieldID(env, jlrConstructor, "clazz", "Ljava/lang/Class;"); - Constructor_slot = (*env)->GetFieldID(env, jlrConstructor, "slot", "I"); - Constructor_ctor = (*env)->GetMethodID(env, jlrConstructor, "<init>", "()V"); } JNIEXPORT jobject JNICALL @@ -689,9 +653,7 @@ static int fill_method_array(JNIEnv *env, ClazzFile *orig_clazz, ClazzFile *clazz, jboolean only_declared, jclass class_class, - jclass method_class, jmethodID method_ctor, jfieldID clazz_field, - jfieldID slot_field, jfieldID name_field, jfieldID returnType_field, - jfieldID parameterTypes_field, jfieldID exceptionTypes_field, + jclass method_class, jobjectArray array, int methodnum, jboolean constructors) { HungryEnv *henv = HVM_ThreadGetEnv(); @@ -736,9 +698,7 @@ { methodnum = fill_method_array(env, orig_clazz, clazz->interface_tuples[i].interface, - only_declared, class_class, method_class, method_ctor, - clazz_field, slot_field, name_field, returnType_field, - parameterTypes_field, exceptionTypes_field, + only_declared, class_class, method_class, array, methodnum, constructors); } } @@ -766,9 +726,7 @@ array = (*env)->NewObjectArray(env, nmethods, jlrMethod, NULL); fill_method_array(env, clazz, clazz, only_declared, jlClass, - jlrMethod, Method_ctor, Method_clazz, Method_slot, Method_name, - Method_returnType, Method_parameterTypes, Method_exceptionTypes, - array, 0, JNI_FALSE); + jlrMethod, array, 0, JNI_FALSE); return array; } @@ -813,9 +771,7 @@ array = (*env)->NewObjectArray(env, nmethods, jlrConstructor, NULL); fill_method_array(env, clazz, clazz, only_declared, jlClass, - jlrConstructor, Constructor_ctor, Constructor_clazz, - Constructor_slot, NULL, NULL, Method_parameterTypes, - Method_exceptionTypes, + jlrConstructor, array, 0, JNI_TRUE); return array; } @@ -928,10 +884,8 @@ static jobject find_method(JNIEnv *env, ClazzFile *clazz, jboolean only_declared, - jclass class_class, jclass method_class, jfieldID clazz_field, - jfieldID slot_field, jfieldID name_field, jfieldID returnType_field, - jfieldID parameterTypes_field, jfieldID exceptionTypes_field, - jmethodID method_ctor, const char *name, jobjectArray parameterTypes, + jclass class_class, jclass method_class, + const char *name, jobjectArray parameterTypes, jboolean constructor) { HungryEnv *henv = HVM_ThreadGetEnv(); @@ -978,9 +932,7 @@ { method = find_method(env, clazz->interface_tuples[i].interface, only_declared, class_class, method_class, - clazz_field, slot_field, name_field, returnType_field, - parameterTypes_field, exceptionTypes_field, - method_ctor, name, parameterTypes, constructor); + name, parameterTypes, constructor); if (method != NULL) { return method; @@ -993,9 +945,8 @@ if (superClass != NULL) { method = find_method(env, superClass, only_declared, - class_class, method_class, clazz_field, slot_field, - name_field, returnType_field, parameterTypes_field, - exceptionTypes_field, method_ctor, name, parameterTypes, + class_class, method_class, + name, parameterTypes, constructor); if (method != NULL) { @@ -1024,9 +975,7 @@ only_declared = (which == MEMBER_DECLARED); method = find_method(env, clazz, only_declared, - jlClass, jlrMethod, Method_clazz, Method_slot, Method_name, - Method_returnType, Method_parameterTypes, Method_exceptionTypes, - Method_ctor, name, parameterTypes, JNI_FALSE); + jlClass, jlrMethod, name, parameterTypes, JNI_FALSE); if (method == NULL) { @@ -1080,9 +1029,7 @@ only_declared = (which == MEMBER_DECLARED); method = find_method(env, clazz, only_declared, - jlClass, jlrConstructor, Constructor_clazz, - Constructor_slot, NULL, NULL, Method_parameterTypes, - Method_exceptionTypes, Constructor_ctor, NULL, + jlClass, jlrConstructor, NULL, parameterTypes, JNI_TRUE); if (method == NULL)
--- class.c.new Sat Dec 18 12:07:50 1999 +++ class.c Sat Dec 18 14:03:58 1999 @@ -424,19 +424,34 @@ } /** - * Determine if the given field or method flag matches the - * only_declared value that is being searched. + * Determine if the given method should be seen + * based on whether the user is asking for public + * or declared */ static jboolean -access_is_ok(int field_flags, jboolean only_declared) +method_access_ok(MethodStruct * m, jint which, ClazzFile * clazz) { + return (which == MEMBER_DECLARED && m->clazz == clazz) + || (which == MEMBER_PUBLIC && (m->access_flags & ACC_PUBLIC)); +} + +/** + * Determine if the given field should be seen + * based on whether the user is asking for public + * or declared + */ +static jboolean +field_access_ok(FieldStruct * f, jint which, ClazzFile * clazz) +{ + return (which == MEMBER_DECLARED && f->clazz == clazz) + || (which == MEMBER_PUBLIC && (f->access_flags & ACC_PUBLIC)); } /** * Counts the number of fields in the specified - * class. If only_declared is JNI_FALSE, then all public fields + * class. If which is MEMBER_PUBLIC, then all public fields * are counted including those inherited from super classes/interfaces. - * If only_declared is JNI_TRUE, then all fields in the + * If which is MEMBER_DECLARED, then all fields in the * specified class are counted (without counting super * classes/interfaces). */ @@ -447,11 +462,11 @@ int i; for (i = 0; i < clazz->num_fields; ++i) { - if ((which == MEMBER_DECLARED && clazz->fields[i]->clazz == clazz) - || (which == MEMBER_PUBLIC && clazz->fields[i]->access_flags & ACC_PUBLIC)) + if (field_access_ok(clazz->fields[i], which, clazz)) { ++nflds; } + } return nflds; } @@ -466,12 +481,11 @@ for (i = 0; i < clazz->num_fields; ++i) { - if ((which == MEMBER_DECLARED && clazz->fields[i]->clazz == clazz) - || (which == MEMBER_PUBLIC && clazz->fields[i]->access_flags & ACC_PUBLIC)) + if (field_access_ok(clazz->fields[i], which, clazz)) { jobject field = (*env)->ToReflectedField(env, clazzfile_to_jclass(henv, clazz), clazz->fields[i]); (*env)->SetObjectArrayElement(env, array, fldnum++, field); - } + } } } @@ -593,9 +607,9 @@ /** * Counts the number of methods (when constructors == JNI_FALSE) or * constructors (when constructors == JNI_TRUE) in the specified - * class. If only_declared is JNI_FALSE, then all public methods + * class. If which is MEMEBER_PUBLIC, then all public methods * are counted including those inherited from super classes/interfaces - * If only_declared is JNI_TRUE, then all methods in the + * If which is MEMBER_DECLARED, then all methods in the * specified class are counted (without counting super * classes/interfaces). */ @@ -638,8 +652,7 @@ } } - if (((which == MEMBER_DECLARED && clazz->methods[i].clazz == clazz) - || (which == MEMBER_PUBLIC && clazz->methods[i].access_flags & ACC_PUBLIC)) + if (method_access_ok(&clazz->methods[i], which, clazz) && (constructors || !overridden(env, orig_clazz, clazz->methods[i].name, clazz->methods[i].sig_str, clazz))) @@ -652,7 +665,7 @@ static int fill_method_array(JNIEnv *env, ClazzFile *orig_clazz, ClazzFile *clazz, - jboolean only_declared, jclass class_class, + jint which, jclass class_class, jclass method_class, jobjectArray array, int methodnum, jboolean constructors) { @@ -661,7 +674,7 @@ for (i = 0; i < clazz->num_methods; ++i) { - if (only_declared && clazz->methods[i].clazz != clazz) + if (which == MEMBER_DECLARED && clazz->methods[i].clazz != clazz) continue; if (isConstructor(&clazz->methods[i])) @@ -679,7 +692,7 @@ } } - if (access_is_ok(clazz->methods[i].access_flags, only_declared) && + if (method_access_ok(&clazz->methods[i], which, clazz) && (constructors || !overridden(env, orig_clazz, clazz->methods[i].name, clazz->methods[i].sig_str, clazz))) { @@ -690,7 +703,7 @@ } } - if (!only_declared && !constructors) + if (which == MEMBER_PUBLIC && !constructors) { if (clazz->access_flags & ACC_INTERFACE) { @@ -698,7 +711,7 @@ { methodnum = fill_method_array(env, orig_clazz, clazz->interface_tuples[i].interface, - only_declared, class_class, method_class, + which, class_class, method_class, array, methodnum, constructors); } } @@ -712,20 +725,18 @@ jint which) { HungryEnv *henv = HVM_ThreadGetEnv(); - jboolean only_declared; ClazzFile *clazz = jclass_to_clazzfile(henv, obj); jobjectArray array; int nmethods; initids(env); - only_declared = (which == MEMBER_DECLARED); - nmethods = countMethods(env, clazz, clazz, only_declared, + nmethods = countMethods(env, clazz, clazz, which, JNI_FALSE); array = (*env)->NewObjectArray(env, nmethods, jlrMethod, NULL); - fill_method_array(env, clazz, clazz, only_declared, jlClass, + fill_method_array(env, clazz, clazz, which, jlClass, jlrMethod, array, 0, JNI_FALSE); return array; } @@ -756,21 +767,18 @@ jint which) { HungryEnv *henv = HVM_ThreadGetEnv(); - jboolean only_declared; ClazzFile *clazz = jclass_to_clazzfile(henv, obj); jobjectArray array; int nmethods; initids(env); - only_declared = (which == MEMBER_DECLARED); - - nmethods = countMethods(env, clazz, clazz, only_declared, + nmethods = countMethods(env, clazz, clazz, which, JNI_TRUE); array = (*env)->NewObjectArray(env, nmethods, jlrConstructor, NULL); - fill_method_array(env, clazz, clazz, only_declared, jlClass, + fill_method_array(env, clazz, clazz, which, jlClass, jlrConstructor, array, 0, JNI_TRUE); return array; @@ -798,7 +806,7 @@ static jobject find_field(JNIEnv *env, ClazzFile *clazz, - jboolean only_declared, const char *name) + jint which, const char *name) { HungryEnv *henv = HVM_ThreadGetEnv(); int i; @@ -806,7 +814,7 @@ for (i = 0; i < clazz->num_fields; ++i) { - if (access_is_ok(clazz->fields[i]->access_flags, only_declared) && + if (field_access_ok(clazz->fields[i], which, clazz) && !strcmp(clazz->fields[i]->name, name)) { return (*env)->ToReflectedField(env, clazzfile_to_jclass(henv, clazz), @@ -814,12 +822,12 @@ } } - if (!only_declared) + if (!(which==MEMBER_DECLARED)) { ClazzFile *superClass = getSuperClass(henv, clazz); if (superClass != NULL) { - field = find_field(env, superClass, only_declared, name); + field = find_field(env, superClass, which, name); if (field != NULL) { return field; @@ -828,7 +836,7 @@ for (i = 0; i < clazz->num_interfaces; ++i) { field = find_field(env, clazz->interface_tuples[i].interface, - only_declared, name); + which, name); if (field != NULL) { return field; @@ -845,16 +853,13 @@ jint which) { HungryEnv *henv = HVM_ThreadGetEnv(); - jboolean only_declared; ClazzFile *clazz = jclass_to_clazzfile(henv, cls); char *name = HVM_StringToCString(henv, jname); jobject field; initids(env); - only_declared = (which == MEMBER_DECLARED); - - field = find_field(env, clazz, only_declared, name); + field = find_field(env, clazz, which, name); if (field == NULL) { @@ -883,7 +888,7 @@ } static jobject -find_method(JNIEnv *env, ClazzFile *clazz, jboolean only_declared, +find_method(JNIEnv *env, ClazzFile *clazz, jint which, jclass class_class, jclass method_class, const char *name, jobjectArray parameterTypes, jboolean constructor) @@ -913,7 +918,7 @@ sig = HVM_SigParseFromJavaSig(henv, clazz->methods[i].sig_str); - if (access_is_ok(clazz->methods[i].access_flags, only_declared) && + if (method_access_ok(&clazz->methods[i], which, clazz) && params_match(env, parameterTypes, &sig->method)) { @@ -924,14 +929,14 @@ HVM_SigFree(henv, sig); } - if (!only_declared && !constructor) + if (which == MEMBER_PUBLIC && !constructor) { if (clazz->access_flags & ACC_INTERFACE) { for (i = 0; i < clazz->num_interfaces; ++i) { method = find_method(env, clazz->interface_tuples[i].interface, - only_declared, class_class, method_class, + which, class_class, method_class, name, parameterTypes, constructor); if (method != NULL) { @@ -944,7 +949,7 @@ ClazzFile *superClass = getSuperClass(henv, clazz); if (superClass != NULL) { - method = find_method(env, superClass, only_declared, + method = find_method(env, superClass, which, class_class, method_class, name, parameterTypes, constructor); @@ -966,15 +971,13 @@ jint which) { HungryEnv *henv = HVM_ThreadGetEnv(); - jboolean only_declared; ClazzFile *clazz = jclass_to_clazzfile(henv, cls); char *name = HVM_StringToCString(henv, jname); jobject method; initids(env); - only_declared = (which == MEMBER_DECLARED); - method = find_method(env, clazz, only_declared, + method = find_method(env, clazz, which, jlClass, jlrMethod, name, parameterTypes, JNI_FALSE); if (method == NULL) @@ -1020,15 +1023,13 @@ jint which) { HungryEnv *henv = HVM_ThreadGetEnv(); - jboolean only_declared; ClazzFile *clazz = jclass_to_clazzfile(henv, cls); jobject method; initids(env); - only_declared = (which == MEMBER_DECLARED); - method = find_method(env, clazz, only_declared, + method = find_method(env, clazz, which, jlClass, jlrConstructor, NULL, parameterTypes, JNI_TRUE);