tl; dr: это обычная ленивая инициализация, и jd
просто сбит с толку.
Байт 16, где он создает это new Object[3]
:
16: anewarray #2 // class java/lang/Object
Вы можете видетьпосле этого, в 19-35, просто копируют локальные переменные в стек (iconst
для индекса, aload
для ссылки) и затем записывают их в массив (aastore
). немедленный следующий байт равен 36, что является оператором new
(только выделение, затем сразу следует invokespecial
для запуска конструктора).
Это приводит нас к байту48, который вызывает linkClosureAndJoinPoint
.Вы не включили свою таблицу констант, но в 45 ldc_w #327
загружает постоянное значение 69648, так что это подводит нас к точке из .around
.
Теперь происходит нечто интересноев байте 51. Один цепной вызов, который jd
реконструировал, теперь прерван.Байт-код загружает поле статической аннотации ajc$anno$10
(а не 5, как говорит jd
) в стек.Если это поле аннотации не равно нулю (55), то выполнение переходит к 86 (нет операции, используемой в качестве «точки посадки» для прыжка), которая выполняет эту проверку приведения ((SomeAnnotation)
), а затем фактически вызываетсовет.
Код, который пропущен (58-82), говорит об этом, что вы узнаете по декомпиляции:
SomeClass.class
.getDeclaredMethod("doSomething", new Class[] { String.class })
.getAnnotation(SomeAnnotation.class)
Байт 83 затем сохраняет результат в статическом поле,и оттуда продолжается выполнение.
С точки зрения Java, это именно то, что происходит:
if (cachedAnnotation == null) {
cachedAnnotation = getAnnotationOnMethodUsingReflection();
}
Байт-код AspectJ очень точный и чистый здесь (вероятно, оптимизированный вручную, потому что это, вероятно, будеточень горячий код).Либо из-за этого, либо из-за того, что эта логика прерывает цепной вызов метода, jd
запутывается и разделяет нулевую проверку и присваивание.