【问题标题】:Calling java code from C++: exception java.lang.NoSuchMethodError从 C++ 调用 java 代码:异常 java.lang.NoSuchMethodError
【发布时间】:2015-03-10 09:34:39
【问题描述】:

我试图从 JNI C++ 函数中调用一些 java 代码,但出现异常:java.lang.NoSuchMethodError

调用 java 代码的 C++ 代码是从另一个本地库调用的回调函数。 当我使用中描述的设置时,此代码运行良好 here:

基本上是一个使用 JNI 的 APK,并且 JNI 正在调用在其他地方编译的本机库)。

但是后来我想在 AOSP 中编译我的所有代码,所以我将我的原生库的代码、JNI 和 APK 代码放在 vendor/MyCode/MyApp 中。它编译得很好,从 java 调用的本机方法工作正常,但是从 JNI 调用的 java 代码现在全部崩溃。

这是我想从 JNI 调用的方法的 java 代码:

package com.android.mycode.myapp;

import android.app.Activity;

public class MainActivity extends Activity implements OnClickListener
{
    private native int powerOn();

    ...

public void ndefRead(int tech, int protocol, byte[] ndef)
{
    Log.d(tag, "ndefRead()");
    Message msg = mHandler.obtainMessage();
    msg.what = MSG_NDEF_READ_RECEIVED;
    msg.obj = ndef;
    msg.arg1 = tech;
    msg.arg2 = protocol;
    mHandler.sendMessage(msg);
}

...
}

我在其中注册 java 数据的 JNI 代码:

JNIEXPORT jint JNICALL
Java_com_android_mycode_myapp_MainActivity_powerOn(JNIEnv * env, jobject obj)
{
    LOGD("calling powerOn()"); //Or ANDROID_LOG_INFO, ...

    env->GetJavaVM(&javaVM);
    jclass cls = env->GetObjectClass(obj);
    activityClass = (jclass) env->NewGlobalRef(cls);
    activityObj = env->NewGlobalRef(obj);
    ...
    return status;
}

调用java代码的回调函数的JNI代码:

void EventCallback(UINT8 event, tEVT_CBACK_DATA* eventData)
{
LOGD("EventCallback() - event: 0x%x", event);

switch (event)
{
    case NDEF_READ_EVT:
    {
        LOGD("EventCallback() - NDEF_READ_EVT - data length: 0x%x", eventData->ndefReadEvt.length);

        JNIEnv *env;
        javaVM->AttachCurrentThread(&env, NULL);

        jmethodID ndefReadID = env->GetMethodID(activityClass, "ndefRead", "(II[B)V");
        if (ndefReadID == 0)
        {
            LOGD("Function ndefRead() not found");
            return;
        }

        jbyteArray result = env->NewByteArray(eventData->ndefReadEvt.length);
        if (result != NULL)
        {
            env->SetByteArrayRegion(result, 0, eventData->ndefReadEvt.length, (jbyte *) eventData->ndefReadEvt.p_ndef);
        }

        env->CallVoidMethod(activityObj, ndefReadID, eventData->ndefReadEvt.tech, eventData->ndefReadEvt.protocol, result);
        javaVM->DetachCurrentThread();
    }
        break;
}

JNI 的 makefile 如下所示:

LOCAL_MODULE    := libinterface
LOCAL_SRC_FILES := interface.cpp
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := libnfc-nci

在执行此代码时,我收到以下异常/错误消息:

Pending exception java.lang.NoSuchMethodError thrown by 'unknown throw location'
java.lang.NoSuchMethodError: no non-static method "Lcom/android/mycode/myapp/MainActivity;.ndefRead(II[B)V"

我查看了此站点上报告的其他几个此类问题,但找不到与我的相似的问题。如果有人有想法,将不胜感激。

编辑添加了ndefRead()函数的代码和JNI的makefile。

【问题讨论】:

  • 当您附加到线程时,activityClass 是否可以在此线程上使用?快速浏览了 JNI 文档,我并不清楚。
  • 我认为使用 activityClass = (jclass) env->NewGlobalRef(cls) 代码应该可以解决问题。正如我所说,在我将所有内容放在 AOPS(供应商文件夹)上并编译之前,这段代码运行良好。
  • 是的,使用类引用应该没问题,因为创建了对它的全局引用。我看到的一个潜在问题 - 取决于对 EventCallback 的调用来自何处 - 如果线程已经附加到 VM,AttachCurrentThread 本质上是一个 NOP,因此在之前已经附加的线程上调用 DetachCurrentThreadAttachCurrentThread 可能会导致问题。
  • 这不会导致 NoSuchMethod 之外的另一个异常吗?因为我已经遇到了 AttachCurrentThread 的问题(退出应用程序时我没有调用分离代码)并且错误消息不同。
  • package com.android.mycode.myapp; vs Java_com_android_st_nfcnintendothread_MainActivity_powerOn

标签: java android c++ android-ndk


【解决方案1】:

这些错误通常是由 make 文件或错误的文件命名引起的。

我没有看到任何static { System.loadLibrary("your-c-module"); },如 android MK 中所定义,例如:

#android.mk

include $(CLEAR_VARS)

LOCAL_MODULE    := your-c-module
LOCAL_SRC_FILES := main.cpp
LOCAL_STATIC_LIBRARIES += fancy-library
LOCAL_LDLIBS +=  -llog -ldl

另外,我不知道你有没有过滤掉它,但如果Java_com_android_st_nfcnintendothread_MainActivity_powerOn是你的c函数,那么你的包名应该是:com.android.st.nfcnintendothread,它的函数是:MainActivity.powerOn

我只是在这里吐口水,希望你能在上面找到有用的东西。

【讨论】:

  • 是的,我尝试并过滤了一些命名,似乎忘记了一些。我的 JNI 函数名与 java 包同名。这是我的 JNI makefile 的样子: italic bold ` LOCAL_MODULE := libinterface LOCAL_SRC_FILES := interface.cpp LOCAL_LDLIBS := -llog LOCAL_SHARED_LIBRARIES := libnfc-nci"跨度>
  • 我重新编辑了代码以反映当前的实现
猜你喜欢
  • 2021-05-11
  • 1970-01-01
  • 2018-09-27
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 2020-06-20
  • 1970-01-01
相关资源
最近更新 更多