Name: rlT66838 Date: 05/20/2000
java version "1.2.2"
Java HotSpot(TM) Server VM (2.0fcs, mixed mode, build E)
Create a program that uses the JNI invocation interface to create a Java VM.
Have the program:
1) Instantiate a custom classloader
2) Call the custom loader's loadClass with resolve=true to load a class that
has a static initializer and some static method.
3) Get the method ID of the static method
4) Try calling the static method
With the classic 1.2.2 VM the static initializer of the loaded class gets run
during this sequence. With the HotSpot VM the static initializer never runs.
Both the classic and HotSpot VMs appear to defer class initialization until
active use. I was a little surprised by this since my custom loader is calling
the resolve function, and I expected this to run static initializers in the
class. The classic VM runs class initialization upon active use of the class.
In this case, that is the GetStaticMethodID JNI function. I verified that
GetMethodID, GetFieldID and GetStaticFieldID also trigger class
initialization. In the HotSpot VM I tried all four of these JNI functions
without ever seeing the static initializer run. I also tried creating an
instance of the object (JNI NewObject) with the HotSpot VM and still did not
see the static initializer run.
The sample code is somewhat contrived so that I could make it as simple as
possible, but still show the bug.
------------------------------------------------
CLASSLOADER:
------------------------------------------------
import java.io.*;
public class MyLoader extends ClassLoader
{
File f;
private byte[] loadClassData( String name )
{
byte[] bData = null;
String sFileName = name.replace('.', '/') + ".class";
FileInputStream in;
int nBytesRead = 0;
try
{
f = new File(sFileName);
bData = new byte[(int)f.length()];
in = new FileInputStream(f);
nBytesRead = in.read(bData);
in.close();
}
catch(Exception e)
{
//System.out.println(e);
bData = null;
}
return bData;
}
protected Class loadClass(String name, boolean resolve) throws
ClassNotFoundException
{
// if the name is one of our own class
System.out.println("loadClass: " + name + " resolve: " + resolve);
Class cl = findLoadedClass(name);
if (cl == null)
{
try
{
byte[] data = loadClassData(name);
if (data == null)
{
cl = findSystemClass(name);
if (cl != null)
{
if (resolve)
resolveClass(cl);
}
return cl;
}
cl = defineClass(name, data, 0, data.length);
if (resolve)
resolveClass(cl);
}
catch(Exception e)
{
}
}
return cl;
}
}
--------------------------
Target Class
---------------------------
public class StatTest
{
static
{
System.out.println("In STATIC INITIALIZER");
System.out.flush();
}
public static boolean m_z = true;
public boolean mx_z = true;
public StatTest()
{
System.out.println("In Constructor");
}
public static void doit()
{
System.out.println("In DOIT");
System.out.flush();
}
}
-----------------------
JNI Test Program
-----------------------
#include <stdio.h>
#include <stdlib.h>
#include "jni.h"
char * Option0 = "-
Djava.class.path=.;e:\\rel50obj\\release.nt\\som";
JavaVMInitArgs initargs;
JavaVM * vm;
JNIEnv * env;
JavaVMOption options[1];
int main(int argc, char * argv[])
{
int retval = 0;
jclass loaderclass;
initargs.version = JNI_VERSION_1_2;
retval = JNI_GetDefaultJavaVMInitArgs(&initargs);
if (retval != 0)
{
printf("Error: DefaultInitArgs returns: %d\n", retval);
return (-1);
}
options[0].optionString = Option0;
initargs.ignoreUnrecognized = JNI_TRUE;
initargs.options = options;
initargs.nOptions = 1;
retval = JNI_CreateJavaVM(&vm, &env, (void *)(&initargs));
if (retval != 0)
{
printf("Error: CreateVM returns: %d\n", retval);
return (-1);
}
loaderclass = (*env)->FindClass(env, "MyLoader");
if (loaderclass)
{
jmethodID lmid;
jobject loader;
lmid = (*env)->GetMethodID(env, loaderclass, "<init>", "()V");
loader = (*env)->NewObject(env, loaderclass, lmid);
if (loader)
{
jmethodID lcMid;
jstring classname;
jobject retval;
classname = (*env)->NewStringUTF(env, "StatTest");
// Call loadClass("StatTest", true)
lcMid = (*env)->GetMethodID(env,
loaderclass, "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;");
retval = (*env)->CallObjectMethod(env, loader, lcMid,
classname, JNI_TRUE);
if (retval)
{
jmethodID mid;
printf("Got StatTest class instance.\n");
mid = (*env)->GetStaticMethodID(env,
retval, "doit", "()V");
printf("Call doit()\n");
(*env)->CallStaticVoidMethod(env, retval, mid);
printf("Finish call to doit()\n");
}
else
{
printf("loadClass failed\n");
}
}
else
{
printf("Could not instantiate classloader, MyLoader\n");
}
}
else
{
printf("Could not find custom classloader, MyLoader\n");
}
(*vm)->DestroyJavaVM(vm);
return 0;
}
(Review ID: 104751)
======================================================================