Java 系统属性的范围
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/908903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scope of the Java System Properties
提问by Chathuranga Chandrasekara
In Java we use System.setProperty() method to set some system properties. According to this articlethe use of system properties is bit tricky.
在 Java 中,我们使用 System.setProperty() 方法来设置一些系统属性。根据这篇文章,系统属性的使用有点棘手。
System.setProperty() can be an evil call.
- It is 100% thread-hostile
- It contains super-global variables
- It is extremely difficult to debug when these variables mysteriously change at runtime.
System.setProperty() 可能是一个邪恶的调用。
- 它是 100% 线程敌对的
- 它包含超全局变量
- 当这些变量在运行时神秘地改变时,调试是极其困难的。
My questions are as follows.
我的问题如下。
How about the scope of the system properties? Are they specific for each and every Virtual Machine or they have a "Super Global nature" that shares the same set of properties over Each and every virtual machine instance? I guess the option 1
Are there any tools that can be used to monitor the runtime changes for detect the changes in System properties. (Just for the ease of problem detection)
系统属性的范围如何?它们是特定于每个虚拟机还是它们具有“超级全局特性”,在每个虚拟机实例上共享相同的属性集?我猜选项1
是否有任何工具可用于监视运行时更改以检测系统属性的更改。(只是为了便于问题检测)
采纳答案by coobird
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.
至少通过阅读该System.setProperties
方法的 API 规范,我无法得到系统属性是否由 JVM 的所有实例共享的答案。
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:
为了找出答案,我编写了两个快速程序,它们将通过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) {}
}
}
}
(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.
事实证明,当使用两个单独的java
进程运行这两个程序时,在一个 JVM 进程中设置的属性值不会影响另一个 JVM 进程的值。
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.
我应该补充一点,这是使用 Sun 的 JRE 1.6.0_12 的结果,至少在 API 规范中没有定义这种行为(或者我找不到它),行为可能会有所不同。
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.
据我所知不是。但是,如果确实需要检查系统属性是否发生更改,则可以一次保留 的副本Properties
,并将其与另一个调用进行比较System.getProperties
-- 毕竟,Properties
是 的子类Hashtable
,因此比较将是以类似的方式进行。
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:
Hashtable
是线程安全的,所以我也期待这样Properties
,事实上,Properties
该类的 API 规范证实了这一点:
This class is thread-safe: multiple threads can share a single
Properties
object without the need for external synchronization., Serialized Form
这个类是线程安全的:多个线程可以共享一个
Properties
对象,不需要外部同步,序列化形式
回答by Laurence Gonsalves
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.).
是的,“系统属性”是针对每个 VM 的(尽管有许多“神奇”属性包含有关主机系统的信息,例如:“os.name”、“os.arch”等)。
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 SecurityManagerto prevent (and perhaps even track) system property changes.
至于你的第二个问题:我不知道有这样的工具,但如果你担心系统属性发生变化,你可以使用特殊的SecurityManager来防止(甚至可能跟踪)系统属性更改。
回答by Tom Hawtin - tackline
There is one copy of the properties per VM. They have much the same problems as other statics (including singletons).
每个 VM 有一份属性副本。它们与其他静态(包括单例)有很多相同的问题。
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.
我想,作为一个 hack,你调用System.setProperties
的版本会Properties
根据上下文(线程、调用堆栈、一天中的时间等)做出不同的响应。它还可以记录任何更改System.setProperty
。您还可以为SecurityManager
相关权限设置日志安全检查。
回答by Yishai
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.
它们的范围是正在运行的 JVM,但除非您有一些深奥的类加载器问题,否则带有属性对象的静态变量将做同样的事情,并且有机会同步或做任何您需要的事情。
回答by Fortyrunner
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.
我们使用 Spring 进行配置,并使用注入 XML 的属性文件设置初始属性。应用程序运行时对配置的更改是使用 JMX 进行的。
There are - of course - many other ways to change configuration in Java using properties file, xml based configuration etc.
当然,还有许多其他方法可以使用属性文件、基于 xml 的配置等更改 Java 中的配置。
回答by Max Nanasy
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.
系统属性是针对每个进程的。这意味着它们比静态字段更具全局性,静态字段是每个类加载器。因此,例如,如果您有一个 Tomcat 实例运行多个 Java Web 应用程序,每个 Java Web 应用程序都有一个com.example.Example
带有名为 的静态字段的类globalField
,那么这些 Web 应用程序将共享系统属性,但com.example.Example.globalField
可以在每个 Web 应用程序中设置为不同的值。
回答by Robin73
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!
当您启动一个新的 JVM 时,它会复制环境变量并将它们用于它的所有生命周期。因此,如果您对该环境进行更改,他们将继续局限于该环境。我遇到的和我正在调查的奇怪行为略有不同:如果我启动一个 JVM,声明一些环境变量(cmd 行上的 -D 参数)会影响我在应用程序中使用的库的行为。但是,如果在 Java 代码中(它们可见的地方),我对它们进行了更改,这些更改似乎不会影响库的行为。奇怪的是我们在同一个JVM!