java.io.NotSerializableException: java.util.logging.Logger

hello vaadin-ers,

I have the following error message in the log when I start tomcat7 in eclipse:

Jan 13, 2012 2:32:07 PM org.apache.catalina.session.StandardManager doLoad
SEVERE: IOException while loading persisted sessions: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.util.logging.Logger
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.util.logging.Logger

What does this mean? Should I take care of it?

how can I solve this problem?

And in general why/when serialization is important in a vaadin app?

And what is the best way to implement logging in a vaadin app? Is there a best practice for it?

Peter

i think you need to declare the Logger as static final transient.

private static final transient Logger logger = Logger.getLogger(yourClass);

this way it will not be tried for serialization.

For serialization: it is important when running a Vaadin application on Google App Engine or some other cloud/clustering platform that relies on serialization. In most other cases, it is not.

Tomcat by default serializes open sessions on exit and restores them on startup. This is why you are seeing the error message, but it only causes old sessions not to be deserialized, which is anyway better when debugging to start from a fresh state. I would recommend uncommenting the related line (Manager=…) in the context.xml file of your development instance of Tomcat. On production servers, you might want to keep sessions over server restarts if your sessions are serializable.

I’d like to point out that you should

never declare a logger static

in a web application or any other application that’s loaded by a container. Generally speaking, never hold a static reference to an object that is also referenced by a class loader outside of your application. In the logger case, the Logger class in the JVM holds a map of strings (logger name) to weak references to logger objects.

Whenever you redeploy your app, the previous classloader for the app holds a reference to the logger object (since it’s static), and so does the Logger class in the JVM. So the classloader never gets garbage collected because the logger is never GC’ed, and you eventually run out of memory after a lot of redeploys. You can find a few articles about this online by searching “java static logger classloader memory” or something. I suppose you could get around this by holding a static weak reference to a logger, but there’s really no need. Just declare the logger when you need it at the top of a method, or whenever it’s used. If you want it at the class level, just don’t make it static, and mark it as transient in a serializable class (no need to ever serialize a class that you can just fetch again from the JVM).

The Logger.getLogger(“foo”) call is just a map lookup, so it’s not that expensive. Even less expensive is having each instance of a class have its own reference to the same Logger. After all, it’s the same logger. As a test, guess what this prints:

        Logger l0 = Logger.getLogger("example");
        Logger l1 = Logger.getLogger("example");
        System.out.println(l0.equals(l1));
        System.out.println(l0 == l1);

I know it’s one of those things that “everybody does,” but in this case “everybody” is actually wrong. :slight_smile: Someone on the JDK team told me a couple years back that this would be fixed in JDK 7, but I don’t honestly know if it is or not.

Cheers,
Bobby

Is this true for Tomcat 7 (and perhaps Tomcat 6) which essentially got rid of shared classloaders? I mean, I guess you can force it back to doing so at your own peril, but assuming your webapp has all JARs and code is in WEB-INF lib/classes and doesn’t make use of a shared classloader, it seems this wouldn’t really be a bug.

Is that true or am I missing something?

Tomcat 7 might not suffer from this issue (Tomcat 6 does AFAIK, at least in part if Vaadin is used as a servlet container level shared library), but other servers may also have similar issues.

This is all so complicated that, at one point, I think I wrote in a thread that I shouldn’t have brought it up! First things first: even when it
is
a problem, it’s really not a huge one. You have to undeploy a LOT of times to take up a significant amount of memory, and I just don’t think people undeploy/deploy to production servers 100s or 1000s of times without a single reboot (which is often faster than the deployment anyway).

I can’t really speak to individual servers, and after a weekend of testing many months ago couldn’t bring down GlassFish this way, so am uncertain about where it’s a problem and when it isn’t (though a static custom Level is always a problem, as discussed in one of the links I’ve sent before).

To actually answer your question, though: all applications get java.util.Logger objects from the JVM, so even if 2 apps have different classloaders, they’re still getting that Logger object from the same JVM bootstrap loader (or whichever one that is). So even if it’s not an issue with the JVM’s map of String to WeakReference, you can cause the problem if two different apps both use loggers with the same names. In that case, the logger object might never be garbage collected, and static references to it in a classloader will pile up. That’s why it’s a tricky problem – you can have objects in your application that have references to them outside of your app.

You can test this if you want (I could always be wrong about the internals of the server!) using this silly
April Fool’s Day app I wrote
. There are two apps there, and they use a Logger object to communicate between themselves.

Cheers,
Bobby

Hi,
maybe you should migrate logging to SLF4J. We did it in our company to solve problems during redeployment. As stated in the FAQ, they avoid these classloader issues:
http://www.slf4j.org/faq.html#yet_another_facade

Kind regards, Sebastian