【问题标题】:java.lang.UnsatisfiedLinkError: No implementation found for Booleanjava.lang.UnsatisfiedLinkError:没有找到布尔的实现
【发布时间】:2016-12-16 06:17:08
【问题描述】:

我在我的项目中使用“.so”文件,但它给出了以下错误“java.lang.UnsatisfiedLinkError: No implementation found for Boolean”,我已经尝试使用 Cygwin 重新创建“.so”并将其放在 jniLibs 文件夹中,并使用创建一个 jar 它,但它给出了同样的错误。

但相同的“.so”文件正在我现有的项目中工作。我尝试了很多方法,但它根本不起作用,我该怎么办?

com.amaze.filemanager E/art: No implementation found for boolean com.amaze.filemanager.scanner.SignatureLib.InitScanner(java.lang.String, java.lang.String)(试过 Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner 和 Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner__Ljava_lang_String_2Ljava_lang_String_2) 12-19 11:47:07.463 4579-4934/com.amaze.filemanager E/AndroidRuntime: 致命异常: Thread-5230 进程:com.amaze.filemanager,PID:4579 java.lang.UnsatisfiedLinkError: No implementation found for boolean com.amaze.filemanager.scanner.SignatureLib.InitScanner(java.lang.String, java.lang.String) (已尝试 Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner 和 Java_com_amaze_filemanager_scanner_SignatureLib_InitScanner__Ljava_lang_String_2Ljava_lang_String_2) 在 com.amaze.filemanager.scanner.SignatureLib.InitScanner(本机方法) 在 com.amaze.filemanager.scanner.SignatureLib.InitializeScanner(SignatureLib.java:42) 在 com.amaze.filemanager.scanner.Signature.(Signature.java:62) 在 com.amaze.filemanager.ScanForVirusActivity$1.run(ScanForVirusActivity.java:66)

public class SignatureLib {

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

    SharedPreferencesUtils spu;
    Context context;

    public SignatureLib(Context context) {
        this.context = context;
    }

    private native boolean InitScanner(String strDBPath, String dbPathTemp);

    private native boolean DeInitScanner();

    private native String checkVirus(String filepath);

    private native boolean UploadFile(String FilePath, String DeviceID, String path);

    private native boolean DownloadFile(String FilePath, String DeviceID, String path);

    private native boolean IsGameApp(String AppName);

    private native boolean SetUpdateInProgressStatus(boolean bStatus);

    public boolean InitializeScanner(String strDBPath) {

        spu = new SharedPreferencesUtils();
        String packageName = context.getPackageName();
        String dbPathTemp = "data/data/" + packageName + "/";

        return InitScanner(strDBPath, dbPathTemp);
    }

}

【问题讨论】:

  • 发布您的完整堆栈跟踪和引发此错误的代码。
  • 我把我的堆栈跟踪和代码,它给了我return InitScanner(strDBPath, dbPathTemp)的错误,请帮助我

标签: android java-native-interface unsatisfiedlinkerror


【解决方案1】:

是的,需要完整的堆栈跟踪 - 您最初在一个毫无意义的地方将其断开。它的意思是你的 .so 文件没有 InitScanner 函数——要么你在 C 文件中错误地命名它,要么签名错误,要么根本不存在。或者如果你使用 C++,你忘记了外部 C 函数。

【讨论】:

  • 确定.so在apk文件中正确吗?对于正确的芯片组?您发布的错误意味着它没有找到该功能。
  • 我放了全栈跟踪,但是 SignatureLib 类和 c++ 的相同代码在现有产品中工作,所以我哪里出错了
  • @FaheemRaza,你能解决这个问题吗?请分享,因为我面临着类似的问题。
【解决方案2】:

在我的 java 文件中,我在下面的静态块中加载了名为“native-lib”的库名

package primeno.naval.com.primenumberusingndk;
static
{
  System.loadLibrary("native-lib");
}

这里我已经声明了这两个函数,它们的实现在 CPP 文件中

public native String stringFromJNI();
public native boolean isPrime(int n);

我的cpp文件,上面的函数实现

extern "C"
JNIEXPORT jstring JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jboolean JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_isPrime(JNIEnv *env,jobject ,jint no)
{
PrimeNumber primeNumber(no);
return primeNumber.isPrime();
}

或者你也可以这样做

extern "C" {

    JNIEXPORT jstring JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_stringFromJNI(
    JNIEnv *env,
    jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
    }

    JNIEXPORT jboolean JNICALL Java_primeno_naval_com_primenumberusingndk_MainActivity_isPrime(JNIEnv *env,jobject ,jint no)
    {
    PrimeNumber primeNumber(no);
    return primeNumber.isPrime();
    }
}

如果函数名称和签名不匹配,那么您必须在 cpp 文件中的每个函数之前编写 extern "C", 所以命名约定的实际格式是

extern "C" JNIEXPORT <RETURN_TYPE> JNICALL Java_<PACKAGE_NAME>_<JAVA_CLASS>_<METHOD_NAME>(
JNIEnv *env, jobject obj, <METHOD_PARAMETERS>...) {
...
}

extern "C":

使 C++ 函数名称具有 C 链接的语句。为了支持函数重载,C++ 编译器会修改函数名称,这意味着 C++ 函数名称与 C 中的不同。没有 extern "C",您的本机函数的签名将与它们在 Java 中的声明不匹配(在运行时)。长话短说,如果您编写的是原生 C++ 而不是 C,则每种方法都需要此语句。

JNIEXPORT

包含确保函数正确导出所需的编译器指令。

&lt;RETURN_TYPE&gt;

JNI 方法的返回类型,通常是 Java 类型的本机版本。例如,在您上面刚刚编写的方法中,您返回的是一个 jstring,它是 Java 中 String 的原生等价物。

JNICALL:C

包含确保使用正确的 JNI 调用约定处理函数所需的编译器指令。

&lt;JAVA_CLASS&gt;:

此函数所绑定的连接 Java 类。在我们的示例中,这将是 MainActivity,因为它将使用该函数的 Java 类。

&lt;PACKAGE_NAME&gt;

之前定义的&lt;JAVA_CLASS&gt;所在的包名。用下划线(_)替换点(.)。

&lt;METHOD_NAME&gt;

此名称应与您在连接中声明的名称相同。在我们的示例中,我们声明了本机方法 getNativeString()。在这种情况下,也应该是getNativeString()。

JNIEnv *env

指向存储所有 JNI 辅助函数指针的结构(准确地说是函数表)的指针,包括我们在示例中调用的那个,NewStringUTF(string)。为了能够使用这些功能,您需要#include。

jobject obj

connecting&lt;JAVA_CLASS&gt;对应的Java对象。

&lt;METHOD_PARAMETERS&gt;...:

本地方法应该采用的输入参数的逗号分隔列表。在我们的示例中,我们的 getNativeString() 函数没有任何输入参数,因此留空。

【讨论】:

  • 这不是问题的答案,您不必执行任何操作:只需将 .h 文件包含在 .cpp 文件中即可。请去掉尖叫的黑体字。
  • 嗨 EJP 这里是示例 git github.com/NavalKishor/PrimeNumberUsingNdk 你只需在 git 的 src/main/../cpp/native-lib 中注释 extern "C" 并编译你会得到相同的错误 java.lang.UnsatisfiedLinkError: No implementation found for and (试过这个......和这个......)然后你会发现答案是合理的
  • @EJP 上面提到的案例你测试了吗
猜你喜欢
  • 1970-01-01
  • 2013-08-03
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 1970-01-01
  • 2020-07-07
  • 2016-01-17
  • 2019-11-13
相关资源
最近更新 更多