簡體   English   中英

Android JNI NDK - 未找到實現

[英]Android JNI NDK - No implementation found

我在 Android 上有一個 libjpeg-turbo 的 JNI 實現。 應用程序的構建沒有任何問題,我可以在生成的 APK 文件中看到本機libJPEGProcessing.so庫位於不同架構的lib文件夾中。 但是,當通過應用程序調用本地方法時,我會收到以下“未找到實現”消息,這將導致異常:

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); 
}

這是ndk-build Android.mk

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 -BV=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

您的代碼似乎沒問題 - 我看不到任何簽名問題,而且您似乎正在以所需的方式加載庫。 但是,事實是日志說找到了庫,但它找不到您的 JNI_OnLoad 實現。 是否有可能您擁有多個版本的 libJPEGProcessing.so,而系統會找到舊版本? 當然,我不是在談論針對各種架構的不同庫。

我發現雖然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 之外編譯本機庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM