【问题标题】:Android JNI NDK - No implementation foundAndroid JNI NDK - 未找到实现
【发布时间】:2017-02-25 19:51:10
【问题描述】:

我在 Android 上有一个 libjpeg-turbo 的 JNI 实现。 应用程序构建没有任何问题,我可以在生成的 APK 文件中看到本机 libJPEGProcessing.so 库位于不同架构的 lib 文件夹中。 但是,当通过应用程序调用native方法时,我会收到如下“no implementation found”消息,这会导致异常:

D/dalvikvm: No JNI_OnLoad found in /system/lib/libjpeg.so 0xa4fe3dc0, skipping init
D/dalvikvm: Trying to load lib /data/app-lib/com.google.test-2/libJPEGProcessing.so 0xa4fe3dc0
D/dalvikvm: Added shared lib /data/app-lib/com.google.test-2/libJPEGProcessing.so 0xa4fe3dc0
D/dalvikvm: No JNI_OnLoad found in /data/app-lib/com.google.test-2/libJPEGProcessing.so 0xa4fe3dc0, skipping init
W/dalvikvm: No implementation found for native Lcom/google/test/NativeMethods;.computeUsableDCTCoefficientsLinkedList:(Ljava/lang/String;)I

这是我在 JNI 中的方法:

extern "C" {
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }

    // Get jclass with env->FindClass.
    // Register methods with env->RegisterNatives.

    return JNI_VERSION_1_6;
}

JNIEXPORT jint JNICALL Java_com_google_test_NativeMethods_computeUsableDCTCoefficientsLinkedList
    (JNIEnv *env, jobject obj, jstring javaString)
{
...
}
}

以及生成的头文件:

extern "C" {
/*
 * Class:     com_google_test_NativeMethods
 * Method:    computeUsableDCTCoefficientsLinkedList
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_google_test_NativeMethods_computeUsableDCTCoefficientsLinkedList
  (JNIEnv *, jclass, jstring);
}

Java 中的实现如下所示:

package com.google.test;

import java.util.ArrayList;

public class NativeMethods {

    private String filename = null;
    private int fromNative = -100;
    private int numberInList = -100;
    private ArrayList<DCTCoefficient> array = null;

    static {
        System.loadLibrary("jpeg");
        System.loadLibrary("JPEGProcessing");
    }

    public static native int computeUsableDCTCoefficientsLinkedList(String filename); 
}

这是Android.mk 代表ndk-build

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_C_FILES := ./libjpeg-turbo/

LOCAL_MODULE    := JPEGProcessing
LOCAL_CFLAGS    := -Ic:\AndroidStudioProjects\Test\Test\src\main\jni\ -Ic:\libjpeg-turbo-gcc\include\
LOCAL_SRC_FILES := JPEGProcessing.c

LOCAL_C_INCLUDES := $(LOCAL_PATH)

LOCAL_STATIC_LIBRARIES := c:\libjpeg-turbo-gcc\lib\libjpeg.a

include $(BUILD_SHARED_LIBRARY)

在构建和编译过程中没有错误,应用程序将在 Android 设备上正常启动。但是,我定义了 JNI_OnLoad 方法,在 Java 类中加载本机库后也不会调用该方法。

编辑:

我在 Gradle Console 中发现了以下可能与之相关的警告:

Android NDK: WARNING:C:/AndroidStudioProjects/Test/Test/src/main/jni/Android.mk:JPEGProcessing: non-system libraries in linker flags: c:\libjpeg-turbo-gcc\lib\libjpeg.a    
Android NDK:     This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES    
Android NDK:     or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the    
Android NDK:     current module 

编辑 2:

尝试在 Linux 上查看编译后的 libJPEGProcessing.so:

nm libJPEGProcessing.so 
nm: libJPEGProcessing.so: no symbols

nm -D libJPEGProcessing.so 
00002004 A __bss_start
         U __cxa_atexit
         U __cxa_finalize
00002004 A _edata
00002004 A _end

没有导出的 JNI 方法和符号。这是正确的吗?

编辑 3:

ndk-build.cmd -B V=1 APP_ABI=armeabi的输出:

ndk-build.cmd -B V=1 APP_ABI=armeabi
del /f/q c:\AndroidStudioProjects\Test\Test\src\main\libs\arm64-v8a\libJPEGProcessing.so c:\AndroidStudioProjects\Test\Test\src\main\libs\armeabi\libJPEGProcessing.so c:\AndroidStudioProjects\Test\Test\src\main\libs\armeabi-v7a\libJPEGProcessing.so c:\AndroidStudioProjects\Test\Test\src\main\libs\mips\libJPEGProcessing.so c:\AndroidStudioProjects\Test\Test\src\main\libs\mips64\libJPEGProcessing.so c:\AndroidStudioProjects\Test\Test\src\main\libs\x86\libJPEGProcessing.so c:\AndroidStudioProjects\Test\Test\src\main\libs\x86_64\libJPEGProcessing.so >NUL 2>NUL
[armeabi] SharedLibrary  : libJPEGProcessing.so
C:/Android/sdk/ndk-bundle/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libJPEGProcessing.so -shared --sysroot=C:/Android/sdk/ndk-bundle/build//../platforms/android-9/arch-arm -lgcc  -gcc-toolchain C:/Android/sdk/ndk-bundle/build//../toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64 -no-canonical-prefixes -target armv5te-none-linux-androideabi  -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings    -lc -lm -o c:/AndroidStudioProjects/Test/Test/src/main/obj/local/armeabi/libJPEGProcessing.so
[armeabi] Install        : libJPEGProcessing.so => libs/armeabi/libJPEGProcessing.so
copy /b/y "c:\AndroidStudioProjects\Test\Test\src\main\obj\local\armeabi\libJPEGProcessing.so" "c:\AndroidStudioProjects\Test\Test\src\main\libs\armeabi\libJPEGProcessing.so" > NUL

【问题讨论】:

  • 看起来你的代码是 c++,但是 Android.mk 编译 c。哪里有错别字?
  • 其实代码在c里
  • 尝试使用 cmake 进行原生构建
  • 我不知道如何将我在Android.mk 中的 ndk 构建脚本转换为 cmake...但它也应该适用于 ndk build
  • nm -D 表明您的 .so 构建不正确。请注意,extern "C" 不会使用 C 编译器进行编译,因此请仔细查看问题所在。我建议你运行ndk-build -B V=1 APP_ABI=armeabi(在命令行上)看看你的设置出了什么问题

标签: java android c++ android-ndk java-native-interface


【解决方案1】:

您的代码似乎没问题 - 我看不到任何签名问题,而且您似乎正在以所需的方式加载库。但是,事实是日志说找到了库,但它找不到您的 JNI_OnLoad 实现。您是否有可能拥有多个版本的 libJPEGProcessing.so,而系统会找到一个较旧的版本?当然,我不是在谈论针对各种架构的不同库。

【讨论】:

  • 我不知道怎么检查,但是我已经删除了所有生成的库和apk文件并重新构建了它。结果是一样的。
  • 检查的方法是在整个项目文件夹中搜索。如果您已经这样做了,并将它们全部删除,那么这当然不是问题。检查包和签名没有意义,因为显然这里的问题是库本身(因为没有找到 onLoad 和您的方法)。但是您最近的编辑提供了更多信息 - 您是否尝试使用 LOCAL_SHARED_LIBRARIES ?
  • 我尝试使用 LOCAL_SHARED_LIBRARIES,结果相同...至少关于链接器中非系统库的警告消失了。
【解决方案2】:

我发现虽然 APK 已编译并可以正常工作,但本机库未正确编译并包含在 lib 文件夹中的 APK 文件中。

所以我将build.gradle 更改为不使用ndk-build,而是为项目使用预编译的本机库。更改后,本机库包含在 APK 中,并且一切正常:

    sourceSets.main {
        jniLibs.srcDir 'src/main/libs' //set libs as default directory for .so files inclusion, instead of jniLibs
        jni.srcDirs = [] //disable automatic ndk-build call
    }

如果有任何更改,我唯一要做的就是在 Android Studio 之外编译原生库。

【讨论】:

    猜你喜欢
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多