Scope of the Java System Properties

匆匆过客 提交于 2019-11-27 04:11:06

Scope of the System properties

At least from reading the API Specifications for the System.setProperties method, I was unable to get an answer whether the system properties are shared by all instances of the JVM or not.

In order to find out, I wrote two quick programs that will set the system property via System.setProperty, using the same key, but different values:

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) {}
    }
  }
}

(Beware that running the two programs above will make them go into an infinite loop!)

It turns out, when running the two programs using two separate java processes, the value for the property set in one JVM process does not affect the value of the other JVM process.

I should add that this is the results for using Sun's JRE 1.6.0_12, and this behavior isn't defined at least in the API specifications (or I haven't been able to find it), the behaviors may vary.

Are there any tools to monitor runtime changes

Not to my knowledge. However, if one does need to check if there were changes to the system properties, one can hold onto a copy of the Properties at one time, and compare it with another call to System.getProperties -- after all, Properties is a subclass of Hashtable, so comparison would be performed in a similar manner.

Following is a program that demonstrates a way to check if there has been changes to the system properties. Probably not an elegant method, but it seems to do its job:

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()));
  }
}

Properties is not thread-safe?

Hashtable is thread-safe, so I was expecting that Properties would be as well, and in fact, the API Specifications for the Properties class confirms it:

This class is thread-safe: multiple threads can share a single Properties object without the need for external synchronization., Serialized Form

System properties are per-process. This means that they are more global than static fields, which are per-classloader. So for instance, if you have a single instance of Tomcat running multiple Java webapps, each of which has a class com.example.Example with a static field named globalField, then the webapps will share system properties, but com.example.Example.globalField can be set to a different value in each webapp.

Tom Hawtin - tackline

There is one copy of the properties per VM. They have much the same problems as other statics (including singletons).

I guess, as a hack, you call System.setProperties to a version of Properties that responds differently depending on the context (thread, call stack, time of day, etc.). It could also log any changes with System.setProperty. You could also set a SecurityManager logs security checks for the relevant permissions.

Yes, "system properties" are per-VM (though there are a number of "magic" properties that contain information about the host system, eg: "os.name", "os.arch", etc.).

As for your second question: I am not aware of such a tool, but if you're concerned abut system properties getting changed you could use a special SecurityManager to prevent (and perhaps even track) system property changes.

Their scope is the running JVM, but unless you have some esoteric class loader issues a static variable with a properties object will do the same thing, and with the opportunity to syncronize or do whatever else you need.

You don't say what your motivation is for using system properties.

We use Spring for our configuration and set initial properties using a properties file that is injected into the XML. Changes to configuration whilst the app is running are made by using JMX.

There are - of course - many other ways to change configuration in Java using properties file, xml based configuration etc.

When you start a new JVM, it makes a copy of enviroment variables and uses them for all life-cycle of it. So if you makes changes to that enviroment, they would remain confined to it. The strange behavior I have encountered and on which I am investigating is slightly different: if I start a JVM declaring some of the environment variables (-D argument on cmd line) that affect the behavior of libraries I use in my applications. But if, inside the java code (where they are visible), I make changes to them, it seems that these changes do not affect the behavior of libraries. The strange is that we are in the same JVM!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!