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

Область свойств Java-системы

В Java мы используем метод System.setProperty() для установки некоторых свойств системы. Согласно этой статье использование свойств системы немного сложно.

System.setProperty() может быть злым вызовом.

  • Это 100%-нить-враждебное
  • Он содержит суперглобальные переменные
  • Чрезвычайно сложно отлаживать, когда эти переменные таинственно   изменение во время выполнения.

Мои вопросы заключаются в следующем.

  • Как насчет объема системных свойств? Являются ли они конкретными для каждой виртуальной машины или у них есть "Супер глобальный характер", который имеет один и тот же набор свойств над каждым экземпляром виртуальной машины? Я предполагаю, что вариант 1

  • Существуют ли какие-либо инструменты, которые можно использовать для контроля изменений времени выполнения для обнаружения изменений в свойствах системы. (Просто для удобства обнаружения проблемы)

4b9b3361

Ответ 1

Область свойств системы

По крайней мере, от чтения спецификаций API для метода System.setProperties мне не удалось получить ответ о том, являются ли общие свойства системы все экземпляры JVM или нет.

Чтобы узнать, я написал две быстрые программы, которые будут устанавливать системное свойство через System.setProperty, используя тот же ключ, но разные значения:

class T1 {
  public static void main(String[] s) {
    System.setProperty("dummy.property", "42");

    // Keep printing value of "dummy.property" forever.
    while (true) {
      System.out.println(System.getProperty("dummy.property"));
      try {
        Thread.sleep(500);
      } catch (Exception e) {}
    }
  }
}

class T2 {
  public static void main(String[] s) {
    System.setProperty("dummy.property", "52");

    // Keep printing value of "dummy.property" forever.
    while (true) {
      System.out.println(System.getProperty("dummy.property"));
      try {
        Thread.sleep(500);
      } catch (Exception e) {}
    }
  }
}

(Остерегайтесь, что запуск этих двух программ приведет их к бесконечному циклу!)

Оказывается, при запуске двух программ с использованием двух отдельных процессов java значение для свойства, заданного в одном JVM-процессе, не влияет на значение другого процесса JVM.

Я должен добавить, что это результаты использования Sun JRE 1.6.0_12, и это поведение не определено, по крайней мере, в спецификациях API (или я не смог его найти), поведение может отличаться.

Существуют ли какие-либо инструменты для мониторинга изменений времени выполнения

Не знаю. Однако, если вам нужно проверить, были ли изменения в свойствах системы, можно одновременно удерживать копию Properties и сравнивать ее с другим вызовом System.getProperties - в конце концов, Properties является подклассом Hashtable, поэтому сравнение будет выполненным аналогичным образом.

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

import java.util.*;

class CheckChanges {

  private static boolean isDifferent(Properties p1, Properties p2) {
    Set<Map.Entry<Object, Object>> p1EntrySet = p1.entrySet();
    Set<Map.Entry<Object, Object>> p2EntrySet = p2.entrySet();

    // Check that the key/value pairs are the same in the entry sets
    // obtained from the two Properties.
    // If there is an difference, return true.
    for (Map.Entry<Object, Object> e : p1EntrySet) {
      if (!p2EntrySet.contains(e))
        return true;
    }
    for (Map.Entry<Object, Object> e : p2EntrySet) {
      if (!p1EntrySet.contains(e))
        return true;
    }

    return false;
  }

  public static void main(String[] s)
  {
    // System properties prior to modification.
    Properties p = (Properties)System.getProperties().clone();
    // Modification of system properties.
    System.setProperty("dummy.property", "42");
    // See if there was modification. The output is "false"
    System.out.println(isDifferent(p, System.getProperties()));
  }
}

Свойства не являются потокобезопасными

Hashtable является потокобезопасным, поэтому я ожидал, что Properties тоже будет, и на самом деле спецификации API для Properties класс подтверждает это:

Этот класс является потокобезопасным: несколько потоки могут совместно использовать один Propertiesобъекта без необходимости внешнего синхронизация., Сериализованная форма

Ответ 2

Свойства системы - это процесс. Это означает, что они более глобальны, чем статические поля, которые являются per-classloader. Например, если у вас есть один экземпляр Tomcat, который запускает несколько веб-приложений Java, каждый из которых имеет класс com.example.Example со статическим полем с именем globalField, то webapps будет совместно использовать свойства системы, но com.example.Example. globalField может быть настроено на другое значение в каждом webapp.

Ответ 3

Существует одна копия свойств для каждой виртуальной машины. Они имеют те же проблемы, что и другие статики (в том числе одиночные).

Я предполагаю, что в качестве хака вы вызываете System.setProperties в версию Properties, которая по-разному реагирует в зависимости от контекста (поток, стек вызовов, время суток и т.д.). Он также может регистрировать любые изменения с помощью System.setProperty. Вы также можете установить проверку безопасности журналов SecurityManager для соответствующих разрешений.

Ответ 4

Их область действия - это работающий JVM, но если у вас есть какие-то проблемы с эзотерическим загрузчиком классов, статическая переменная со объектом properties будет делать то же самое, а также возможность синхронизировать или делать все, что вам нужно.

Ответ 5

Да, "системные свойства" - для каждой виртуальной машины (хотя существует множество "магических" свойств, которые содержат информацию о хост-системе, например: "os.name", "os.arch" и т.д.).

Что касается вашего второго вопроса: я не знаю такого инструмента, но если вы беспокоитесь о том, что изменились свойства системы, вы можете использовать специальный SecurityManager, чтобы предотвратить (и возможно даже отслеживать) системные изменения свойств.

Ответ 6

Вы не говорите, какова ваша мотивация для использования свойств системы.

Мы используем Spring для нашей конфигурации и устанавливаем начальные свойства, используя файл свойств, который вводится в XML. Изменения конфигурации во время работы приложения выполняются с помощью JMX.

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

Ответ 7

Когда вы запускаете новую JVM, она создает копию переменных окружения и использует их для всего жизненного цикла. Поэтому, если вы вносите изменения в эту среду, они останутся при этом. Странное поведение, с которым я столкнулся и которое я изучаю, несколько отличается: если я запускаю JVM, объявляющую некоторые переменные среды (-D аргумент в строке cmd), которые влияют на поведение библиотек, которые я использую в своих приложениях. Но если внутри java-кода (где они видны), я вношу в них изменения, кажется, что эти изменения не влияют на поведение библиотек. Странно то, что мы находимся в одном JVM!