4

Background

I have a native function in 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");
    }

}

and a JNI Wrapper in C for the same

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

Problem

When I call the native function twice in JAVA it gives me an error because it is equivalent to calling the C function processRequest(char*, char*) twice in a row, which is not supported by my application. I want to be able to call it standalone every time, similar to how it is when you run an executable twice. (The program works when it is called twice, but not when the same function is called twice in the same application). I want JNI to re-initialize everything when it makes the native call. How can I do this?

varrunr
  • 845
  • 1
  • 11
  • 19

1 Answers1

5

Hmm well you could try unloading the dll from the JVM by using your own ClassLoader to load the necessary class doing what you need, setting values to null then callingSystem.gc() to get rid of old traces of the instance and its dll, then reloading the dll into the JVM by reinitilaizing the instance:

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

Reference:

Community
  • 1
  • 1
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • I need to call a method. From the [reference](http://codethesis.com/sites/default/index.php?servlet=4&content=2), I need to use aClass.getMethod("",parameters). My experience with JAVA is limited. Can you help me out as to how I can pass the second parameter to it(since I have arguments - 2 strings)? It expects an array of Class objects(parameters). – varrunr Aug 13 '12 at 21:24
  • The above code doesn't unload the shared library. I implemented the `jint JNI_OnUnload(JavaVM *vm, void *reserved)` function to check the same, and it does not get invoked. – varrunr Aug 14 '12 at 19:33
  • 1
    I think maybe the custom class loader is missing in the code extract above? – Mick Feb 24 '15 at 21:36