From 25744b508d2b5e5ed45668c3f4d868816d46015d Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 26 May 2026 17:07:20 +0800 Subject: [PATCH] [Fix][Connector-V2] Fix Arrow memory leak by correcting close order in ArrowToSeatunnelRowReader Close arrowStreamReader before rootAllocator to prevent memory leak. ArrowStreamReader internally closes VectorSchemaRoot and releases all Arrow buffer allocations back to the allocator. The previous order closed rootAllocator while arrowStreamReader still held unreleased buffers, causing IllegalStateException: Memory was leaked by query (issue #9863). Fix: #9863 --- .../arrow/reader/ArrowToSeatunnelRowReader.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/arrow/reader/ArrowToSeatunnelRowReader.java b/seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/arrow/reader/ArrowToSeatunnelRowReader.java index f7821ed5fdd7..2609a591eec1 100644 --- a/seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/arrow/reader/ArrowToSeatunnelRowReader.java +++ b/seatunnel-connectors-v2/connector-common/src/main/java/org/apache/seatunnel/connectors/seatunnel/common/source/arrow/reader/ArrowToSeatunnelRowReader.java @@ -320,15 +320,17 @@ private Function genericsConvert(SeaTunnelDataType dataType) { @Override public void close() { try { - if (root != null) { - root.close(); + // ArrowStreamReader must be closed before RootAllocator. + // ArrowStreamReader internally closes VectorSchemaRoot and releases all Arrow + // buffer allocations back to the allocator. If the allocator is closed first, + // it detects unreleased memory and throws IllegalStateException ("Memory was + // leaked by query"), which is the root cause of issue #9863. + if (arrowStreamReader != null) { + arrowStreamReader.close(); } if (rootAllocator != null) { rootAllocator.close(); } - if (arrowStreamReader != null) { - arrowStreamReader.close(); - } } catch (IOException e) { throw new RuntimeException("failed to close arrow stream reader.", e); }