Class.forName ? Probably not ...

After subscribing to the OSGi Planet feed I felt like starting to read some old blog posts and stumbled upon a series of posts by BJ Hargave around the issues of the Eclipse ContextFinder caused by the Class.forName methods.

For the full story please go and read Class.forName caches defined class in the initiating class loader (and folow the links !).

So, these posts caused me to try and look how we behave in Apache Sling ... and of course hoped we would be clean.

Well, hmm, turns out we are not ... I found nine classes using Class.forName.

So we probably have to clean this up. Maybe or maybe not, these uses may be the cause for some strange failures we had over time. I cannot really tell. But I cannot exclude this possibility either.

BTW, this is what I did to find the classes:
$ find . -name "*.java" -exec fgrep -l Class.forName {} \;

Kommentare

Thomas Mueller hat gesagt…
How should a OSGi-aware library load user defined classes? For example, an embedded database that allows users to register user defined triggers using Statement.execute("create trigger xyz before insert on test call \"com.acme.MyTrigger\""). The embedded database then needs to load the class com.acme.MyTrigger somehow - but how? The current implementation tries Class.forName(className), and if that fails, it calls Class.forName(className, true, Thread.currentThread().getContextClassLoader()). If that's wrong, what is the correct way? The embedded database is supposed to work in both OSGi and non-OSGi environments.

If there is no 'easy' solution for OSGi that always works, what about supporting rules that define how to load the class (optionally with parameters) as in: Statement.execute("create trigger ... call \"com.acme.MyTrigger?bundle=abc&version=1.1\"") (OSGi) or "create trigger ... call \"com.acme.MyTrigger?service=def\"" (OSGi) or \"com.acme.MyTrigger?loader=context\"" (only use the context class loader) or \"com.acme.MyTrigger?loader=forName\"" (only use Class.forName).

Please forgive me my current non-knowledge about OSGi.
fmeschbe hat gesagt…
This post is about not using the Class.forName() method. It is not about don't ever try to load classes. Thus the library should do getClass().getClassLoader().loadClass(theClazz) or Thread.currentThread().getContextClassLoader().loadClass(theClazz). There is nothing wrong in using the ClassLoader.loadClass method; just don't use Class.forName().

As for the "loader hint": I think this completely defeats the whole idea of OSGi and loose coupling. Thus it creates even more harm.

Beliebte Posts aus diesem Blog

Ready to serve requests ...

LinkedHashMap's hidden (?) features

OSGi Bundles require Classes from the Environment