开发者

Modifying Java classes at runtime to make instance fields transient -- will it work?

We have an annoying log message coming from Weblogic whenever we invalidate the HTTPSession when it has objects that are not serializable (which we don't care about but which is polluting our logs). Tweaking our log4j configuration to not log this message does not appear to be an option (the message is coming from a generic Weblogic class and we dont want to supress all messages from this class and other than writing our own adapter to look at messages about to be written to the log and suppressing the deserialization error messages I dont know how we would do it through log4j configuration).

In order to temporarily fix this to clean up our logs I want to intercept calls to add objects to the HTTP Session so that the class of the object being added (and any objects in its object graph) have their instance variable declarations changed to transient. Figured I would intercept calls by adding an HTTPSesssionEventListener and then modifying the Class's instances variables using the reflection开发者_运维知识库 libraries.

Does anyone know if this would work?


Does anyone have a better suggestion and/or know if this will/will not work like I would want it to?

Yes. Build to spec!

In compliance with the Java Servlet specification:

The distributed servlet container must throw an IllegalArgumentException for objects where the container cannot support the mechanism necessary for migration of the session storing them.

So if you want to avoid this message (and write good portable and distributable code), just make the object you put in HttpSession implement the Serializable interface.

Seriously, I can't believe you are thinking to a solution to workaround the real problem instead of fixing it.


One option if would be

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

Which is much less intrusive. But creates a second file.

I did this for a project where I needed to trace an specific problem and all those stupid messages where getting in the middle.


Why go to that trouble? It sounds just as easy to mark them all as Serializable, as long as all the objects in question are yours.

If that's not possible, .aAnother way is to have a class registered within your webApp that implements HttpSessionAttributeListener. In the attributeAdded method print the sessionID and then serialize the session data:

public void attributeAdded(HttpSessionBindingEvent hsbe)
{
    // Handle the details yourself here.
    ObjectOutputStream.writeObject(hsbe.getValue())
}


Try modifying the ObjectOutputStream, not the serialized object.

If you extend ObjectOutputStream, you can override the replaceObject method and clear the non-serializable fields or re-create the object without the non-serializable properties.

Another option is to use reflection to nullify the non-serializable fields of the session objects, but that is very risky as a session object could be loaded back and appear to work but then throw a NullPointerException hours or even months later (when the field you nullified is eventually referenced.)

Modifying the classes will probably not work.

It is possible to extend ClassLoader and tweak flags on instance fields but:

  • If it's your class that contains the non-serializable field then it's simpler to change the code yourself to make it transient
  • If it's not your class then it will be loaded by a different ClassLoader from your application classes so by the time you see the object it will be too late (because the class has already been loaded.)

You cannot set the transient flag on an individual object, only on a class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜