Android JNI NDK - 未找到任何实现

时间:2017-02-25 19:51:10

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

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

Android.mk的{​​{1}}:

ndk-build

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

修改

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

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)

编辑2:

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

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 

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

编辑3:

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 的输出:

ndk-build.cmd -B V=1 APP_ABI=armeabi

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我发现尽管APK已编译并正常工作,但本地库未正确编译并包含在APK文件夹中的lib文件中。

所以我将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外部编译本机库。