使用Java编号的文件描述符

时间:2011-01-30 19:56:35

标签: java file-io freebsd

我需要从Java访问编号的文件描述符 - 不是0,1或2。

如何做到这一点?我查看了FileDescriptor类,但没有找到任何方法用给定的文件描述符编号初始化它。

作为一个具体的例子,假设Java从另一个编程语言被调用为子进程。文件描述符3和4由另一种语言提供,用于输入和输出。

我在Java中需要的是InputStreamOutputStream对象连接到这些文件描述符,就像System.in,System.out和System.error连接到文件解析器0,1和2.

我正在使用Java 1.6,这应该在类似Unix的系统上运行。

经过测试的工作解决方案:

文件描述符特殊文件系统条目的答案确实指出了以下可行的解决方案:

  1. 找出你的Unix系统是否以及在哪里有一个特殊的文件系统,其中包含所有文件描述符的命名条目。

    • 我正在使用FreeBSD,fdescfs(5)是一个文件系统。在Linux下,它将是procfs。
  2. 确保已安装此文件系统

    • FreeBSD:将fdescfs /dev/fd fdescfs rw 0 0放入/etc/fstab

      或在shell提示符下运行mount -t fdescfs null /dev/fd(可能使用sudo)

  3. 使用新的FileInputStream("/dev/fd/3")new FileOutputStream("/dev/fd/4")来获取连接到文件描述符的流(路径适用于FreeBSD,替换为您的操作系统路径)

4 个答案:

答案 0 :(得分:14)

我很确定使用纯Java无法做到这一点 - 您可能必须使用本机代码将文件描述符绑定到FileDescriptor对象或FileInputStream或FileOutputStream对象。

修改
如果您使用的是Linux,* BSD或macOS,则可以使用伪文件/ dev / fd / nnn来访问文件描述符nnn。

答案 1 :(得分:9)

使用SUN JavaVM,您可以:

FileDescriptor fd = new FileDescriptor();
sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess().set(fd,3);
FileInputStream fin = new FileInputStream(fd);

答案 2 :(得分:6)

我最近需要为在jail中运行的Java子进程执行此操作。这意味着它无法访问/ dev / fd文件系统。

@Bozho评论说,反射可能会或可能不会创建FileDescriptor对象。不过,它似乎在我做过的简单测试中起作用。以下是TestFD.java的来源:

import java.lang.reflect.Constructor;
import java.io.FileDescriptor;
import java.io.FileOutputStream;

public class TestFD {
  public static void main(String[] args) throws Exception {
    Constructor<FileDescriptor> ctor = FileDescriptor.class.getDeclaredConstructor(Integer.TYPE);
    ctor.setAccessible(true);
    FileDescriptor fd = ctor.newInstance(3);
    ctor.setAccessible(false);

    new FileOutputStream(fd).write("hi there\n".getBytes());
  }
}

为了测试这个,我制作了一个简单的Bash脚本来编译它,设置fd3,然后运行java程序:

#!/bin/bash

javac TestFD.java

exec 3>&1  # open fd3, redirect to stdout
java TestFD
exec 3>&-

果然,fd3被重定向到stdout,并输出&#34;你好\ n&#34;在终端上。注释掉&#34; exec 3&gt;&amp; 1&#34; line和Java程序按预期失败,并且#34;设备未配置&#34; IOException异常。

对于私有FileDescriptor构造函数的反射似乎在无法访问/ dev / fd的情况下工作正常,并且比使用JNI创建FileDescriptor更不笨,这是我在别处看到的一个建议。

注意:我在BSD系统上进行了测试。它可能适用于其他系统,也可能不适用。

答案 3 :(得分:3)

首先:

  

应用程序不应创建自己的文件描述符

您可以尝试使用反射来调用构造函数private FileDescriptor(int fd),方法是获取构造函数并在其上调用setAccessible(true)。但这是一个黑客,我不能保证它会工作(它可能不会)。特别是考虑到我开始时的引用。