Search code examples
javaclassloaderjava.util.logging

java.util.logging.Logger uses very specific ResourceBundle loading behavior. Why?


The java.util.logging.Logger class locates ResourceBundle instances in a very specific manner. I am interested in understanding the classloading behavior.

Discarding caching, etc., first the Logger class attempts to use the context classloader (this is good and what I'd expect).

If that classloader cannot load a ResourceBundle (using the ResourceBundle#getBundle(String, Locale, ClassLoader) call ), then the system classloader is used next. That was slightly puzzling to me; I'd assume that the caller's classloader would be the next one in line. Is this an optimization, or is this to handle some specific use case, or...?

Finally, if the system classloader cannot load the ResourceBundle, then the inferred call stack (!) is walked, and each class in that stack is mined for its classloader, and each of those is tried in turn.

For all the various classloading scenarios I've encountered or had to write, this one makes the least sense to me. I suspect this has to do with Logger's potential centrality to any given system, but I would welcome any explanation as to why this particular algorithm was selected.

(Also, side question not really worthy of its own entry: is there any circumstance in the JVM where the context classloader is null?)


Solution

  • My guess is they were thinking in a way to support J2EE classloader hierarchies and its different implementations in each application server.

    Moreover, if we check JavaDoc we have

    As a temporary transition feature in the initial implementation, if the Logger is unable to locate a ResourceBundle from the ContextClassLoader or SystemClassLoader the Logger will also search up the class stack and use successive calling ClassLoaders to try to locate a ResourceBundle. (This call stack search is to allow containers to transition to using ContextClassLoaders and is likely to be removed in future versions.)