Этот метод выполняется при создании CachedClass
для класса с одним абстрактным методом (он же SAM). Кэшированные классы - это Groovy-механизм, позволяющий более эффективно работать с отражением - вместо того, чтобы всегда ретроспективно анализировать классы с самого начала во время выполнения, он запоминает, например, модификации, применяемые с метапрограммированием (например, добавление новых методов в классы), поэтому он очень быстро получает всю информацию о классе. Конечно, это связано с некоторыми накладными расходами.
Например, когда регистр мета-классов инициализируется (один раз), он регистрирует около 1180 методов. Около 190 из них приводят к казни CachedSAMClass.getSAMMethodImpl(Class<?> c)
. Это происходит потому, что ClassInfo.isSAM(Class<?> c)
, который проверяет, является ли данный класс единственным классом абстрактного метода, вызывает этот метод. И если вы посмотрите на ClassInfo.createCachedClass(Class klazz, ClassInfo classInfo)
, то увидите, что этот метод isSAM()
всегда вызывается как последняя проверка.
В большинстве случаев создание реестра кэшируемых классов не должно быть проблемой - это происходит один раз для каждого класса. Большинство из них регистрируются, когда вы просто получаете доступ к metaClass
свойству любого класса. Или когда вы создаете первое закрытие. Когда дело доходит до производительности, много разных факторов имеют значение. Например, Spring Boot использует горячую замену для перезагрузки классов во время выполнения. В этом случае реестр мета классов Groovy воссоздается, и все кэшированные классы также должны быть воссозданы. То же самое может произойти при запуске приложения Spring Boot с добавленной зависимостью spring-boot-devtools
- оно использует дополнительный загрузчик классов с именем RestartClassLoader
, для которого требуется инициализация дополнительного реестра мета-классов. На самом деле количество загрузчиков классов, которое вы имеете, это количество раз, которое будет инициализирован регистр мета-классов (один раз для каждого загрузчика классов). Это RestartClassLoader
также вызывает воссоздание кэшированных классов при перезапуске.
И последнее, но не менее важное: если вы хотите правильно измерить производительность, попробуйте сделать это на рабочем сервере, а не в локальной среде разработки. Если вы можете присоединить отладчик к запущенному процессу на сервере и установить точку останова в CachedSAMClass.getSAMMethodImpl(Class<?> c)
в строке 169 , вы сможете увидеть, сколько раз и для каких классов выполняется этот метод. Если случается, что он выполняется несколько раз для одного и того же класса, это может означать, что ваше приложение перезапускает загрузчик классов, а Groovy должен перестроить реестр мета-классов. Этого не должно быть - производственное приложение после запуска не должно вносить никаких изменений в загрузчик классов без цели. Это допустимо на локальном dev - devtools, и горячая замена заставит реестр мета-классов быть воссозданным при каждом обновлении загрузчика классов.