JNI 调用GetMethodID 获得System.out.println()方法的jmethodid时出错的问题。

症状如下:

作为练习,为了在C代码中调用java的System.out.println()方法,我写了如下代码。

java代码片段如下:
[size=xx-small]

public class JNI_JAVA {

public static native void println(String str); // 在C代码里打算调用System.out.println()。
public static void main(String[] args) {
    JNI_JAVA.println("Lady Gaga");
}

}
[/size]

生成如下头文件 JNI_JAVA.h 的片段:

[size=xx-small]
/*

  • Class: JNI_JAVA
  • Method: println
  • Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_JNI_1JAVA_println (JNIEnv *, jclass, jstring);

[/size]

以下是我自己写的C代码 JNI_JAVA.C的片段:
[size=xx-small]
/*

  • Class: JNI_JAVA
  • Method: println
  • Signature: (Ljava/lang/String;)V
    */
    JNIEXPORT void JNICALL Java_JNI_1JAVA_println
    (JNIEnv *env, jclass clz, jstring str) {

    //获取java.lang.system类
    

    jclass cls_system = (**env).FindClass(env, "java/lang/System");
    if (NULL == cls_system) {
    fprintf(stderr, "Error %s:%d\n", FILE, LINE);
    return;
    }

    //获取System.out的FID
    

    jfieldID fid_out = (**env).GetStaticFieldID(env, cls_system, "out", "Ljava/io/PrintStream;");
    if (NULL == fid_out) {
    fprintf(stderr, "Error %s:%d\n", FILE, LINE);
    return;
    }

    fprintf(stderr, "alive1\n");//正常输出

    //获取System.out的对象
    

    jobject obj_out = (**env).GetStaticObjectField(env, cls_system, fid_out);
    if (NULL == obj_out) {
    fprintf(stderr, "Error %s:%d\n", FILE, LINE);
    return;
    }

    fprintf(stderr, "alive2\n");//正常输出

    //[color=red]百分百死在下面这一句[/color]
    //获取System.out.println()的MID
    jmethodID mid_println = (**env).GetMethodID(env, obj_out, "println", "(Ljava/lang/String;)V");

    fprintf(stderr, "alive3\n");//这句不会输出,下面也不会执行
    if (NULL == mid_println) {
    fprintf(stderr, "Error %s:%d\n", FILE, LINE);
    return;
    }

    (**env).CallVoidMethod(env, obj_out, mid_println, str);

    fprintf(stderr, "Yeah\n");
    }

[/size]

执行到
jmethodID mid_println = (**env).GetMethodID(env, obj_out, "println", "(Ljava/lang/String;)V");
这一句时程序会死掉,同时给出以下输出:

//下面的alive1,alive2是我故意输出的
[size=xx-small]alive1

alive2
#

An unexpected error has been detected by HotSpot Virtual Machine:

#

SIGSEGV (0xb) at pc=0x00000000, pid=11192, tid=3076175552

#

Java VM: Java HotSpot(TM) Client VM (1.5.0_19-b02 mixed mode, sharing)

Problematic frame:

C 0x00000000

#

An error report file with more information is saved as hs_err_pid11192.log

#

If you would like to submit a bug report, please visit:

http://java.sun.com/webapps/bugreport/crash.jsp

#
[/size]

[b]问题:
我调用 jmethodID mid_println = (**env).GetMethodID(env, obj_out, "println", "(Ljava/lang/String;)V"); 为啥会死??
是不是违反了什么安全限制,所以才使得程序死掉?[/b]

实话说,我真的没有看出你那句有什么问题。。。你先把
[quote]
jmethodID mid_println = (**env).GetMethodID(env, obj_out, "println", "(Ljava/lang/String;)V");

fprintf(stderr, "alive3\n");//这句不会输出,下面也不会执行
if (NULL == mid_println) {
fprintf(stderr, "Error %s:%d\n", FILE, LINE);
return;
}

(**env).CallVoidMethod(env, obj_out, mid_println, str);
[/quote]

你先把这2句话注释掉,看有没有问题

如果没问题换jdk再试试

我这里反正没问题的,给你看看
[code="java"]
jclass cls;
jfieldID fid;
jobject obj;
jmethodID mid;

cls = (*env)->FindClass(env, "java/lang/System");
if (cls == 0) {
printf("java/lang/System error\n");
return;
}
fid = (*env)->GetStaticFieldID(env, cls, "out", "Ljava/io/PrintStream;");
if (fid == 0) {
printf("java/lang/System::out error\n");
return;
}
obj = (*env)->GetStaticObjectField(env, cls, fid);
if (obj == 0) {
printf("GetStaticObjectField error\n");
return;
}
cls = (*env)->GetObjectClass(env, obj);
if (cls == 0) {
printf("GetObjectClass out error\n");
return;
}
mid = (*env)->GetMethodID(env, cls, "println", "(Ljava/lang/String;)V");
if (mid == 0) {
printf("println method error\n");
return;
}
(*env)->CallVoidMethod(env, obj, mid, s);

[/code]