【问题标题】:How to resolve the java.lang.UnsatisfiedLinkError in NDK in Android?如何解决 Android NDK 中的 java.lang.UnsatisfiedLinkError?
【发布时间】:2011-03-16 19:14:12
【问题描述】:

我是android ndk开发的新手。我已经通过了ndk android的文件系统。 在这里,解释我做了什么。 1) 我创建了一个名为“jni”的文件夹,然后创建了 2 个名为 Android.mk 和 ndkfoo.c 的文件。

在 Android.mk 中

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Here we give our module name and source file(s)
LOCAL_MODULE    := ndkfoo
LOCAL_SRC_FILES := ndkfoo.c

include $(BUILD_SHARED_LIBRARY)

在 ndkfoo.c 中

#include <string.h>
#include <jni.h>

jstring Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
 return (*env)->NewStringUTF(env, "Hello from native code!");
}

然后我创建了 NdkFooActivity 类,我在其中编写了

// load the library - name matches jni/Android.mk
 static {
  System.loadLibrary("ndkfoo");
 }

但是现在当我在 xp 中从 cygwin 构建时,它会成功创建 .so 文件,然后我作为 android 应用程序运行。它给了我 LOGCAT 中的 java.lang.UnsatisfiedLinkError。

所以,请让我知道我错在哪里。

提前致谢,

【问题讨论】:

  • 你确定你声明invokeNativeFunction()的类实际上是com.mindtherobot.samples.ndkfoo.NdkFooActivity吗?您可以发布所有代码
  • 具体请在.java文件中包含native方法的声明。也显示“包”和“类”声明。此外,将 JNI_OnLoad 函数添加到您的共享库并在那里放置一些日志记录,以便您可以确保成功加载库。
  • 在 ndkfoo.c Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction 中检查此声明,这应该更改为您的包名称,例如 Java_com_your_package_ndkfoo_NdkFooActivity_invokeNativeFunction

标签: android-ndk


【解决方案1】:
JNIEXPORT jstring JNICALL Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
 return (*env)->NewStringUTF(env, "Hello from native code!");
}

问题是您为目标处理器编译并在其他处理器中执行。如果您在 ARM(armeabi) 中编译,则在基于 armeabi 的模拟器中执行。 在与 Android.mk 相同的文件夹中创建一个名为 application.mk 的文件,并将其放入其中之一:

  1. APP_ABI := x86
  2. APP_ABI := armeabi
  3. APP_ABI := mips
  4. APP_ABI := armeabi x86 mips //在所有目标中编译,您将获得 3 个 *.so 文件

然后编译->运行。 它应该工作。

【讨论】:

    【解决方案2】:

    替换这个

    Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction
    

    Java_your_packege_name_your_Activity_Name_invokeNativeFunction
    

    例如,如果您的包是 com.pack 并且活动名称名称是 MainActivity 那么

    Java_com_pack1_MainActivity_invokeNativeFunction 
    

    不要忘记在 Activity 中添加引用。

    // 加载库 - 名称匹配 jni/Android.mk

    static {
            System.loadLibrary("ndkfoo");
          }
    
     public native String invokeNativeFunction();
    

    重复所有这些步骤它应该可以工作:)

    【讨论】:

      【解决方案3】:

      方法名Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction

      可能与您的包名或类名不同。 要使该方法的命名完全相同,您必须使用javah

      这将创建一个头文件,该头文件将具有所需的相同方法名称。要使此头文件转到项目 bin 中的 classes 文件夹(确保您已使用静态方法创建了 java 文件,并且通过终端中的此命令正确构建它)

      ~/workspace/Android_Example2/bin/classes$

      在这个目录下写如下命令

      sudo javah -jni com.NDK.android_example2.MainActivity
      

      根据您的项目更改包名和类名。这将在您的类文件夹中创建一个 com_NDK_android_example2_MainActivity.h。

      只需将此文件移动到您的jni 文件夹中。在此文件中,将有您在 MainActivity.java 文件中创建的静态方法,但它们只是声明为未实现,您将在 C 文件中实现。

      注意:在处理方法时检查方法参数是否需要声明,因此请在您的C 文件中声明它们。

      希望对您有所帮助。

      【讨论】:

        【解决方案4】:

        这里有一个如何使用本机代码的教程:here

        确保您的项目路径中没有任何空格。 您也不能在包或项目名称中使用下划线。

        【讨论】:

          【解决方案5】:

          我也遇到了java.lang.UnsatisfiedLinkError 错误。我验证了上述答案中提到的所有内容,但仍然出现错误。我最终发现 JNI 方法名称不能有下划线。

          示例: Java_com_example_app_NativeLib_print_out_stuff

          将 print_out_stuff 函数重命名为不带下划线的名称: Java_com_example_app_NativeLib_printOutStuff

          【讨论】:

            【解决方案6】:

            另外(刚刚遇到这个问题),请注意,如果您在 Intel Atom x86 仿真器上进行测试,System.loadLibrary() 将始终抛出异常。它在常规 Android 模拟器上运行良好,在物理设备上进行调试。

            【讨论】:

            • @Daniel Rodriguez:非常感谢。 :) :) :)
            • 试错。为了给你这个答案,我们浪费了很多调试时间。
            • ...除非您加载的库是为 x86 编译的
            • 另外值得注意的是,这个问题可以通过编译所有架构来解决,如stackoverflow.com/a/12607739/2264920所示
            • 怎么知道模拟器是Intel Atom x86还是普通模拟器?
            【解决方案7】:

            也许不再相关,但据我所知,您还需要在您的本机库名称中添加“lib”前缀。在您的情况下,您需要将 Android.mk 更改为 "LOCAL_MODULE := libndkfoo" 并保留 "System.loadLibrary("ndkfoo");"照原样。查看 ndk 示例代码。

            【讨论】:

              【解决方案8】:

              在 jni 文件夹中创建文件 Application.mk。复制以下行并将其粘贴到 Application.mk 并保存。现在使用 cgywin 构建项目并再次运行

              APP_ABI := armeabi armeabi-v7a

              【讨论】:

                【解决方案9】:

                我很确定应该是:

                JNIEXPORT jstring JNICALL Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
                 return (*env)->NewStringUTF(env, "Hello from native code!");
                }
                

                您的目标是哪个 SDK 以及您拥有哪个版本的 NDK?你得到的错误是说它根本无法加载库还是有一个未实现的方法?无论哪种方式,请确保您没有在清单中的应用程序标记上设置 android:hasCode="false" 。

                您也可以在构建后使用 winrar 或类似工具打开 APK 文件,以确保 libndkfoo.so 文件实际上包含在包中。

                无论哪种方式,如果您没有在 NdkFooActivity 中声明本机函数,您都会收到该错误,即

                公共静态原生字符串invokeNativeFunction();

                【讨论】:

                  【解决方案10】:

                  虽然这不是 OP 的问题,但由于缺少,我遇到了相同的 java.lang.UnsatisfiedLinkError

                  static {
                      System.loadLibrary("mylibraryname");
                  }
                  

                  【讨论】:

                  • 通常会导致以下问题:'java.lang.ExceptionInInitializerError java.lang.UnsatisfiedLinkError: Library xyz... not found'
                  【解决方案11】:

                  我想你忘记更改包名了。

                  Java_com_mindtherobot_samples_ndkfoo

                  它应该是你指定的创建项目的包。

                  【讨论】:

                    【解决方案12】:

                    正如其他人所提到的,签名很有可能是错误的。

                    如果您运行 javah 实用程序,您可以找到确切的签名。从项目中的 bin 文件夹(.apk 所在且生成 Java 类层次结构的根目录)中,运行:

                    javah -o jni_sig.h com.mindtherobot.whatever.your.package.is.NdkFooActivity

                    ...并且,如果您的包名和类名正确,它将为任何本机函数写出带有正确函数签名的标头(称为 jni_sig.h)。将其复制到您的头文件和 .c 文件中,根据需要添加参数,它应该可以正常工作。

                    【讨论】:

                    • 谢谢。在我的系统上,它需要从 Classes 子目录运行。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-11-10
                    • 2015-07-29
                    • 2012-03-24
                    • 2012-02-20
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多