java - Shall jarrayObject (array of strings) be deleted/released after usage in a JNI call ? -


i'm experimenting in c++ jni , have doubt java object i've created in c++ being used jni call argument.

take simple java class, string array argument:

public class mytest {     public static void main(string[] args) {         system.out.println("hello, world in java");         int i;          (i=0; i<args.length; i++)             system.out.println(args[i]);             } } 

i call c++ following jni code:

jmethodid mid3 = env->getstaticmethodid(cls2, "main", "([ljava/lang/string;)v"); // signature string array arg. if(mid3 == nullptr)      cerr << "error: method not found !" << endl; else {      jobjectarray arr = env->newobjectarray(5,   // constructs java array of 5              env->findclass("java/lang/string"),                 env->newstringutf("str"));   // default value      env->setobjectarrayelement(             // change 1 of array elements              arr, 1, env->newstringutf("myownstring"));      env->callstaticvoidmethod(cls2, mid3, arr); // call method } 

this works well. i'm unsure have to jarrayobject (and java strings contains) afterwards, keep things clean.

my understanding jvm responsible java objects. how know objectsz no longer need on c++ side ? googled around , didn't find clear explanation. read in jni specifications deletelocalref() that:

local references valid duration of native method call. freed automatically after native method returns.

so shall call deletelocalref() jarrayobject (or every java string contains) or other cleaning function ? or can assume jvm takes care of on own ?

the jni design specs (see section global , local references) explains that:

  • all references passed native method references returned jni functions local references;
  • these local references automatically freed after native method returns.

however, principle applies case of c++ function called java: local references released when function returns java (see section implementing local references).

if create objects or references jni functions in c++ code not called java, local references not freed automatically, causing memory leak.

so should better use deletelocalref() free java objects created/obtained c++ no longer used.

demonsration:

the following simple java code allocates big objects without keeping references, , call memory inspection:

class bigmemoryconsumer {     private char mytable[];         public bigmemoryconsumer () {   // allocate , use 1mb          mytable = new char[1048576];         (int i=0; i<1048576; i++)              mytable[i] = (char) (i % 256);       }      public static long showmem() {  // show memory statistics          int funit = 1024*1024;         string unit =  " mb";          runtime runtime = runtime.getruntime();         system.gc();    // opportunity run garbage collector (not guaranteed !)           long used = runtime.totalmemory() - runtime.freememory();         system.out.println("used memory:  " + used / funit + unit              + " ("+ (used*100/runtime.maxmemory())+"%)");         system.out.println("free memory:  " + runtime.freememory() / funit + unit);         system.out.println("total memory: " + runtime.totalmemory() / funit + unit);         system.out.println("max memory:   " + runtime.maxmemory() / funit + unit);         system.out.println("");         return used;        }      public static void main (string[] args) {     // test in java         long lastmem = showmem();          (int i=0; i<256; i++) {             bigmemoryconsumer m = new bigmemoryconsumer();              long mem = showmem();              if (mem<=lastmem) {                 system.out.println ("garbage collector freed memory");                  return;              }             else lastmem = mem;         }     } } 

when run class directly java (aka main()) you'll notice java quicly (second or third iteration on 64bit system) run garbage collector: object m reinitialised on every iteration, meaning created objects no longer referenced.

now i've reproduced equivalent main() in c++ code, after having loaded jvm , initialized jni environment:

jclass cls = env->findclass("bigmemoryconsumer"); jmethodid ctor = env->getmethodid(cls, "<init>", "()v");    // find consructor  jmethodid show = env->getstaticmethodid(cls, "showmem", "()j");  // find memshow()   jlong lastmem = 0; vector<jobject> v; for(int = 0; < 256; i++) {     jobject myo = env->newobject(cls, ctor);     v.push_back(myo);     jlong mem = env->callstaticlongmethod(cls, show);     if(mem <= lastmem) {         cout << "attention:  garbage collector called consumed java memory didn't increase after "<<i<<" iterations\n";         break;     }     else lastmem = mem;     //env->deletelocalref(myo); ///!!!! <======= see text  } 

if running code without deletelocalref(), you'll notice continuous increase in consumed memory: no garbage collection takes place, jvm not aware reference java object requested c++ no longe used.

if comment out highlighted line, deletelocalref() tell jvm object no longer needed in c++ code, , garbage collector behave in pure java example, rfreeing object after couple of iterations.


Comments

Popular posts from this blog

c++ - Difference between pre and post decrement in recursive function argument -

php - Nothing but 'run(); ' when browsing to my local project, how do I fix this? -

php - How can I echo out this array? -