Обнаружение вызовов метода System.setProperty - PullRequest
3 голосов
/ 17 ноября 2010

Здесь я сталкиваюсь с загадкой.

Одно из разработанных мною приложений загружает некорректную реализацию класса JAXP DocumentBuilderFactory .Позже это поведение было выведено из другого класса в другом приложении, созданном другой командой / компанией.Указанный класс изменил предпочтительный класс DocumentBuilderFactory при загрузке путем включения статического блока, аналогичного приведенному ниже:

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

Если он идет по Javadocs DocumentBuilderFactory.newInstance В этом методе было бы совершенно очевидно, что приведенный выше код отвечает за изменение реализации синтаксического анализатора, возвращаемого всем приложениям при вызове метода newInstance.

Был применен патч, который исправил эту проблему, но он приводит менячтобы задать этот вопрос - как определить, какой класс выполняет вызов System.setProperty во время выполнения?

Мы создали пользовательскую сборку OpenJDK с измененным классом System, который отвечал заприбить виновника по той простой причине, что у нас не было доступа ко всем источникам для всех приложений, развернутых на сервере.Но это стало возможным только благодаря тому, что производственная среда была воспроизведена в полном объеме.Следовательно, вопрос можно также интерпретировать как - как определить, какой класс выполняет вызов System.setProperty во время выполнения, в производственной среде?

Ответы [ 5 ]

5 голосов
/ 17 ноября 2010

System.setProperty проверяется SecurityManager , если установлен.

Вы можете создать свой собственный 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);
    }
}
2 голосов
/ 17 ноября 2010

Строковые литералы кодируются в формате UTF8 в формате файла класса, и, поскольку нет никаких оснований предполагать, что вызывающий нарушитель использует код для объединения имени свойства, я просто распаковал бы все JAR-файлы из classpath в один каталог и попыталсярекурсивный grep для "javax.xml.parsers.DocumentBuilderFactory" через файлы классов.Вы бы, по крайней мере, нашли бы все файлы классов, содержащие эту строку, как литерал и, надеюсь, не слишком много ложных срабатываний.

Если бы имя класса неверной реализации было легче идентифицировать, возможно, было бы более умным искатьвместо этого.

1 голос
/ 17 ноября 2010

Просто запустите приложение в режиме отладки, подключитесь к нему с помощью eclipse, установите точку останова и посмотрите, какой класс это делает в иерархии вызовов http://www.eclipsezone.com/eclipse/forums/t53459.html

1 голос
/ 17 ноября 2010

Я знаю 2 решения

  1. использовать структуру аспекта (aspectJ или около того)
  2. Изменить системный класс (добавить запись в метод setProperty ()) new Throwable().printStacktrace(); сообщит вам, откуда был вызван метод.

Теперь запустите ваше приложение с опцией -Xbootclasspath/p и поместите туда версию класса вашей системы.

-Xbootclasspath/p:<directories and zip/jar files separated by ;> подготовить перед начальной загрузкой пути класса

Я предпочитаю второе решение, потому что оно очень простое.

0 голосов
/ 17 ноября 2010

Похоже на случай использования для аспект фреймворков, нет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...