加载本地库多次加载

2023-09-07 03:35:58 作者:趁我还在趁我还爱

我做了可以存储整数并返回一个简单的机库。

I've made a simple native library that can store a integer and return it.

#include <string.h>
#include <jni.h>
static int a;

void Java_com_example_testnativelibs_TestClass_setA(JNIEnv* env, jobject javaThis, jint val){
    a = val;
}
jint Java_com_example_testnativelibs_TestClass_getA(JNIEnv* env, jobject javaThis) {
      return a;
}

这是识别TestClass code:

This is the TestClass code:

public class TestClass {
    public TestClass() {
        System.loadLibrary("ndkfoo2");
    }
public native void setA(int val);
public native int getA();
}

然后我MainActivity的code:

And then the code of my MainActivity:

TestClass a = new TestClass();
TestClass b = new TestClass();
a.setA(5);
b.setA(2);
Log.i("A VALUE",""+a.getA());
Log.i("B VALUE",""+b.getA());

的值2示出在记录中的两倍,这意味着,该库只加载一次,它是由同一类的所有实例共享。是否有可能多次加载它,每一个类实例?

The value 2 is shown two times in the log, this means that the library is loaded only once and it is "shared" by all the instances of the same class. Is it possible to load it multiple times, one for each class instance?

推荐答案

没有。在Linux(Android版)的共享库被加载只有一次进入一个过程。这就是为什么你应该非常,非常罕见用不完的全球数据共享库 - 数据是全球对于整个过程。

No. Shared libraries on Linux (Android) are loaded only once into a process. This is why you should very, very rarely ever use global data in your shared libraries -- that data is global for that entire process.

而不是你的图书馆应该生产和消费的某种状态变量,保持它的功能调用之间的轨道数据(结构,指针等等)。

Instead your libraries should produce and consume some sort of "state" variable (struct, pointer, etc.) that keeps track of data between invocations of its functions.

不幸的是我从来没有用JNI工作,所以我不知道相关的API调用来实现。

Unfortunately I've never worked with the JNI, so I don't know the relevant API calls to accomplish this.

在普通的Linux,你可能会碰到这样的:

In plain Linux, you might have something like:

公开头文件

typedef void* PublicState;  // Don't let consumers know anything about the
                            // state that we're keeping.

PublicState MyLib_init();
void        MyLib_free(PublicState state)
int         MyLib_getVal(PublicState state);

私人C实现文件

// This is the actual "state" object we keep track of information with.
typedef struct _PrivateState {
    int a;
} PrivateState;


PublicState MyLib_init() {
    PrivateState* state = malloc( sizeof(PrivateState) );
    // check for errors

    state->a = 42;

    return (PublicState)state;
}

int MyLib_getVal(PublicState state) {
    PrivateState* ps = (PrivateState*)state;

    return ps->a;
}

void MyLib_free(PublicState state) {
    // any other cleanup
    free(state);
}

我甚至不知道这是不是你应该做的JNI的方式。

I don't even know if this is the way you're "supposed" to do it in JNI.

另请参见:

Passing C和Java之间的指针通过JNI Passing使用长从JNI一个指针的Java Passing pointers between C and Java through JNI Passing a pointer from JNI to Java using a long