Изменение классов Java во время выполнения, чтобы сделать поля экземпляров временными - это будет работать? - PullRequest
2 голосов
/ 16 января 2010

У нас есть раздражающее сообщение журнала, поступающее от Weblogic всякий раз, когда мы делаем недействительным HTTPSession, когда у него есть объекты, которые не сериализуются (что нас не волнует, но которое загрязняет наши журналы). Настроить нашу конфигурацию log4j, чтобы не регистрировать это сообщение, похоже, не вариант (сообщение приходит из универсального класса Weblogic, и мы не хотим подавлять все сообщения из этого класса, кроме написания нашего собственного адаптера для просмотра сообщений о быть записанным в журнал и подавляющим сообщения об ошибках десериализации, я не знаю, как мы будем делать это через конфигурацию log4j).

Чтобы временно исправить это, чтобы очистить наши журналы, я хочу перехватить вызовы, чтобы добавить объекты в HTTP-сессию, чтобы класс добавляемого объекта (и любые объекты в его графе объектов) изменили свои объявления переменных экземпляра. переходный. Я подумал, что перехватил бы вызовы, добавив HTTPSesssionEventListener, а затем изменив переменные экземпляров класса, используя библиотеки отражений.

Кто-нибудь знает, будет ли это работать?

Ответы [ 4 ]

2 голосов
/ 16 января 2010

Есть ли у кого-нибудь лучшее предложение и / или знать, будет ли оно работать / не будет работать так, как я бы этого хотел?

Да. Сборка по спецификации!

В соответствии со спецификацией Java-сервлета:

Контроллер распределенного сервлета должен выдавать IllegalArgumentException для объектов, которые контейнер не может поддерживатьмеханизм, необходимый для переноса сессии, хранящей их.

Так что, если вы хотите избежать этого сообщения (и написать хороший переносимый и распространяемый код), просто сделайте объект, который вы вставили в HttpSession, реализующимSerializable интерфейс.

Серьезно, я не могу поверить, что вы думаете о решении, которое поможет обойти реальную проблему, а не исправлять ее.

1 голос
/ 16 января 2010

Один вариант, если будет

tail -f yourlog | grep -v "annoying line here" > cleanLogFile

Что гораздо менее навязчиво. Но создает второй файл.

Я сделал это для проекта, в котором мне нужно было отследить конкретную проблему и все эти глупые сообщения, которые попали в середину.

0 голосов
/ 16 января 2010

Зачем идти на эту проблему? Звучит так же просто, как пометить их как сериализуемые, если все эти объекты принадлежат вам.

Если это невозможно, .aДругим способом является регистрация класса в вашем webApp, который реализует HttpSessionAttributeListener. В методе attributeAdded выведите идентификатор сессии и затем сериализуйте данные сессии:

public void attributeAdded(HttpSessionBindingEvent hsbe)
{
    // Handle the details yourself here.
    ObjectOutputStream.writeObject(hsbe.getValue())
}
0 голосов
/ 16 января 2010

Попробуйте изменить ObjectOutputStream, а не сериализованный объект.

Если вы расширили ObjectOutputStream, вы можете переопределить метод replaceObject и очистить несериализуемые поля или заново создать объект без несериализуемых свойств.

Другой вариант - использовать отражение, чтобы обнулить несериализуемые поля объектов сеанса, но это очень рискованно, так как объект сеанса может быть загружен обратно и работать, но затем выбросить NullPointerException часов или даже месяцев спустя (когда на поле, которое вы аннулировали, в конце концов есть ссылка.)

Изменение классов, вероятно, не будет работать.

Возможно расширить ClassLoader и настроить флаги на полях экземпляра, но:

  • Если ваш класс содержит не сериализуемое поле, проще изменить код самостоятельно, чтобы сделать его временным
  • Если это не ваш класс, тогда он будет загружен ClassLoader, отличным от классов вашего приложения, поэтому к тому времени, когда вы увидите объект, будет слишком поздно (поскольку класс уже загружен).

Нельзя установить флаг transient для отдельного объекта, только для класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...