Подтвердить что ты не робот

Использование пронумерованного файлового дескриптора из Java

Мне нужно получить доступ к дескрипторам нумерованных файлов из Java - кроме 0, 1 или 2.

Как это можно сделать? Я просмотрел класс FileDescriptor, но не нашел способа инициализировать его с заданным номером дескриптора файла.

В качестве конкретного примера можно предположить, что Java вызывается как дочерний процесс с другого языка программирования. Файловые дескрипторы 3 и 4 предоставляются другим языком для ввода и вывода.

В Java мне нужны объекты InputStream и OutputStream, связанные с этими файловыми дескрипторами, так же как System.in, System.out и System.error связаны с файловыми дескрипторами 0, 1 и 2.

Я использую Java 1.6, и это должно работать на Unix-подобных системах.

Протестированное рабочее решение:

Ответ на записи файловой дескрипторной специальной файловой системы показал мне следующее работоспособное решение:

  • узнать, если и где ваша система Unix имеет специальную файловую систему, содержащую именованные записи для всех дескрипторов файлов.

    • Я использую FreeBSD, где fdescfs (5) - это файловая система, которая делает именно это. В Linux это будет procfs.
  • убедитесь, что эта файловая система установлена ​​

    • FreeBSD: поместите fdescfs /dev/fd fdescfs rw 0 0 в /etc/fstab

      или запустите mount -t fdescfs null /dev/fd в командной строке (возможно, с помощью sudo)

  • Используйте новые FileInputStream("/dev/fd/3") и new FileOutputStream("/dev/fd/4"), чтобы получить потоки, подключенные к файловым дескрипторам (пути для FreeBSD, заменить на пути к вашей операционной системе)

4b9b3361

Ответ 1

Я уверен, что это невозможно сделать с использованием чистой Java - вам, вероятно, придется использовать собственный код для привязки дескриптора файла к объекту FileDescriptor или к объекту FileInputStream или FileOutputStream.

ИЗМЕНИТЬ
Если вы используете Linux, * BSD или macOS, вы можете использовать псевдо файлы /dev/fd/nnn для доступа к файловому дескриптору nnn.

Ответ 2

С помощью SUN JavaVM вы можете:

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

Ответ 3

Мне недавно нужно было сделать это для дочернего процесса 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 script, который его компилирует, устанавливает fd3 и запускает программу java:

#!/bin/bash

javac TestFD.java

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

Конечно, fd3 перенаправляется на stdout и выводит "hi there there\n" на терминал. Прокомментируйте строку "exec 3 > & 1", и программа Java завершится неудачно, как ожидалось, с "Не настроенным устройством" IOException.

Отражение в частном конструкторе FileDescriptor, похоже, отлично работает в тех случаях, когда доступ к /dev/fd невозможен и менее неуклюж, чем попытка создания FileDescriptor с использованием JNI, предложение, которое я видел в другом месте.

Примечание. Я тестировал это в системе BSD. Он может работать или не работать в других системах.

Ответ 4

Для начала:

Приложения не должны создавать свои собственные файловые дескрипторы

Вы можете попробовать использовать отражение, чтобы вызвать конструктор private FileDescriptor(int fd), получив конструктор и набрав setAccessible(true) на нем. Но это взломать, и я не могу гарантировать, что это сработает (скорее всего, этого не произойдет). Особенно учитывая цитату, которую я начал с.