Странное поведение 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, и его там нет!

Другие вопросы по тегам