3

我在这里面临一个难题。

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

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

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

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

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

4

5 回答 5

6

System.setPropertySecurityManager检查(如果已安装)。

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

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);
    }
}
于 2010-11-17T19:09:37.407 回答
2

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

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

于 2010-11-17T17:34:00.567 回答
1

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

于 2010-11-17T16:22:34.887 回答
1

我知道2个解决方案

  1. 使用方面框架(aspectJ左右)
  2. 修改 System 类(将日志记录添加到 setProperty() 方法)new Throwable().printStacktrace(); 将报告您从何处调用该方法。

现在使用选项运行您的应用程序-Xbootclasspath/p并将您的版本 System 类放在那里。

-Xbootclasspath/p:<directories and zip/jar files separated by ;> 在引导类路径前面添加

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

于 2010-11-17T17:13:50.747 回答
0

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

于 2010-11-17T16:21:55.853 回答