You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JaCoP JNI: local refs from model conversion are never released (Invocation API) #283
The JaCoP solver embeds a JVM (JNI_CreateJavaVM in solvers/jacop/java.cc) and keeps JNIEnv for the process lifetime. Local references are not freed when C++ functions return. They live until DeleteLocalRef / PopLocalFrame / DestroyJavaVM.
Model conversion creates one local ref per Java IntVar / constraint and never deletes it. Cached jclass values from FindClass are also stored as members without NewGlobalRef.
for (int j = 0; j < num_vars; ++j) {
jobject jvar = var_class_.NewObject(env_, store_, ...);
vars_[j] = jvar;
env_.SetObjectArrayElement(var_array_, j, jvar);
// missing: DeleteLocalRef(jvar) after the array holds it,// or NewGlobalRef if vars_[j] must outlive the current frame
}
ClassBase::NewObject → Env::NewObjectV returns a fresh local ref on every call. The same pattern is used for constraints, NewObjectArray, and NewIntArray. Local-ref count scales with problem size.
SetObjectArrayElement / store.impose already keep the Java objects alive. The extra local refs are unnecessary.
class_ = env.FindClass(Info::name()); // local ref kept as a member
Init() runs once per Class<>, so this is a small fixed set, but it should still be a global ref. ClassBase::~ClassBase() does not release class_.
solvers/jacop/java.ccEnv::NewObject(const char *class_name, ...) calls FindClass and never DeleteLocalRef on the jclass. Used a few times per solve (e.g. SimpleSelect), not in the variable loop.
The code already uses GlobalRef for search_ and obj_var, so the intended pattern exists; store_, vars_, and cached classes do not follow it.
Suggested fix
After SetObjectArrayElement / impose, DeleteLocalRef the temporary jobject (and temp arrays), orEnsureLocalCapacity / PushLocalFrame around Convert.
Promote long-lived refs (store_, vars_[i], cached class_) with NewGlobalRef; DeleteGlobalRef in the destructor.
In Env::NewObject(class_name, ...), DeleteLocalRef(cls) after NewObjectV.
Activity