Как определить, получено ли системное свойство от оператора-человека, а не от default?

#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 по умолчанию.

Если вы сможете убедить пользователей поместить туда постоянные свойства, затем запустить процесс запуска дочернего процесса, а затем загрузки из файла, вы могли бы вообще избежать головной боли.

Тем не менее, вам, скорее всего, будут представлены сценарии отладки, в которых требуются временные или одноразовые свойства без изменения файла (не то чтобы это действительно имело большое значение). Здесь у вас есть несколько вариантов:

  1. Продолжайте использовать текущий подход.
  2. Попросите пользователя передать системные свойства в качестве аргументов командной строки, которые вы затем загружаете в системные свойства как для родительского, так и для дочернего процесса.
  3. Скажем жестко, используй файл. (Не ужасная вещь, но я был бы раздражен этим решением как пользователь)

Ответ №2:

Я не думаю, что на этот вопрос есть хороший ответ. Но, к счастью, большинство стандартных системных свойств либо невозможно переопределить, либо никто в здравом уме не стал бы переопределять.

Итак, следующие подходы, вероятно, являются вашими лучшими вариантами:

  • передайте подмножество стандартных свойств, которые, по вашему мнению, имеет смысл передать,
  • предоставьте способ указать параметры JVM (включая параметры -D), которые будут использоваться для дочерних JVM, или
  • комбинация вышеперечисленных подходов.

Ответ №3:

Выбранное решение:

Мне все равно пришлось использовать дочерний процесс, который ничего не делает, но передает родительскому все системные свойства, которые он получает для сравнения. Единственной незначительной проблемой, на которую я наткнулся, было свойство line.separator, из-за которого мой код чтения строки натыкался на лишнюю пустую строку. Это было легко исправить.

Почему я не принял ни один из ответов:

Подходы, предложенные в приведенных ниже ответах, разумны, но ни один из них не является полностью удовлетворяющим.

У меня нет большой власти над пользователями, чтобы указывать им, что системные свойства Java должны передаваться через файл свойств или специальный аргумент командной строки. Это неудобно и противоречит операционной практике (особые случаи всегда плохи).

Я также не могу выбрать подмножество системных свойств для передачи дочернему процессу. В документации системного класса не указано, какие из них можно перезаписать (а здравый смысл не заменяет никакой документации). Для конечного пользователя также есть возможность определять свои собственные свойства, и я не могу предсказать их ни по имени, ни по номеру.