mirror of
https://github.com/apache/rocketmq.git
synced 2026-08-29 04:13:00 +08:00
[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>
This commit is contained in:
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user