【问题标题】:Android and UnsatisfiedLinkErrorAndroid 和 UnsatisfiedLinkError
【发布时间】:2011-05-20 04:18:12
【问题描述】:

我在使用 Android 和 JNI 库时遇到了一个特殊问题。 JNI 库名为 libBase.so 并正确包含在 APK 中。我能够执行 System.loadLibrary("Base") 并且库被加载并且可以毫无问题地使用。

考虑以下代码 sn-ps:

/* NativeObject.java */
public class NativeObject
{
    /* ... */
    static
    {
        System.loadLibrary("Base");
    }
}

/* ObjectUtil.java */
public class ObjectUtil
{
    public static native NativeObject readNative(String path);
    public static native void writeNative(String path, NativeObject obj);
}

当我尝试在程序开始时执行 ObjectUtil.readNative() 时,我在 logcat 中遇到以下问题:

05-19 18:57:38.508: WARN/dalvikvm(365): No implementation found for native Lcom/navimatics/base/ObjectUtil;.readNative (Ljava/lang/String;)Lcom/navimatics/base/NativeObject;
05-19 18:59:15.409: ERROR/AndroidRuntime(365): java.lang.UnsatisfiedLinkError: readNative

我的理解是,因为 ObjectUtil 类引用 NativeObject,加载 ObjectUtil 类应该强制加载 NativeObject 类,从而执行执行 System.LoadLibrary() 调用的 NativeObject 静态初始化程序。不清楚为什么我会收到上述 logcat 消息。

但是,如果我将 ObjectUtil.java 修改为如下所示,则没有异常并且程序可以正常工作:

/* ObjectUtil.java */
public class ObjectUtil
{
    public static native NativeObject readNative(String path);
    public static native void writeNative(String path, NativeObject obj);
    static
    {
        System.loadLibrary("Base");
    }
}

如果我这样做也可以:

/* ObjectUtil.java */
public class ObjectUtil extends NativeObject
{
    public static native NativeObject readNative(String path);
    public static native void writeNative(String path, NativeObject obj);
}

对此的任何帮助将不胜感激。

更新: 我被要求的本机端代码是这样的:

static jobject JNICALL readNative(JNIEnv *env, jclass jcls, jstring jpath)
{
    // ...
}
static void JNICALL writeNative(JNIEnv *env, jclass jcls, jstring jpath, jobject jobj)
{
    // ...
}

static JNINativeMethod methods[] =
{
    { "readNative", "(Ljava/lang/String;)Lcom/navimatics/base/NativeObject;", readNative },
    { "writeNative", "(Ljava/lang/String;Lcom/navimatics/base/NativeObject;)V", writeNative },
};

使用 JNIEnv.RegisterNatives() 注册方法。

【问题讨论】:

  • 你没有提供原生端声明的代码,答案就在那儿
  • 按要求添加代码。

标签: java-native-interface android-ndk


【解决方案1】:

在初始化 JNINativeMethod 数组时有两个额外的括号,这段代码不应该编译。

检查RegisterNatives()的返回码,成功应该为零。

如果您正在编译 C++ 代码,您应该声明本机方法 extern "C" 以避免它们被破坏。

【讨论】:

  • Ognian,括号是对的。但是,原始代码中不存在额外的括号。原始代码包含许多我手动扩展的宏,因此您看到了问题。现已修复。
  • 我不同意 extern "C" 观察。回想一下 RegisterNatives() 注册函数指针。这些静态函数的名称不相关。
  • extern "C" 是对的。你查看RegisterNatives的返回值,注册成功了吗?
  • RegisterNatives() 返回成功 如果 它被调用。如前所述,如果我明确调用 System.loadLibrary() 然后 ObjectUtil.readNative() 它可以正常工作。仅当我调用 ObjectUtil.readNative() 而没有先调用 System.loadLibrary() 时才会出现问题。但是,这不应该引起问题,因为 ObjectUtil 引用了 NativeObject 类,该类确实在静态初始化程序中调用 System.loadLibrary()。请参阅我的原始帖子以获得完整的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 2012-07-21
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多