获取 FileChannel 的 Linux 个文件描述符
Get Linux file descriptor of FileChannel
有没有办法为打开的 FileChannel 获取 Linux 文件描述符?
我需要它来调用 mount.fuse -o fd=...
(用于实现 FUSE)。
作为一个 hacky 解决方法,我正在做:
var pid = ProcessHandle.current().pid();
var fd = Files.list(Path.of("/proc/"+pid+"/fd")).count();
var fc = FileChannel.open(path);
System.out.println("file descriptor: " + fd);
请注意,出现了两个文件描述符。一个用于 path
,另一个用于 socket
。我用的是第一个。插座有什么用?
您可以使用反射从 RandomAccessFile
:
中获取文件描述符
long pid = ProcessHandle.current().pid();
long guessedFd = Files.list(Path.of("/proc/"+pid+"/fd")).count();
var file = new java.io.RandomAccessFile(FUSE_DEVICE_PATH.toFile(), "rw");
FileChannel fc = file.getChannel(); // Use FileChannel for fast NIO
var javaFd = file.getFD();
try {
Field f = FileDescriptor.class.getDeclaredField("fd");
f.setAccessible(true);
var trueFd = (int) f.get(javaFd);
return trueFd;
}
catch (InaccessibleObjectException | NoSuchFieldException | IllegalAccessException e) {
return guessedFd;
}
在 Java 11+ 上,您将在启动时选择 jvm 选项 --add-opens=java.base/java.io=ALL-UNNAMED
。在 Java 18.
上测试
在 Java 17 中你可以使用 SharedSecrets
而不是反射:
FileDescriptor javaFd = ...
try {
int trueFd = jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess().get(javaFd);
return trueFd;
}
catch (IllegalAccessError e) {
return guessedFd;
}
编译时需要加上--add-exports=java.base/jdk.internal.access=ALL-UNNAMED
和运行。参见 for Maven。
有没有办法为打开的 FileChannel 获取 Linux 文件描述符?
我需要它来调用 mount.fuse -o fd=...
(用于实现 FUSE)。
作为一个 hacky 解决方法,我正在做:
var pid = ProcessHandle.current().pid();
var fd = Files.list(Path.of("/proc/"+pid+"/fd")).count();
var fc = FileChannel.open(path);
System.out.println("file descriptor: " + fd);
请注意,出现了两个文件描述符。一个用于 path
,另一个用于 socket
。我用的是第一个。插座有什么用?
您可以使用反射从 RandomAccessFile
:
long pid = ProcessHandle.current().pid();
long guessedFd = Files.list(Path.of("/proc/"+pid+"/fd")).count();
var file = new java.io.RandomAccessFile(FUSE_DEVICE_PATH.toFile(), "rw");
FileChannel fc = file.getChannel(); // Use FileChannel for fast NIO
var javaFd = file.getFD();
try {
Field f = FileDescriptor.class.getDeclaredField("fd");
f.setAccessible(true);
var trueFd = (int) f.get(javaFd);
return trueFd;
}
catch (InaccessibleObjectException | NoSuchFieldException | IllegalAccessException e) {
return guessedFd;
}
在 Java 11+ 上,您将在启动时选择 jvm 选项 --add-opens=java.base/java.io=ALL-UNNAMED
。在 Java 18.
在 Java 17 中你可以使用 SharedSecrets
而不是反射:
FileDescriptor javaFd = ...
try {
int trueFd = jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess().get(javaFd);
return trueFd;
}
catch (IllegalAccessError e) {
return guessedFd;
}
编译时需要加上--add-exports=java.base/jdk.internal.access=ALL-UNNAMED
和运行。参见 for Maven。