Странное поведение java.beans.Introspector в WebLogic с DCEVM и HotSwapAgent
Я запускаю WebLogic на JVM 1.7 с DCEVM (полная реализация) и HotSwapAgent с настраиваемым плагином, который запускается при каждом onClassLoad.
Я сталкиваюсь с проблемами с Freemarker, который использует java.beans.Introspector. Я обнаружил тот факт, что когда я вызываю Introspector.flushCaches для метода, вызываемого HotSwapAgent (через ReflectionCommand), то BeanInfo в Introspector становится недействительным (проверяется с помощью отладчика в этом потоке). Однако, когда я делаю запрос к серверу приложений WLS, тогда Introspector для рабочего потока показывает старые значения!
Это похоже на некоторую локальную реализацию потока, но я не смог найти ничего, что указывало бы на это предположение в документации java.beans.Introspector.
Кто-нибудь знает, почему это происходит и как это решить?
В настоящее время я храню информацию о перезагруженных классах в отдельном классе и перезагружаю все, что находится в этом кэше, из потока запросов, который работает.
Спасибо за любую подсказку.
1 ответ
Обнаружил это благодаря @ddekany и его ответу на связанную проблему во Freemarker removeIntrospectionInfo не работает с DCEVM после горячей замены модели
Кажется, что JVM (по крайней мере, HotSpot 1.7) кэширует кэш Introspector для каждой группы ThreadGroup. Это означает, что Introspector.flushCaches
должен быть вызван в потоке, который работает в соответствующем ThreadGroup
,
Когда я выполнил это для всех ThreadGroups в приложении, все снова начало работать правильно.
Я не смог найти никакой документации, почему java.beans.Introspector
кэшируется за ThreadGroup
так что, если у кого-то есть достоверная информация, пожалуйста, добавьте комментарий со ссылкой.
Благодарю.
Обновить:
Исходя из источника JDK7
/**
* Introspect on a Java Bean and learn about all its properties, exposed
* methods, and events.
* <p>
* If the BeanInfo class for a Java Bean has been previously Introspected
* then the BeanInfo class is retrieved from the BeanInfo cache.
*
* @param beanClass The bean class to be analyzed.
* @return A BeanInfo object describing the target bean.
* @exception IntrospectionException if an exception occurs during
* introspection.
* @see #flushCaches
* @see #flushFromCaches
*/
public static BeanInfo getBeanInfo(Class<?> beanClass)
throws IntrospectionException
{
if (!ReflectUtil.isPackageAccessible(beanClass)) {
return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
}
ThreadGroupContext context = ThreadGroupContext.getContext();
BeanInfo beanInfo;
synchronized (declaredMethodCache) {
beanInfo = context.getBeanInfo(beanClass);
}
if (beanInfo == null) {
beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
synchronized (declaredMethodCache) {
context.putBeanInfo(beanClass, beanInfo);
}
}
return beanInfo;
}
Это было определенно добавлено в JDK7, потому что я проверил код JDK6, и его там нет!