检测System.setProperty方法调用

时间:2010-11-17 16:14:02

标签: java debugging instrumentation jaxp

我在这里面临一个难题。

我开发的一个应用程序是加载DocumentBuilderFactory类JAXP的错误实现。后来推断这种行为是由不同团队/公司构建的不同应用程序中的另一个类产生的。通过包含类似于下面的静态块,所述类在加载时更改了首选的DocumentBuilderFactory类:

  static
  {
    System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "a new factory");
  }

如果使用Javadocs of the DocumentBuilderFactory.newInstance方法,那么在调用newInstance方法时,上述代码很明显负责更改返回给所有应用程序的解析器实现。

应用了补丁,纠正了这个问题,但它让我问这个问题 - 如何确定哪个类在运行时执行System.setProperty调用?

我们已经制作了一个OpenJDK的自定义版本,其中包含一个修改过的System类,负责确定罪魁祸首,原因很简单,我们无法访问部署在服务器上的所有应用程序的所有源代码。但这可能只是因为生产环境在其环境中得到了复制。因此,问题也可以解释为 - 如何在生产环境中确定哪个类在运行时执行System.setProperty调用?

5 个答案:

答案 0 :(得分:5)

System.setPropertySecurityManager检查,如果已安装。

您可以创建自己的MySecurityManager并在运行时进行部署。当调用方法checkPropertyAccess时,您自己的SecurityManager可以记录一些信息,如当前的堆栈跟踪:

public class MySecurityManager extends SecurityManager
{

    public MySecurityManager()
    {
        super();
    }

    @Override
    public void checkPropertyAccess(String key)
    {
        if ("javax.xml.parsers.DocumentBuilderFactory".equals(key))
        {
            System.err.println("checkPropertyAccess(String :" + key + "): ");
            Thread.currentThread().dumpStack(); // or anything useful for
                                                // logging the context.
            new Throwable().printStackTrace(); // whatever, or use it with
            // PrintStream/PrintWriter, or some logging framework if configured.
        }
        super.checkPropertyAccess(key);
    }

    @Override
    public void checkPermission(Permission perm)
    {
        if (perm instanceof PropertyPermission)
        {
            PropertyPermission propPerm = (PropertyPermission) perm;
            System.err.println("checkPropertyAccess(String:" + propPerm.getName() + "):");
            Thread.currentThread().dumpStack(); // or anything useful for
                                                // logging the context.
            new Throwable().printStackTrace(); // whatever, or use it with
            // PrintStream/PrintWriter, or some logging framework if configured.
        }
        super.checkPermission(perm);
    }
}

答案 1 :(得分:2)

字符串文字是以类文件格式进行UTF8编码的,因为没有理由认为有问题的调用者正在使用代码来连接属性名称,我只需将所有JAR从类路径解压缩到一个目录中并尝试通过类文件的“javax.xml.parsers.DocumentBuilderFactory”的递归grep。您至少会发现包含此String的所有类文件都是文字,并且希望没有多少误报。

如果更容易识别不正确的实现的类名,那么搜索它可能会更加聪明。

答案 2 :(得分:1)

只需在调试模式下启动应用程序,使用eclipse连接到它,设置断点并查看调用层次结构http://www.eclipsezone.com/eclipse/forums/t53459.html

中的类

答案 3 :(得分:1)

我知道2个解决方案

  1. 使用方面框架(aspectJ左右)
  2. 修改系统类(将记录添加到setProperty()方法)new Throwable().printStacktrace(); 将报告您调用方法的位置。
  3. 现在使用选项-Xbootclasspath/p运行您的应用程序并将您的版本System类放在那里。

    -Xbootclasspath/p:<directories and zip/jar files separated by ;>                   prest在bootstrap类路径前面

    我更喜欢第二种解决方案,因为它很简单。

答案 4 :(得分:0)

看起来像aspect框架的一些用例,不是吗?