This is an automated email from the ASF dual-hosted git repository.

morrysnow pushed a commit to branch branch-3.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.1 by this push:
     new 9aff673894b branch-3.1:  [fix](jdbc) Fix JNI global reference leak in 
JdbcConnector close #58574 (#58752)
9aff673894b is described below

commit 9aff673894b2f88b6ea293c3a1dcbb810cc06cf3
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Dec 5 18:22:26 2025 +0800

    branch-3.1:  [fix](jdbc) Fix JNI global reference leak in JdbcConnector 
close #58574 (#58752)
    
    Cherry-picked from #58574
    
    Co-authored-by: zy-kkk <[email protected]>
---
 be/src/vec/exec/vjdbc_connector.cpp                | 50 +++++++++++++++++-----
 .../org/apache/doris/jdbc/BaseJdbcExecutor.java    | 19 ++++++--
 2 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/be/src/vec/exec/vjdbc_connector.cpp 
b/be/src/vec/exec/vjdbc_connector.cpp
index d4cf31f4f78..d55dd4b48e1 100644
--- a/be/src/vec/exec/vjdbc_connector.cpp
+++ b/be/src/vec/exec/vjdbc_connector.cpp
@@ -68,23 +68,51 @@ JdbcConnector::~JdbcConnector() {
 
 Status JdbcConnector::close(Status /*unused*/) {
     SCOPED_RAW_TIMER(&_jdbc_statistic._connector_close_timer);
-    _closed = true;
+    if (_closed) {
+        return Status::OK();
+    }
     if (!_is_open) {
+        _closed = true;
         return Status::OK();
     }
+
+    JNIEnv* env = nullptr;
+    Status status = JniUtil::GetJNIEnv(&env);
+    if (!status.ok() || env == nullptr) {
+        LOG(WARNING) << "Failed to get JNIEnv in close(): " << 
status.to_string();
+        _closed = true;
+        return status;
+    }
+
+    // Try to abort transaction and call Java close(), but don't block cleanup
     if (_is_in_transaction) {
-        RETURN_IF_ERROR(abort_trans());
+        Status abort_status = abort_trans();
+        if (!abort_status.ok()) {
+            LOG(WARNING) << "Failed to abort transaction: " << 
abort_status.to_string();
+        }
     }
-    JNIEnv* env = nullptr;
-    RETURN_IF_ERROR(JniUtil::GetJNIEnv(&env));
+
     env->CallNonvirtualVoidMethod(_executor_obj, _executor_clazz, 
_executor_close_id);
-    RETURN_ERROR_IF_EXC(env);
-    env->DeleteGlobalRef(_executor_factory_clazz);
-    RETURN_ERROR_IF_EXC(env);
-    env->DeleteGlobalRef(_executor_clazz);
-    RETURN_IF_ERROR(JniUtil::GetJniExceptionMsg(env));
-    env->DeleteGlobalRef(_executor_obj);
-    RETURN_ERROR_IF_EXC(env);
+    if (env->ExceptionCheck()) {
+        LOG(WARNING) << "Java close() failed: " << 
JniUtil::GetJniExceptionMsg(env).to_string();
+        env->ExceptionClear();
+    }
+
+    // Always delete Global References to allow Java GC
+    if (_executor_factory_clazz != nullptr) {
+        env->DeleteGlobalRef(_executor_factory_clazz);
+        _executor_factory_clazz = nullptr;
+    }
+    if (_executor_clazz != nullptr) {
+        env->DeleteGlobalRef(_executor_clazz);
+        _executor_clazz = nullptr;
+    }
+    if (_executor_obj != nullptr) {
+        env->DeleteGlobalRef(_executor_obj);
+        _executor_obj = nullptr;
+    }
+
+    _closed = true;
     return Status::OK();
 }
 
diff --git 
a/fe/be-java-extensions/jdbc-scanner/src/main/java/org/apache/doris/jdbc/BaseJdbcExecutor.java
 
b/fe/be-java-extensions/jdbc-scanner/src/main/java/org/apache/doris/jdbc/BaseJdbcExecutor.java
index 3e71cc5abdd..151e9cffe1a 100644
--- 
a/fe/be-java-extensions/jdbc-scanner/src/main/java/org/apache/doris/jdbc/BaseJdbcExecutor.java
+++ 
b/fe/be-java-extensions/jdbc-scanner/src/main/java/org/apache/doris/jdbc/BaseJdbcExecutor.java
@@ -127,7 +127,11 @@ public abstract class BaseJdbcExecutor implements 
JdbcExecutor {
 
     public void close() throws Exception {
         if (outputTable != null) {
-            outputTable.close();
+            try {
+                outputTable.close();
+            } finally {
+                outputTable = null;
+            }
         }
         try {
             if (stmt != null && !stmt.isClosed()) {
@@ -143,10 +147,17 @@ public abstract class BaseJdbcExecutor implements 
JdbcExecutor {
             }
         } finally {
             closeResources(resultSet, stmt, conn);
+            // Always clear references to help GC, even if close() failed
+            resultSet = null;
+            stmt = null;
+            conn = null;
             if (config.getConnectionPoolMinSize() == 0 && hikariDataSource != 
null) {
-                hikariDataSource.close();
-                
JdbcDataSource.getDataSource().getSourcesMap().remove(config.createCacheKey());
-                hikariDataSource = null;
+                try {
+                    hikariDataSource.close();
+                    
JdbcDataSource.getDataSource().getSourcesMap().remove(config.createCacheKey());
+                } finally {
+                    hikariDataSource = null;
+                }
             }
         }
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to