我一直在使用相当多的
System.getProperty("property")
以获取环境信息。但是,在我看来,Sun更喜欢以下内容:
(String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("property"));
奇怪的是,这段代码涉及演员表,结果应该比
稍慢 System.getProperty
实现,只使用安全管理器然后立即从实例变量props中获取属性。我的问题是为什么Sun选择使用第二种方法在内部获取代码中的大多数环境变量,而
System.getProperty
似乎是更快的方式?
答案 0 :(得分:9)
两种方法都有不同的含义,因此必须根据当前代码的需要使用正确的方法。
代码System.getProperty("property")
说“如果当前的安全上下文允许我阅读它,请给我属性的值。”
使用doPrivileged
的代码说“如果当前类(这行代码所在的位置)允许读取它,请给我属性的值。”
当前类的保护域与当前活动的安全上下文不同时,差异就会发挥作用。
例如,考虑一个执行插件代码的框架,该代码是不可信的。因此,框架使用SecurityManager来限制不受信任的插件代码的操作。但是当然插件可能会调用框架的某些方法,并假设其中一个方法需要读取属性。现在,当从不受信任的受限代码调用该方法时,它本身受到限制,因此读取属性将失败。但是当然框架信任自己并希望自己能够读取该属性,即使在调用堆栈中的某个地方是不受信任的代码的情况下也是如此。那时你需要使用doPrivileged
。它基本上说“无论调用堆栈中的内容是什么,我都是一段框架代码,我可以做任何允许框架代码执行的操作”。因此,使用第二种方法读取属性成功。
当然,在使用doPrivileged
时需要小心,以免让(不可信的)调用代码做得太多。例如,如果框架代码为插件提供以下方法:
public String getProp(String key) {
return (String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(key));
}
这将完全使不受信任的代码不允许读取系统属性的策略失效,因为它只能使用您的方法。
所以只有当你知道它是安全的时才使用这种方法,并且只在你需要它时(也就是说,当你希望你的代码能够比其他代码做更多的代码时应该能够直接做到) 。在普通应用程序(通常没有安全管理器或所有代码的相同安全上下文)中运行,没有区别,应该使用第一种方法。
答案 1 :(得分:2)
我建议坚持使用System.getProperty()
,因为sun.security.action.GetPropertyAction
似乎是SUN专有的,并且不适用于所有Java VM实现。甚至编译器也会警告你:
警告:sun.security.action.GetPropertyAction是Sun专有API,可能会在将来的版本中删除
要了解其实际含义,请参阅this answer。
答案 2 :(得分:0)
使用像sun.security.action.GetPropertyAction这样的类的原因是为了避免加载几个基本相同的类。
如果你写了:
(String) java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<java.lang.String>() {
String run() {
System.getProperty("property");
}
}
);
每次想要获取系统属性时,都会为每个getProperty调用加载一个新类。只要包含ClassLoader(永远用于bootclassloader),每个类都需要系统资源和生命。
查看javap输出以获取更多详细信息:
javap -c -v -p sun.security.action.GetPropertyAction