【问题标题】:JNI NewStringUTF called with pending exception 'java.lang.NoSuchMethodError'JNI NewStringUTF 调用挂起异常'java.lang.NoSuchMethodError'
【发布时间】:2015-11-12 15:07:39
【问题描述】:

我不知道为什么调用原生方法时会抛出异常。

本机代码:

JNIEXPORT jstring JNICALL Java_org_amk_lockscreen_JNIActivity_getPackege(JNIEnv *env,jclass cls,jobject context){
    jclass Context_class = (*env).FindClass("android/content/Context");
    jmethodID midGetPackageName = (*env).GetMethodID(Context_class, "getPackageName", "(V)Ljava/lang/String;");
    if(midGetPackageName==0){
        return (*env).NewStringUTF("Not Found Method");
    }
    else{
        jobject packageName=(*env).CallObjectMethod( context, midGetPackageName);
        return (jstring)packageName;
    }
}

还有我的java代码:

public class JNIActivity extends Activity {

    static {
        System.loadLibrary("myjni"); // "myjni.dll" in Windows, "libmyjni.so" in Unixes
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jni);
        TextView txt = (TextView) findViewById(R.id.txtMessage);
        try {
            txt.setText(getPackege(getApplicationContext()));
        } catch (Exception exp) {
            txt.setText(exp.getMessage());
        }
    }

    public native String getMessage();

    public native String getPackege(Context con);
}

但是当运行它时,它会抛出异常:

JNI DETECTED ERROR IN APPLICATION: JNI NewStringUTF called with pending exception 'java.lang.NoSuchMethodError' thrown in java.lang.String org.amk.lockscreen.JNIActivity.getPackege(android.content.Context):-2
in call to NewStringUTF
from java.lang.String org.amk.lockscreen.JNIActivity.getPackege(android.content.Context)

我测试了不同的方法签名,比如:

(Ljava/lang/Void;)Ljava/lang/String;     
   (V;)Ljava/lang/String;

但它再次抛出异常。

我哪里做错了?

【问题讨论】:

  • 你不应该使用 -> 语法:(*env)->NewStringUTF("...");
  • 当我使用这种语法时,发生.gradle 错误:错误:错误:'->' 的基本操作数具有非指针类型'JNIEnv {aka _JNIEnv}'

标签: java android android-ndk


【解决方案1】:

GetMethodID 引发异常。您没有检查是否使用 env->ExceptionCheck(env) 引发了异常,然后使用 ExceptionClear() 清除它或立即从函数返回以便 JVM 处理它。请在此处查看有关 getMethodId 的 Oracle 文档:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html

例如(来自http://www.ibm.com/developerworks/library/j-jni/:) findClass、GetStaticMethodID 和 CallStaticVoidMethod 调用都会产生类似于 GetMethodID 的异常。

int val=1;
jmethodID method;
jclass cls;

cls = (*env)->FindClass(env, "com/ibm/example/TestClass");
if ((*env)->ExceptionCheck(env)) {
   return ERR_FIND_CLASS_FAILED;
}
method = (*env)->GetStaticMethodID(env, cls, "setInfo", "(I)V");
if ((*env)->ExceptionCheck(env)) {
   return ERR_GET_STATIC_METHOD_FAILED;
}
(*env)->CallStaticVoidMethod(env, cls, method,val);
if ((*env)->ExceptionCheck(env)) {
   return ERR_CALL_STATIC_METHOD_FAILED;
}

【讨论】:

  • 可以给出ndk中异常处理的例子
  • 如果出现异常,你有两个选择:清除它,或者返回VM,它会负责处理它。
  • 但例外是NoSuchMethodError。清除它有什么意义?
【解决方案2】:

你的方法定义在这里是错误的:

jmethodID midGetPackageName = (*env).GetMethodID(Context_class, "getPackageName", "(V)Ljava/lang/String;");

您根本无法在参数中传递 (V),因为这意味着您传递的是 void 参数,这在 Java 中没有意义。您需要弄清楚传递给您的 java 方法的参数类型(例如 String),以及此方法返回的返回类型(例如 void)。

因此,您可能打算这样做:

jmethodID midGetPackageName = (*env).GetMethodID(Context_class, "getPackageName", "Ljava/lang/String;(V)");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 2011-11-23
    相关资源
    最近更新 更多