Bill Zissimopoulos
Bill Zissimopoulos

Reputation: 555

Android and UnsatisfiedLinkError

I have a peculiar issue with Android and a JNI library that I am using. The JNI library is named libBase.so and is properly included in the APK. I am able to do System.loadLibrary("Base") and the library gets loaded and can be used without any problems.

Consider the following code snippets:

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

When I attempt to do ObjectUtil.readNative() in the beginning of my program, I get the following issues in 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

My understanding is that because the class ObjectUtil references NativeObject, loading the ObjectUtil class should force the loading of the NativeObject class and thus the execution of the NativeObject static initializer which performs the System.LoadLibrary() call. It is not clear then why I would get the aforementioned logcat messages.

However if I modify ObjectUtil.java to read as follows there is no exception and the program works:

/* 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");
    }
}

It also works if I do this:

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

Any help on this would be greatly appreciated.

UPDATE: The native side code that I was asked for is this:

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

The methods are registered using JNIEnv.RegisterNatives().

Upvotes: 1

Views: 3848

Answers (1)

ognian
ognian

Reputation: 11541

You have two extra parenthesis in initializing the JNINativeMethod array, this code shouldn't compile.

Check the return code of RegisterNatives(), it should be zero on success.

Also in case you're compiling a C++ code, you should declare the native methods extern "C" to avoid getting them mangled.

Upvotes: 1

Related Questions