This is an automated email from the ASF dual-hosted git repository.
jinrongtong pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/rocketmq.git
The following commit(s) were added to refs/heads/develop by this push:
new 7a1a9501ca [ISSUE# 9841] Improve Resource Management in TimerWheel to
Prevent File Handle Leaks (#9842)
7a1a9501ca is described below
commit 7a1a9501cab8ff74b1a4aaecb2f22235eef66616
Author: guyinyou <[email protected]>
AuthorDate: Wed Nov 12 15:22:59 2025 +0800
[ISSUE# 9841] Improve Resource Management in TimerWheel to Prevent File
Handle Leaks (#9842)
* fix: fix file handle leak in TimerWheel
- Move RandomAccessFile and FileChannel to instance variables
- Close FileChannel in shutdown() method instead of constructor finally
block
- This ensures proper resource cleanup and prevents file handle leaks
Change-Id: If6f0bdd555e5f6fdd5c44ca8404f7918b45cf67b
Co-developed-by: Cursor <[email protected]>
* fix
Change-Id: Icf8f6c316208f8e38421013f2d7b7028f56d5259
* fix
Change-Id: I9ed022b94fca31f005e71afe92a0374265f6ea11
* fix
Change-Id: Ibfd499652378710ccc7b5632370a77ab5dc4b8f3
---------
Co-authored-by: guyinyou <[email protected]>
---
.../apache/rocketmq/store/timer/TimerWheel.java | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git
a/store/src/main/java/org/apache/rocketmq/store/timer/TimerWheel.java
b/store/src/main/java/org/apache/rocketmq/store/timer/TimerWheel.java
index 261d8f6a3d..2d5ce38201 100644
--- a/store/src/main/java/org/apache/rocketmq/store/timer/TimerWheel.java
+++ b/store/src/main/java/org/apache/rocketmq/store/timer/TimerWheel.java
@@ -43,7 +43,9 @@ public class TimerWheel {
public final int slotsTotal;
public final int precisionMs;
private final String fileName;
- private MappedByteBuffer mappedByteBuffer;
+ private final MappedByteBuffer mappedByteBuffer;
+ private final RandomAccessFile randomAccessFile;
+ private final FileChannel fileChannel;
private final ByteBuffer byteBuffer;
private final ThreadLocal<ByteBuffer> localBuffer = new
ThreadLocal<ByteBuffer>() {
@Override
@@ -69,7 +71,6 @@ public class TimerWheel {
File file = new File(finalFileName);
UtilAll.ensureDirOK(file.getParent());
- RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(finalFileName, "rw");
if (file.exists() && randomAccessFile.length() != 0 &&
@@ -79,8 +80,13 @@ public class TimerWheel {
}
randomAccessFile.setLength(wheelLength);
if (snapOffset < 0) {
- mappedByteBuffer =
randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0,
wheelLength);
+ fileChannel = randomAccessFile.getChannel();
+ mappedByteBuffer =
fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, wheelLength);
assert wheelLength == mappedByteBuffer.remaining();
+ } else {
+ fileChannel = null;
+ mappedByteBuffer = null;
+ randomAccessFile.close();
}
this.byteBuffer = ByteBuffer.allocateDirect(wheelLength);
this.byteBuffer.put(Files.readAllBytes(file.toPath()));
@@ -90,10 +96,6 @@ public class TimerWheel {
} catch (IOException e) {
log.error("map file " + finalFileName + " Failed. ", e);
throw e;
- } finally {
- if (randomAccessFile != null) {
- randomAccessFile.close();
- }
}
}
@@ -114,6 +116,12 @@ public class TimerWheel {
UtilAll.cleanBuffer(this.mappedByteBuffer);
UtilAll.cleanBuffer(this.byteBuffer);
localBuffer.remove();
+
+ try {
+ this.fileChannel.close();
+ } catch (Throwable t) {
+ log.error("Shutdown error in timer wheel", t);
+ }
}
public void flush() {