This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new 0e1d0beab fix(java/driver/jni): check for pending exceptions more
thoroughly (#4398)
0e1d0beab is described below
commit 0e1d0beab6a4b9bded58f9d2edc94bc6e4d51e7a
Author: David Li <[email protected]>
AuthorDate: Tue Jun 23 15:13:59 2026 -0700
fix(java/driver/jni): check for pending exceptions more thoroughly (#4398)
After JNI calls that can leave a pending Java exception (GetArrayLength,
GetObjectArrayElement, GetIntArrayRegion, GetByteArrayRegion,
NewByteArray, SetByteArrayRegion) and are followed by further JNI or
native ADBC work, check env->ExceptionCheck() and return the function's
existing error default, letting the pending exception propagate to Java
rather than performing more work or raising a second exception.
Generated-by: Claude Opus 4.8 <[email protected]>
---
java/driver/jni/src/main/cpp/jni_wrapper.cc | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/java/driver/jni/src/main/cpp/jni_wrapper.cc
b/java/driver/jni/src/main/cpp/jni_wrapper.cc
index c76e70f0c..6221a60cb 100644
--- a/java/driver/jni/src/main/cpp/jni_wrapper.cc
+++ b/java/driver/jni/src/main/cpp/jni_wrapper.cc
@@ -414,6 +414,7 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_openDatabase(
jclass nativeHandleKlass = RequireImplClass(env, "NativeDatabaseHandle");
jmethodID nativeHandleCtor = RequireMethod(env, nativeHandleKlass,
"<init>", "(J)V");
const jsize num_params = env->GetArrayLength(parameters);
+ if (env->ExceptionCheck()) return nullptr;
if (num_params % 2 != 0) {
throw AdbcException{
.code = ADBC_STATUS_INVALID_ARGUMENT,
@@ -431,8 +432,10 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_openDatabase(
for (jsize i = 0; i < num_params; i += 2) {
// N.B. assuming String because Java side is typed as String[]
auto key =
reinterpret_cast<jstring>(env->GetObjectArrayElement(parameters, i));
+ if (env->ExceptionCheck()) return nullptr;
auto value =
reinterpret_cast<jstring>(env->GetObjectArrayElement(parameters, i +
1));
+ if (env->ExceptionCheck()) return nullptr;
JniStringView key_str(env, key);
JniStringView value_str(env, value);
@@ -820,8 +823,10 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_statementGetOptionBytes(
return nullptr;
}
jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
+ if (result == nullptr || env->ExceptionCheck()) return nullptr;
env->SetByteArrayRegion(result, 0, static_cast<jsize>(length),
reinterpret_cast<const jbyte*>(buf.data()));
+ if (env->ExceptionCheck()) return nullptr;
return result;
}
@@ -899,9 +904,11 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_statementSetOptionBytes(
try {
JniStringView key_str(env, key);
jsize value_length = env->GetArrayLength(value);
+ if (env->ExceptionCheck()) return;
std::vector<uint8_t> value_buf(static_cast<size_t>(value_length));
env->GetByteArrayRegion(value, 0, value_length,
reinterpret_cast<jbyte*>(value_buf.data()));
+ if (env->ExceptionCheck()) return;
CHECK_ADBC_ERROR(AdbcStatementSetOptionBytes(stmt, key_str.value,
value_buf.data(),
value_buf.size(),
&error_guard.value),
error_guard.value);
@@ -997,11 +1004,13 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_connectionGetObjects(
const char** c_table_types = nullptr;
if (table_types != nullptr) {
jsize len = env->GetArrayLength(table_types);
+ if (env->ExceptionCheck()) return nullptr;
table_type_strings.reserve(len);
table_type_ptrs.reserve(len + 1);
for (jsize i = 0; i < len; i++) {
auto element =
reinterpret_cast<jstring>(env->GetObjectArrayElement(table_types,
i));
+ if (env->ExceptionCheck()) return nullptr;
table_type_strings.push_back(GetJniString(env, element));
table_type_ptrs.push_back(table_type_strings.back().c_str());
}
@@ -1040,9 +1049,11 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_connectionGetInfo(
std::vector<uint32_t> info_codes_vec;
if (info_codes != nullptr) {
jsize len = env->GetArrayLength(info_codes);
+ if (env->ExceptionCheck()) return nullptr;
info_codes_vec.resize(len);
env->GetIntArrayRegion(info_codes, 0, len,
reinterpret_cast<jint*>(info_codes_vec.data()));
+ if (env->ExceptionCheck()) return nullptr;
c_info_codes = info_codes_vec.data();
info_codes_length = static_cast<size_t>(len);
}
@@ -1133,8 +1144,10 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_connectionGetOptionBytes(
return nullptr;
}
jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
+ if (result == nullptr || env->ExceptionCheck()) return nullptr;
env->SetByteArrayRegion(result, 0, static_cast<jsize>(length),
reinterpret_cast<const jbyte*>(buf.data()));
+ if (env->ExceptionCheck()) return nullptr;
return result;
}
@@ -1212,9 +1225,11 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_connectionSetOptionBytes(
try {
JniStringView key_str(env, key);
jsize value_length = env->GetArrayLength(value);
+ if (env->ExceptionCheck()) return;
std::vector<uint8_t> value_buf(static_cast<size_t>(value_length));
env->GetByteArrayRegion(value, 0, value_length,
reinterpret_cast<jbyte*>(value_buf.data()));
+ if (env->ExceptionCheck()) return;
CHECK_ADBC_ERROR(AdbcConnectionSetOptionBytes(conn, key_str.value,
value_buf.data(),
value_buf.size(),
&error_guard.value),
error_guard.value);
@@ -1395,8 +1410,10 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_databaseGetOptionBytes(
return nullptr;
}
jbyteArray result = env->NewByteArray(static_cast<jsize>(length));
+ if (result == nullptr || env->ExceptionCheck()) return nullptr;
env->SetByteArrayRegion(result, 0, static_cast<jsize>(length),
reinterpret_cast<const jbyte*>(buf.data()));
+ if (env->ExceptionCheck()) return nullptr;
return result;
}
@@ -1474,9 +1491,11 @@
Java_org_apache_arrow_adbc_driver_jni_impl_NativeAdbc_databaseSetOptionBytes(
try {
JniStringView key_str(env, key);
jsize value_length = env->GetArrayLength(value);
+ if (env->ExceptionCheck()) return;
std::vector<uint8_t> value_buf(static_cast<size_t>(value_length));
env->GetByteArrayRegion(value, 0, value_length,
reinterpret_cast<jbyte*>(value_buf.data()));
+ if (env->ExceptionCheck()) return;
CHECK_ADBC_ERROR(AdbcDatabaseSetOptionBytes(db, key_str.value,
value_buf.data(),
value_buf.size(),
&error_guard.value),
error_guard.value);