Invocation API (JNI) completely broken

Martin Kahlert martin.kahlert@infineon.com
Mon Oct 29 06:11:00 GMT 2001


Hi!
Once upon a time JNI worked for me in 3.1.
Testcase:
#include <jni.h>
#include <stdio.h>
#define PATH_SEPARATOR ':'
#define USER_CLASSPATH "." /* where Prog.class is */
int main()
{
 JNIEnv *env;
 JavaVM *jvm;
 JavaVMInitArgs vm_args;
 jint res;
 jclass cls;
 jmethodID mid;
 jstring jstr;
 jobjectArray args;
 char classpath[1024];
 vm_args.version = JNI_VERSION_1_2;
 JNI_GetDefaultJavaVMInitArgs(&vm_args);
 /* Create the Java VM */
 res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
 if (res < 0)
 {
 fprintf(stderr, "Can't create Java VM\n");
 exit(1);
 }
 cls = (*env)->FindClass(env, "hello");
 if (cls == 0) {
 fprintf(stderr, "Can't find hello class\n");
 exit(1);
 }
 mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
 if (mid == 0) {
 fprintf(stderr, "Can't find Prog.main\n");
 exit(1);
 }
 jstr = (*env)->NewStringUTF(env, " from C!");
 if (jstr == 0) {
 fprintf(stderr, "Out of memory\n");
 exit(1);
 }
 args = (*env)->NewObjectArray(env, 1, 
 (*env)->FindClass(env, "java/lang/String"), jstr);
 if (args == 0) {
 fprintf(stderr, "Out of memory\n");
 exit(1);
 }
 (*env)->CallStaticVoidMethod(env, cls, mid, args);
 (*jvm)->DestroyJavaVM(jvm);
}
Now it bombs over and over:
The first problem was
clinit_name = init_name = finit_name == NULL
I assume that got in with this change:
2001年10月16日 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
 * name-finder.cc (_Jv_name_finder::lookup): Check for NULL dli_sname.
 
 Eliminate use of C++ static constructors. 
 * interpret.cc: Remove static Utf8Consts. Use namespace gcj.
 * jni.cc: Likewise. 
 * resolve.cc: Likewise.
 * defineclass.cc: Likewise.
 (_Jv_ClassReader::handleClassBegin): Synchronize call to 
 _Jv_RegisterClass.
 * include/jvm.h (void_signature, clinit_name, init_name, finit_name):
 Declare in namespace gcj.
 * java/lang/Class.h (Class): Remove initialization for primitive
 types.
 (friend void _Jv_InitPrimClass): This is in prims.cc.
 * prims.cc (_Jv_InitPrimClass): Do primitive type initialization
 here instead.
 (void_signature, clinit_name, init_name, finit_name): Define in
 namespace gcj.
 (_Jv_CreateJavaVM): Call _Jv_InitThreads, _Jv_InitGC, and
 _Jv_InitializeSyncMutex from here. Initialize Utf8 constants. 
 Initialize primitive types.
 * java/lang/natClassLoader.cc (_Jv_RegisterClasses): Don't call
 initialization routines. Don't synchronize.
 * java/lang/natRuntime.cc (_load): Synchronize on java.lang.Class
 across dlopen call.
I tried to correct that with 
clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
init_name = _Jv_makeUtf8Const ("<init>", 6);
finit_name = _Jv_makeUtf8Const ("finit$", 6);
before the call to _Jv_JNI_AttachCurrentThread in JNI_CreateJavaVM (jni.cc).
(i copied these lines from prims.cc).
Then the garbage collector bombed from deeply inside _Jv_makeUtf8Const. So i
inserted an _Jv_InitGC() before these lines - cannot heart i assume.
Then the thread creator bombed and i added a _Jv_InitThread() before that.
And because i wanted to avoid another compilation i added the
_Jv_InitializeSyncMutex () call too.
After that the JNI_CreateJavaVM() got through, but _Jv_NewPrimArray() bombs deeply
from inside _Jv_JNI_FindClass().
All that doesn't look good to me.
I am not that confident, that my 'fixes' are correct either, so i leave this
for the more knowledgable people as an exercise ;-)
Thanks for any help,
Martin.
-- 
The early bird catches the worm. If you want something else for 
breakfast, get up later.


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /