Objects and Classes

Classes

All Java classes are derived from java.lang.Object. C++ does not have a unique “root”class, but we use a C++ java::lang::Object as the C++ version of the java.lang.Object Java class. All other Java classes are mapped into corresponding C++ classes derived from java::lang::Object.

Interface inheritance (the “implements” keyword) is currently not reflected in the C++ mapping.

Object references

We implement a Java object reference as a pointer to the start of the referenced object. It maps to a C++ pointer. (We cannot use C++ references for Java references, since once a C++ reference has been initialized, you cannot change it to point to another object.) The null Java reference maps to the NULL C++ pointer.

Note that in some Java implementations an object reference is implemented as a pointer to a two-word “handle”. One word of the handle points to the fields of the object, while the other points to a method table. Gcj does not use this extra indirection.

Object fields

Each object contains an object header, followed by the instance fields of the class, in order. The object header consists of a single pointer to a dispatch or virtual function table. (There may be extra fields “in front of” the object, for example for memory management, but this is invisible to the application, and the reference to the object points to the dispatch table pointer.)

The fields are laid out in the same order, alignment, and size as in C++. Specifically, 8-bite and 16-bit native types (byte, short, char, and boolean) are not widened to 32 bits. Note that the Java VM does extend 8-bit and 16-bit types to 32 bits when on the VM stack or temporary registers.

If you include the gcjh-generated header for a class, you can access fields of Java classes in the “natural” way. Given the following Java class:

public class Int
{
  public int i;
  public Integer (int i) { this.i = i; }
  public static zero = new Integer(0);
}
you can write:
#include <gcj/cni.h>
#include <Int.h>
Int*
mult (Int *p, jint k)
{
  if (k == 0)
    return Int::zero;  // static member access.
  return new Int(p->i * k);
}

CNI does not strictly enforce the Java access specifiers, because Java permissions cannot be directly mapped into C++ permission. Private Java fields and methods are mapped to private C++ fields and methods, but other fields and methods are mapped to public fields and methods.