This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Invocation API (JNI) completely broken
- To: java at gcc dot gnu dot org
- Subject: Invocation API (JNI) completely broken
- From: Martin Kahlert <martin dot kahlert at infineon dot com>
- Date: Mon, 29 Oct 2001 15:11:35 +0100
- Reply-To: martin dot kahlert at infineon dot com
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.