Java requires that each class be automatically initialized at the time
of the first active use. Initializing a class involves
initializing the static fields, running code in class initializer
methods, and initializing base classes. There may also be
some implementation specific actions, such as allocating
String
objects corresponding to string literals in
the code.
The GCJ compiler inserts calls to JvInitClass
at appropriate
places to ensure that a class is initialized when required. The C++
compiler does not insert these calls automatically--it is the
programmer's responsibility to make sure classes are initialized.
However, this is fairly painless because of the conventions assumed by
the Java system.
First, libgcj
will make sure a class is initialized
before an instance of that object is created. This is one
of the responsibilities of the new
operation. This is
taken care of both in Java code, and in C++ code. (When the G++
compiler sees a new
of a Java class, it will call
a routine in libgcj
to allocate the object, and that
routine will take care of initializing the class.) It follows that you can
access an instance field, or call an instance (non-static)
method and be safe in the knowledge that the class and all
of its base classes have been initialized.
Invoking a static method is also safe. This is because the
Java compiler adds code to the start of a static method to make sure
the class is initialized. However, the C++ compiler does not
add this extra code. Hence, if you write a native static method
using CNI, you are responsible for calling JvInitClass
before doing anything else in the method (unless you are sure
it is safe to leave it out).
Accessing a static field also requires the class of the
field to be initialized. The Java compiler will generate code
to call Jv_InitClass
before getting or setting the field.
However, the C++ compiler will not generate this extra code,
so it is your responsibility to make sure the class is
initialized before you access a static field from C++.