#java #process #processbuilder #system-properties
#java #процесс #processbuilder #system-свойства
Вопрос:
У меня есть автономное приложение, упакованное в JAR, которое при выполнении распаковывается во временный каталог и порождает дочерний процесс внутри этого каталога. Причина в том, что какой-то сторонний код и конфигурация предполагают, что файлы данных находятся относительно текущего рабочего каталога, а в java нет метода chdir(), поэтому единственный способ — переключить рабочий каталог для дочернего процесса.
Все работает нормально, за исключением системных свойств. Оператор может решить указать некоторые системные свойства в командной строке, как стандартные, так и связанные со сторонней конфигурацией:
java -Djava.io.tmpdir=/temp -Dsomething=else -jar foo.jar (parameters)
Системные свойства, доступные родительскому процессу Java, по умолчанию не передаются дочернему процессу. Я должен сделать это сам. И здесь я сталкиваюсь с препятствием: у меня нет способа определить, какие свойства задаются operator, а какие инициализируются по умолчанию JVM.
Возьмем этот java.io.tmpdir . Если оператор предоставил это, у него есть веская причина сделать это (возможно, местоположение по умолчанию — «диск заполнен»). Я должен установить его в дочерний процесс, иначе произойдет сбой. Но как мне узнать, получено ли оно от operator? Это может быть просто значение по умолчанию.
Я могу попробовать установить все доступные системные свойства дочернему процессу. Однако для этого требуется длинный список и, что еще хуже, сбой в некоторых средах, где длина командной строки ограничена.
Единственное решение, которое я нашел на данный момент (довольно хитрое), — это сначала запустить другой дочерний процесс вообще без аргументов и позволить ему передавать обратно родительскому все системные свойства, которыми он обладает. Значения, которые соответствуют тем, которые есть у родительского элемента, являются значениями по умолчанию. Остальное должно быть передано рабочему дочернему процессу.
У кого-нибудь есть альтернатива получше?
Ответ №1:
Там, где я работаю, у нас был медленно растущий список системных свойств, которые могли применять пользователи, и хотя нам не приходилось беспокоиться о дочернем процессе, у нас была другая проблема: их было просто слишком много.
Вместо того, чтобы заставлять пользователя предоставлять системные свойства через командную строку (или, в нашем случае, удлинять строку в скрипте, который запускает приложение, еще на одно свойство), мы добавили поддержку загрузки файла .properties по умолчанию.
Если вы сможете убедить пользователей поместить туда постоянные свойства, затем запустить процесс запуска дочернего процесса, а затем загрузки из файла, вы могли бы вообще избежать головной боли.
Тем не менее, вам, скорее всего, будут представлены сценарии отладки, в которых требуются временные или одноразовые свойства без изменения файла (не то чтобы это действительно имело большое значение). Здесь у вас есть несколько вариантов:
- Продолжайте использовать текущий подход.
- Попросите пользователя передать системные свойства в качестве аргументов командной строки, которые вы затем загружаете в системные свойства как для родительского, так и для дочернего процесса.
- Скажем жестко, используй файл. (Не ужасная вещь, но я был бы раздражен этим решением как пользователь)
Ответ №2:
Я не думаю, что на этот вопрос есть хороший ответ. Но, к счастью, большинство стандартных системных свойств либо невозможно переопределить, либо никто в здравом уме не стал бы переопределять.
Итак, следующие подходы, вероятно, являются вашими лучшими вариантами:
- передайте подмножество стандартных свойств, которые, по вашему мнению, имеет смысл передать,
- предоставьте способ указать параметры JVM (включая параметры -D), которые будут использоваться для дочерних JVM, или
- комбинация вышеперечисленных подходов.
Ответ №3:
Выбранное решение:
Мне все равно пришлось использовать дочерний процесс, который ничего не делает, но передает родительскому все системные свойства, которые он получает для сравнения. Единственной незначительной проблемой, на которую я наткнулся, было свойство line.separator, из-за которого мой код чтения строки натыкался на лишнюю пустую строку. Это было легко исправить.
Почему я не принял ни один из ответов:
Подходы, предложенные в приведенных ниже ответах, разумны, но ни один из них не является полностью удовлетворяющим.
У меня нет большой власти над пользователями, чтобы указывать им, что системные свойства Java должны передаваться через файл свойств или специальный аргумент командной строки. Это неудобно и противоречит операционной практике (особые случаи всегда плохи).
Я также не могу выбрать подмножество системных свойств для передачи дочернему процессу. В документации системного класса не указано, какие из них можно перезаписать (а здравый смысл не заменяет никакой документации). Для конечного пользователя также есть возможность определять свои собственные свойства, и я не могу предсказать их ни по имени, ни по номеру.