JNI: cannot access member of superclass via subclass

Godmar Back gback at cs.utah.edu
Tue May 25 12:35:59 PDT 1999


> 
> I want to access a member field of a Java object from within C code, using JNI.
> When this member field is declared in a superclass of the object, I get an 
> error. 

I see.  We only look in the class you pass in getFieldID, so we don't include
members in the superclass.  This is apparently wrong.

Note that we also don't do the right thing in pure Java code.
For example, consider this program:

	class A {
		static int x = 1;
	}
	class B extends A {
	}
	class C {
		public static void main(String []av) {
			System.out.println(B.x);
		}
	}

This program compiles and runs, but only because the compiler
replaced the reference to B.x with a reference to A.x!
To see this, delete A.class and create a file B.java like so:

	class B {
		static int x = 2;
	}

Running C will now fail with a NoSuchField error, despite the
fact that the programmer asked for a field in class B in C.java!

Well, I'm sure that the Java language freaks have found that out
already somewhere; in fact, I may just check the revised JLS to
see if that's pointed out somewhere.

I fixed Kaffe to look in all superclasses for fields for now,
this should fix both Java and your JNI problem. Update classMethod.c.

Let's explore this issue a bit further.  This is so screwed up
it's almost funny.

Suppose we compile this program first:

// testSupField.java
class A {
}
class B extends A {
    public static int x = 5;
}

public class testSupField {

    public static void main(String av[]) {
        try {
            System.out.println(B.x);
        } catch (Throwable o) {
            o.printStackTrace();
        }
        java.lang.reflect.Field []f = B.class.getFields();
        for (int i = 0; i < f.length; i++) {
            System.out.println(f[i].getName());
        }
    }
}

and then we compile this program:
// B.java
interface A {
        public static int x = 4;
}
public class B implements A {
}

Guess what the output of testSupField under JDK 1.1 and 1.2 is:

JDK 1.1.7 (Linux):
java.lang.NoSuchFieldError: B: field x not found
        at 
x

JDK 1.2 (Sun)
java.lang.NoSuchFieldError: B: field x not found
        at testSupField.main(Compiled Code)
x

Field x is not found in class B, yet it is reflected via getFields(). 

I should note that kaffe does not report fields declared in
interfaces in getFields().  In my assessment of bug vm/#17,
I thought this is a problem, but in light of the behavior shown
above (first throwing a NoSuchFieldError that the field isn't
found, then reporting it via getFields()), I am no longer so
sure whether we're wrong or whether Sun simply didn't think things
through.

> With the JDK, it works as expected. (It also goes wrong with a 
> non-private field.)
> 

What do you mean by "goes wrong with a non-private field"?

	- Godmar




More information about the kaffe mailing list