JNI local-reference accumulation in the string array helpers
- Lingua principale
- Java
- Stelle
- 94
- Fork
- 152
- Merge medio
- 3g 16h
- PR unite (30g)
- 11
Descrizione
### Describe the bug, including details regarding any error messages, version, and platform.
There is a JNI local-reference issue in the dataset helpers that convert Java `String[]` arrays into C++ containers. They get each element with `GetObjectArrayElement()` and convert it, but never delete the resulting local reference.
Files:
- `dataset/src/main/cpp/jni_util.cc`
- `dataset/src/main/cpp/jni_wrapper.cc`
Functions:
- `ToStringVector` (`jni_util.cc`)
- `ToStringMap`, `LoadNamedTables` (`jni_wrapper.cc`)
Relevant code in `ToStringVector()`:
```cpp
std::vector ToStringVector(JNIEnv* env, jobjectArray& str_array) {
int length = env->GetArrayLength(str_array);
std::vector vector;
for (int i = 0; i < length; i++) {
auto string = reinterpret_cast(env->GetObjectArrayElement(str_array, i));
vector.push_back(JStringToCString(env, string));
}
return vector;
}
```
`JStringToCString()` does correctly release the native UTF chars it acquires:
```cpp
const char* chars = env->GetStringUTFChars(string, nullptr);
std::string ret(chars);
env->ReleaseStringUTFChars(string, chars);
return ret;
```
but that release only matches `GetStringUTFChars()`. It does not delete the `jstring` local reference that `GetObjectArrayElement()` returned, so one reference remains live per element until the native method returns.
`ToStringMap()` has the same pattern with two references per iteration:
```cpp
for (int i = 0; i < length; i += 2) {
auto key = reinterpret_cast(env->GetObjectArrayElement(str_array, i));
auto value = reinterpret_cast(env->GetObjectArrayElement(str_array, i + 1));
map[JStringToCString(env, key)] = JStringToCString(env, value);
}
```
`LoadNamedTables()` also takes two per iteration, and has three `JniThrow()` exits inside the loop body — the odd-length check and the two `std::stol` failure handlers — so on those paths the references acquired in the current iteration are abandoned mid-loop.
These are local references, so they are reclaimed when the native method returns, and the inputs are option maps, partition columns, and named-table lists — typically tens of entries. There is no observable leak or reachable failure here; the reference count is simply higher than necessary for the duration of the call.
Suggested fix:
```cpp
auto string = reinterpret_cast(env->GetObjectArrayElement(str_array, i));
vector.push_back(JStringToCString(env, string));
env->DeleteLocalRef(string);
```
For the key/value loops, delete both `key` and `value`, including on the `JniThrow()` paths in `LoadNamedTables()`.
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
Inizia leggendo ToStringVector in dataset/src/main/cpp/jni_util.cc e ToStringMap e LoadNamedTables in dataset/src/main/cpp/jni_wrapper.cc, concentrandoti su ogni chiamata a GetObjectArrayElement. Assicurati che ogni riferimento locale acquisito venga eliminato nei percorsi normali e nei percorsi JniThrow(); il lavoro è completato quando non rimangono riferimenti dell’iterazione corrente abbandonati.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- cpp, java
- Ambito
- backend
- Tipo di issue
- Bug
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Stato di attività
- Tranquilla
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 75/100