Skip to content

Commit 7a1a950

Browse files
guyinyouguyinyou
andauthored
[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 <noreply@cursor.com> * fix Change-Id: Icf8f6c316208f8e38421013f2d7b7028f56d5259 * fix Change-Id: I9ed022b94fca31f005e71afe92a0374265f6ea11 * fix Change-Id: Ibfd499652378710ccc7b5632370a77ab5dc4b8f3 --------- Co-authored-by: guyinyou <guyinyou.gyy@alibaba-inc.com>
1 parent e2be0f2 commit 7a1a950

1 file changed

Lines changed: 15 additions & 7 deletions

File tree

store/src/main/java/org/apache/rocketmq/store/timer/TimerWheel.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ public class TimerWheel {
4343
public final int slotsTotal;
4444
public final int precisionMs;
4545
private final String fileName;
46-
private MappedByteBuffer mappedByteBuffer;
46+
private final MappedByteBuffer mappedByteBuffer;
47+
private final RandomAccessFile randomAccessFile;
48+
private final FileChannel fileChannel;
4749
private final ByteBuffer byteBuffer;
4850
private final ThreadLocal<ByteBuffer> localBuffer = new ThreadLocal<ByteBuffer>() {
4951
@Override
@@ -69,7 +71,6 @@ public TimerWheel(String fileName, int slotsTotal, int precisionMs, long snapOff
6971
File file = new File(finalFileName);
7072
UtilAll.ensureDirOK(file.getParent());
7173

72-
RandomAccessFile randomAccessFile = null;
7374
try {
7475
randomAccessFile = new RandomAccessFile(finalFileName, "rw");
7576
if (file.exists() && randomAccessFile.length() != 0 &&
@@ -79,8 +80,13 @@ public TimerWheel(String fileName, int slotsTotal, int precisionMs, long snapOff
7980
}
8081
randomAccessFile.setLength(wheelLength);
8182
if (snapOffset < 0) {
82-
mappedByteBuffer = randomAccessFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, wheelLength);
83+
fileChannel = randomAccessFile.getChannel();
84+
mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, wheelLength);
8385
assert wheelLength == mappedByteBuffer.remaining();
86+
} else {
87+
fileChannel = null;
88+
mappedByteBuffer = null;
89+
randomAccessFile.close();
8490
}
8591
this.byteBuffer = ByteBuffer.allocateDirect(wheelLength);
8692
this.byteBuffer.put(Files.readAllBytes(file.toPath()));
@@ -90,10 +96,6 @@ public TimerWheel(String fileName, int slotsTotal, int precisionMs, long snapOff
9096
} catch (IOException e) {
9197
log.error("map file " + finalFileName + " Failed. ", e);
9298
throw e;
93-
} finally {
94-
if (randomAccessFile != null) {
95-
randomAccessFile.close();
96-
}
9799
}
98100
}
99101

@@ -114,6 +116,12 @@ public void shutdown(boolean flush) {
114116
UtilAll.cleanBuffer(this.mappedByteBuffer);
115117
UtilAll.cleanBuffer(this.byteBuffer);
116118
localBuffer.remove();
119+
120+
try {
121+
this.fileChannel.close();
122+
} catch (Throwable t) {
123+
log.error("Shutdown error in timer wheel", t);
124+
}
117125
}
118126

119127
public void flush() {

0 commit comments

Comments
 (0)