2011-01-30 29 views
16

我需要從Java訪問編號爲0,1或2以外的文件描述符。使用來自Java的編號文件描述符

這怎麼辦?我查看了FileDescriptor類,但沒有找到任何方法用給定的文件描述符號來初始化它。

作爲一個具體的例子,讓我們假設Java被另一種編程語言稱爲子進程。文件描述符3和4由另一種語言提供,用於輸入和輸出。

我需要在Java中什麼是連接到這些文件的描述InputStreamOutputStream對象,就像System.in,System.out和System.error連接到文件desctiptors 0,1和2

我使用的是Java 1.6,它應該在Unix系統上運行。

測試工作液:

與文件描述符特殊的文件系統條目答案都指向我下面的可行的解決方案:

  1. 看看並在你的Unix相似系統具有包含所有文件描述符的命名條目的特殊文件系統。

    • 我使用的是FreeBSD,其中fdescfs(5)是一個文件系統。在Linux下它將是procfs。
  2. 確保此文件系統被安裝

    • FreeBSD的:在/etc/fstab

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

  3. 使用新的FileInputStream("/dev/fd/3")new FileOutputStream("/dev/fd/4")獲取連接到filedescriptors流(路徑是爲FreeBSD,用你的操作系統路徑替換)

+1

http://www.kfu.com/~nsayer/Java/jni-filedesc.html可能會幫助 – 2011-01-30 20:03:02

回答

13

我敢肯定,這不能用純Java來完成 - 你可能會必須使用本機代碼將文件描述符綁定到FileDescriptor對象或FileInputStream或FileOutputStream對象。

編輯
如果你正在使用Linux,* BSD或者MacOS,你可以使用僞文件/ dev/FD/NNN訪問文件描述符NNN。

+1

是的,當從你的答案中得知,這在Java本身中是不可能的(我沒有想到)我正在研究它的操作系統支持。我在FreeBSD下運行,並且對於所有打開的文件描述符都有/ dev/fd/。 – 2011-01-30 20:22:00

2

首先:

應用程序不應創建自己的文件描述符

可以嘗試使用反射調用構造函數private FileDescriptor(int fd),通過獲得構造函數並在其上調用setAccessible(true) 。但是這是一個黑客,我不能保證它會起作用(它很可能不會)。尤其是給了我開始的報價。

+2

我的問題是,我得到的這些文件描述符是由其他語言和其他外部約束的運行時間給出的,因此我不需要這樣做。我會嘗試你的建議。 – 2011-01-30 20:12:51

+0

正如你懷疑......它不會工作。我只能通過Class.getConstructor獲取公共構造函數 – 2011-01-30 20:19:16

+1

@Peer Stritzinger - 使用`FileDescriptor.getDeclaredConstructor(..)` – Bozho 2011-01-30 20:21:53

8

帶陽光JavaVM的你可以這樣做:

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

我最近需要在監獄中運行的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()); 
    } 
} 

爲了測試這一點,我做了編譯它,建立FD3一個簡單的bash腳本,並運行Java程序:

#!/bin/bash 

javac TestFD.java 

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

果然, fd3被重定向到stdout,並在終端上輸出「hi there \ n」。註釋掉「exec 3> & 1」行,並且Java程序按照預期發生「Device not configured」IOException異常。

對於私有FileDescriptor構造函數的反思似乎在無法訪問/ dev/fd的情況下工作正常,並且比使用JNI創建FileDescriptor更笨拙,這是我在其他地方看到的建議。

注意:我在BSD系統上測試過這個。它可能會或可能不會在其他系統上工作。