4

背景

我在 JAVA 中有一个本机函数

package mypackage;

public class MyWrapper {

    private native int
    wrapFilterRawRequest(String config, String rawRequest);

    public void 
    processRequest( String configPath,String rawRequest){
        int status = 0; 
        status = new MyWrapper().wrapFilterRawRequest(configPath, rawRequest);
        status2 = new MyWrapper().wrapFilterRawRequest(configPath, rawRequest);
    }

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

}

和 C 中的 JNI Wrapper

int processRequest(char *conf, char *req)
{
    int status = 0;   
    // Do something here
    return status;
}

JNIEXPORT jint JNICALL Java_mypackage_MyWrapper_wrapFilterRawRequest
(JNIEnv *env, jobject obj, jstring config, jstring rawRequest)
{
    jint status = 0;

    const char *conf, *req;
    char *conf_copy, *req_copy;

    conf = (env)->GetStringUTFChars(config, NULL);
    req  = (env)->GetStringUTFChars(rawRequest, NULL);

    copy_str(&conf_copy, conf);
    copy_str(&req_copy, req);

    (env)->ReleaseStringUTFChars(config, conf);
    (env)->ReleaseStringUTFChars(rawRequest, req);

    status = processRequest(conf_copy , req_copy );   
    return status;
}

问题

当我在 JAVA 中调用本机函数两次时,它会给我一个错误,因为它相当于连续两次调用 C 函数 processRequest(char*, char*),我的应用程序不支持。我希望每次都能独立调用它,类似于两次运行可执行文件时的情况。(程序在被调用两次时有效,但在同一个应用程序中同一个函数被调用两次时无效)。我希望 JNI 在进行本机调用时重新初始化所有内容。我怎样才能做到这一点?

4

1 回答 1

5

嗯,您可以尝试从 JVM 中卸载 dll,方法是使用您自己ClassLoader的加载必要的类来执行您需要的操作,将值设置为null然后调用System.gc()以消除实例及其 dll 的旧痕迹,然后将 dll 重新加载到 JVM通过重新初始化实例:

package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 *
 * @author David
 */
public class Test {

    static {
         System.loadLibrary("mydll.dll");
    }

    @Override
    public void finalize() {
        System.out.println("A garbage collected");
    }

    public void print(String str, int value) {
        System.out.println(str);
        System.out.println(value);
    }

    public static int getNumber() {
        return 42;
    }

    public static void main(String[] args) throws Exception {
        Class<?> clazz = Test.class;//class name goes here
        // static call
        Method getNumber = clazz.getMethod("getNumber");
        int i = (Integer) getNumber.invoke(null /*
                 * static
                 */);
        // instance call
        Constructor<?> ctor = clazz.getConstructor();
        Object instance = ctor.newInstance();
        Method print = clazz.getMethod("print", String.class, Integer.TYPE);
        print.invoke(instance, "Hello, World!", i);
        print = null;
        instance = null;
        ctor = null;
        getNumber = null;
        clazz = null;
        i = 0;
        System.gc();  //reload by empting garbage   Class<?> clazz = Test.class;//class name goes here

        clazz = Test.class;//class name goes here
        // static call
        getNumber = clazz.getMethod("getNumber");
        i = (Integer) getNumber.invoke(null /*
                 * static
                 */);
        // instance call
        ctor = clazz.getConstructor();
        instance = ctor.newInstance();
        print = clazz.getMethod("print", String.class, Integer.TYPE);
        print.invoke(instance, "Hello, World!", i);
        print = null;
        instance = null;
        ctor = null;
        getNumber = null;
        clazz = null;
        i = 0;
        System.gc();  //reload by empting garbage
    }
}

参考:

于 2012-08-13T18:24:10.920 回答