AspectJ Ткач времени загрузки не обнаруживает все классы

Я использую декларативные транзакции Spring (аннотацию @Transactional) в режиме аспекта. В большинстве случаев это работает точно так же, как и должно, но для одного - нет. Мы можем назвать это Lang (потому что это то, что он на самом деле называется).

Мне удалось точно определить проблему для ткача времени загрузки. Включив отладку и подробное ведение журнала в aop.xml, он перечисляет все переплетенные классы. Проблемный класс Ланга действительно вообще не упоминается в журналах.

Затем я ставлю точку останова на вершине Ланга , вызывая Eclipse приостановить поток, когда загружен класс Lang . Эта точка останова достигнута, пока LTW ткут другие классы! Так что я предполагаю, что он либо пытается соткать Lang и терпит неудачу, но не выводит его, либо у некоторого другого класса есть ссылка, которая заставляет его загрузить Lang , прежде чем он действительно получит шанс чтобы сплести его.

Однако я не уверен, как продолжать отлаживать это, так как я не могу воспроизвести его в меньшем масштабе. Любые предложения о том, как продолжить?


Обновление: Другие подсказки также приветствуются. Например, как на самом деле работает LTW? Кажется, что происходит много магии. Есть ли варианты, чтобы получить еще больше отладочной информации от LTW? В настоящее время у меня есть:

<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">

Я забыл упомянуть об этом раньше: spring-agent используется для разрешения LTW, т.е. то есть, InstrumentationLoadTimeWeaver .


На основании предложений Энди Клемента я решил проверить, прошел ли когда-либо преобразователь AspectJ класс. Я установил точку останова в ClassPreProcessorAgent.transform (..) , и кажется, что класс Lang даже не достигает этого метода, несмотря на то, что он загружается тем же загрузчиком классов, что и другие классы (экземпляр JetA's WebAppClassLoader).

Затем я добавил точку останова в InstrumentationLoadTimeWeaver $ FilteringClassFileTransformer.transform (..) . Даже тот не попал под Ланга . И я считаю, что метод должен быть вызван для всех загруженных классов, независимо от того, какой загрузчик классов они используют. Это начинает выглядеть так:

  1. Проблема с моей отладкой. Возможно, Lang не загружен в то время, когда Eclipse сообщает, что это
  2. ошибка Java? Придурковат, но я предполагаю, что это действительно происходит.

Следующая подсказка: я включил -verbose: class , и кажется, что Лэнг загружается преждевременно - вероятно, прежде чем трансформатор будет добавлен в приборостроение. Как ни странно, моя точка останова Eclipse не улавливает эту загрузку.

Это означает, что Spring является новым подозреваемым. в ConfigurationClassPostProcessor , по-видимому, выполняется некоторая обработка, которая загружает классы для их проверки. Это может быть связано с моей проблемой.


Эти строки в ConfigurationClassBeanDefinitionReader заставляют читать класс Lang :

else if (metadata.isAnnotated(Component.class.getName()) ||
        metadata.hasAnnotatedMethods(Bean.class.getName())) {
    beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    return true;
}

В частности, метаданные . hasAnnotatedMethods () вызывает getDeclaredMethods () для класса, который загружает все классы параметров всех методов этого класса. Я предполагаю, что это, возможно, не конец проблемы, потому что я думаю, что классы должны быть выгружены. Может ли JVM кэшировать экземпляр класса по непонятным причинам?

13
задан waxwing 7 September 2010 в 11:57
поделиться

1 ответ

Вариант 1) Аспект J с открытым исходным кодом.Вскройте его и посмотрите, что происходит.

Вариант 2) Переименуйте свой класс в Bang, посмотрите, заработает ли он.

Я не удивлюсь, если там есть жесткое кодирование для пропуска "lang", хотя я не могу сказать, почему.

Изменить -

Вижу такой код в исходниках

        if (superclassnameIndex > 0) { // May be zero -> class is java.lang.Object
            superclassname = cpool.getConstantString(superclassnameIndex, Constants.CONSTANT_Class);
            superclassname = Utility.compactClassName(superclassname, false);

} else {
            superclassname = "java.lang.Object";
        }

Похоже, они пытаются пропустить вплетение java.lang.stuff.... не вижу ничего для просто "lang", но он может быть там (или ошибка)

1
ответ дан 2 December 2019 в 00:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: