GetPropertyAction与System.getProperty获取系统变量

我一直在使用相当多的东西

System.getProperty("property") 

为了获得环境信息。 但是,在我看来,Sun更喜欢以下内容:

 (String) java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("property")); 

奇怪的是,这段代码涉及一个演员,结果应该比一点慢

System.getProperty

实现,只使用安全管理器然后立即从实例变量props获取属性。 我的问题是为什么Sun选择使用第二种方法在内部获取代码中的大多数环境变量

System.getProperty

似乎更快的方式去?

两种方法都有不同的含义,因此必须使用正确的方法,具体取决于当前代码需要做什么。

代码System.getProperty("property")说“如果当前安全上下文允许我读取它,请给我属性的值。”

使用doPrivileged的代码说:“如果当前的类(这行代码所在的位置)被允许读取它,请给我属性的值。”

当当前类的保护域与当前活动的安全上下文不同时,差异就会发挥作用。

例如,考虑一个执行插件代码的框架,该代码是不可信的。 因此,框架使用SecurityManager来限制不受信任的插件代码的操作。 但是当然插件可能会调用框架的某些方法,并假设其中一个方法需要读取属性。 现在,当从不受信任的受限代码调用该方法时,它本身受到限制,因此读取属性将失败。 但是当然框架信任自己并且希望自己能够读取该属性,即使在调用堆栈中的某个地方是不受信任的代码的情况下也是如此。 那时你需要使用doPrivileged 。 它基本上说“无论调用堆栈中的内容是什么,我都是一段框架代码,我可以做任何允许框架代码执行的操作”。 因此,使用第二种方法读取属性成功。

当然,在使用doPrivileged时需要小心,以免让(不可信的)调用代码做太多。 例如,如果框架代码为插件提供以下方法:

 public String getProp(String key) { return (String) java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction(key)); } 

这将完全使不受信任的代码不允许读取系统属性的策略失效,因为它只能使用您的方法。

因此,只有当您知道这样做是安全的时才使用此方法,并且只在您需要它时(也就是说,当您希望代码能够比其他代码做更多的代码时应该能够直接执行)。 在普通应用程序(通常没有安全管理器或所有代码的相同安全上下文运行)内部,没有区别,应该使用第一种方法。

我建议坚持使用System.getProperty()因为sun.security.action.GetPropertyAction似乎是SUN专有的,并且不适用于所有Java VM实现。 甚至编译器也会警告你:

警告:sun.security.action.GetPropertyAction是Sun专有API,可能会在将来的版本中删除

要了解它的实际含义,请参阅此答案 。

使用像sun.security.action.GetPropertyAction这样的类的原因是为了避免加载几个基本相同的类。

如果你写道:

 (String) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { String run() { System.getProperty("property"); } } ); 

每次要获取系统属性时,都会为每个getProperty调用加载一个新类。 每个类占用系统资源并且只要包含ClassLoader(永远用于bootclassloader)。

查看javap输出以获取更多详细信息:

 javap -c -v -p sun.security.action.GetPropertyAction