【问题标题】:GetPropertyAction vs System.getProperty in obtaining system variablesGetPropertyAction vs System.getProperty 获取系统变量
【发布时间】:2011-06-24 16:55:20
【问题描述】:

我用了很多

System.getProperty("property")

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

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

奇怪的是这段代码涉及强制转换,因此应该比

System.getProperty

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

System.getProperty

似乎是更快的方法?

【问题讨论】:

    标签: java performance properties system environment-variables


    【解决方案1】:

    这两种方法的含义不同,因此必须根据当前代码需要执行的操作来使用正确的方法。

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

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

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

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

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

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

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

    所以只有当你知道这样做是安全的,并且只有在你需要它的时候才使用这个方法(也就是说,当你希望你的代码能够做的比其他一些代码应该能够直接做的更多时) .在普通应用程序中(通常在没有 SecurityManager 或所有代码的安全上下文相同的情况下运行),没有区别,应该使用第一种方法。

    【讨论】:

      【解决方案2】:

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

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

      要了解它的实际含义,请参阅this answer

      【讨论】:

      • 我确实知道它的含义,并且我知道不建议使用它,尤其是因为它涉及强制转换和创建新对象。然而,我一直想知道的是,为什么 Sun 在他们的实现中使用它,而不是在 privilegedAction 调用中围绕 System.getProperty。
      【解决方案3】:

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

      如果你写了:

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

      每次您想要获取系统属性时,您都会为每个 getProperty 调用加载一个新类。每个类都占用系统资源,并且与包含的 ClassLoader 一样长(对于引导类加载器来说永远存在)。

      查看 javap 输出了解更多详情:

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

      【讨论】:

      • Dan 是对的,一个类避免使用匿名类是有意义的,但 GetPropertyAction 是一个 sun 内部类。我建议你自己做。
      猜你喜欢
      • 2014-03-21
      • 2015-12-11
      • 2020-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 2013-06-17
      • 2010-10-06
      相关资源
      最近更新 更多