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 ラッパー

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 でネイティブ関数を 2 回呼び出すと、アプリケーションでサポートされていない C 関数 processRequest(char*, char*) を連続して 2 回呼び出すのと同じことになるため、エラーが発生します。実行可能ファイルを 2 回実行するときと同様に、毎回スタンドアロンで呼び出せるようにしたいと考えています。(プログラムは 2 回呼び出された場合は機能しますが、同じアプリケーションで同じ関数が 2 回呼び出された場合は機能しません)。ネイティブ呼び出しを行うときに、JNI がすべてを再初期化するようにします。これどうやってするの?

4

1 に答える 1

5

うーん、JVM から dll をアンロードしてみることもできます。独自のクラスを使用しClassLoaderて必要なクラスをロードし、値を に設定してから、インスタンスとその dll の古いトレースを取り除くためnullに呼び出し、次に dll を JVM にリロードします。System.gc()インスタンスを再初期化することにより:

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 に答える