java loadlibrary和本机方法声明

时间:2017-10-05 12:39:11

标签: java java-native-interface

简而言之:显然,必须在发出loadLibrary调用的同一个类中声明本机方法。如果在静态内部类中声明本机方法,则绑定失败。

工作示例:

imageView.setImageDrawable(getResource().getDrawable(R.drawable.animation);
AnimationDrawable animation = (AnimationDrawable)imageView.getDrawable();
animation.start();

示例失败:

public class TestNative
{
    public TestNative()
    {
        System.loadLibrary( "mylibrary");
    }

    private native int nativeMethod();

    public void doit()
    {
        new NativeWrap().callNative();
    }

    class NativeWrap
    {
        int callNative()
        {
           return nativeMethod();    // <<<< works
        }
    }
}

BTW:loadLibrary在两个示例中都有效。

我没有找到关于这个主题的任何提示。我发现的所有JNI示例都在声明本机方法的同一个类中加载库。有人可以对这些东西发光吗?

1 个答案:

答案 0 :(得分:1)

它完美无缺。放置库的位置并不重要。这里重要的是方法的名称。如果您生成方法签名,然后将方法移动到其他位置,则无法运行。

看看这里:

package recipeNo001;

public class HelloWorld {

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

  private native void displayMessage();

  static class NativeWrapper {
    void callNative() {
      displayMessageInner();
    }
    private native void displayMessageInner();
  }

  public static void main(String[] args) {
    new HelloWorld().displayMessage();
    new NativeWrapper().callNative();
  }
}

但是你必须确保在库中提供正确的名称。注意两者之间的区别:

JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_displayMessage
  (JNIEnv *env, jclass obj)
JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_00024NativeWrapper_displayMessageInner
  (JNIEnv *env, jobject obj)

当然,它有效。

Hello world from enclosing class!
Hello world from wrapper!

而且,在您的情况下,您还有另一个问题。如果您不在静态块中加载库,则必须确保在调用本机方法之前实例化该类的至少一个对象。

在示例代码中看看这里:

https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo034