QiuYucheng2003 opened a new issue, #4403:
URL: https://github.com/apache/carbondata/issues/4403

   ## Summary
   
   `sdk/CSDK/src/Configuration.cpp` leaks JNI local references.
   
   CSDK takes a caller-supplied `JNIEnv*` (typically after `JNI_CreateJavaVM` / 
`AttachCurrentThread`). Local refs on that thread are **not** freed when a C++ 
function returns. `get`/`set` never delete the `NewStringUTF` arguments; the 
constructor keeps `FindClass` / `NewObject` results as member fields without 
promoting them to global refs, and there is no destructor.
   
   ## Affected code
   
   
[`sdk/CSDK/src/Configuration.cpp`](https://github.com/apache/carbondata/blob/f86ac085ddbbd8381b0a5b65658731fe618eff4a/sdk/CSDK/src/Configuration.cpp)
   
   ## 1. `get` / `set` — `jstring` arguments never released (main leak)
   
   ```cpp
   jvalue args[2];
   args[0].l = jniEnv->NewStringUTF(key);
   args[1].l = jniEnv->NewStringUTF(value);
   jniEnv->CallObjectMethodA(configurationObject, setID, args);
   // args[0].l and args[1].l never DeleteLocalRef'd
   
   get only deletes the return value:
   
   jobject result = jniEnv->CallObjectMethodA(configurationObject, getID, args);
   char *str = (char *) jniEnv->GetStringUTFChars((jstring) result, JNI_FALSE);
   jniEnv->DeleteLocalRef(result);  // key/defaultValue jstrings still leaked
   return str;
   
   Each set/get leaves two extra local refs in the table. Loading many 
Hadoop/S3 properties will accumulate them until the thread detaches.
   
   2. Constructor — local refs stored as members
   
   configurationClass = env->FindClass("org/apache/hadoop/conf/Configuration");
   configurationObject = jniEnv->NewObject(configurationClass, initID);
   
   These are kept in Configuration.h as fields and reused by get/set. They must 
be global refs (NewGlobalRef then DeleteLocalRef on the originals). As written 
they occupy local-ref table slots for the object's lifetime.
   
   CarbonSchemaReader::readSchema also constructs a stack Configuration 
conf(jniEnv) and never releases those refs, so each call leaks two more.
   
   There is no ~Configuration() to DeleteGlobalRef even after a correct 
promotion.
   
   Note: after NewObject, the null check still tests configurationClass instead 
of configurationObject.
   
   Suggested fix
   After CallObjectMethodA, release the argument strings:
   
   jniEnv->DeleteLocalRef(args[0].l);
   jniEnv->DeleteLocalRef(args[1].l);
   
   In the constructor:
   
   jclass localClass = env->FindClass("org/apache/hadoop/conf/Configuration");
   configurationClass = (jclass) env->NewGlobalRef(localClass);
   env->DeleteLocalRef(localClass);
   
   jobject localObj = env->NewObject(configurationClass, initID);
   configurationObject = env->NewGlobalRef(localObj);
   env->DeleteLocalRef(localObj);
   
   Add a destructor that DeleteGlobalRefs both. Prefer a small RAII wrapper so 
throws cannot skip cleanup.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to