1

I found the following loaders structure for OSGi in internet.

bootstrap classloader (Java standard libraries from jre/lib/rt.jar etc)
^
extension classloader
^
system classloader (ie stuff on $CLASSPATH, OSGi core code)
^ (** limited access to types from parent classloader
common OSGi classloader:
--|-- OSGi classloader for bundle1 -> (map of imported-package->classloader)
--|-- OSGi classloader for bundle2 -> (map of imported-package->classloader)
--|-- OSGi classloader for bundle3 -> (map of imported-package->classloader)

Here it says that

A context classloader set on the executing thread. By default it is always set to System classloader or from the thread from where the new thread instance was created.

From structure above we see system loader(=context loader) has higher position and as I know parent classloader never asks its children.

So my question please explain how current thread works with classes that are in current bundle?

  • In OSGI `Thread.currentThread().getContextClassLoader()` returns a special OSGI bundle classloader. In Equinox it is a `org.eclipse.osgi.framework.internal.core.BundleClassLoader`. This classloader is set by the OSGI container and knows only the imported packages and classes that defined by `Bundle-ClassPath` in the `MANIFEST.MF` (default is `.` => the bundle jar itself) – drkunibar Apr 20 '14 at 07:51
  • @drkunibar I don't know about Equinox but in felix Thread.currentThread().getContextClassLoader() returns sun.misc.Launcher$AppClassLoader@2f0f94a0, and this.getClass().getClassLoader returns org.apache.felix.framework.BundleWiringImpl@51dd475f. Something seems to be wrong in your explanation. –  Apr 20 '14 at 08:55
  • You can find every information about classloaders in OSGi in the OSGi core specification. Thread context classloader is often used by servlet containers. When the web application is called, the classloader of the web application is set as the thread context classloader. Technology developers use thread context classloader normally to be sure that they see all of the classes that are available in the webapp. In OSGi, you should never depend on thread context classloader and you should not use a technology that depends on thread context classloader. – Balazs Zsoldos Apr 20 '14 at 09:45
  • @P82 I don't know anything about felix, but the classloader returned by `Thread.currentThread().getContextClassLoader()` can be different than `this.getClass().getClassLoader` because the first one can be changed (the second one can't be changed). If you think about class loading in OSGI you should read this blog: http://blog.osgi.org/2011/05/what-you-should-know-about-class.html – drkunibar Apr 20 '14 at 12:48
  • Some of the information in the comments above is false. In OSGi, the thread context classloader is simply **undefined**. You cannot assert or expect it to be anything in particular, and in fact it may be null. – Neil Bartlett Apr 20 '14 at 19:50

1 Answers1

9

In OSGi the Thread Context ClassLoader (TCCL) is simply undefined. You cannot expect or assert that it will be anything in particular. In fact, a lot of the time it will be null.

TCCL is a hack that was added in Java 1.2 to support J2EE. Specifically it was needed to support things like Entity Beans; in a modern world it's used to support technologies like JPA, JAXB, Hibernate and so on.

The issue with parent delegation is that, while the application classes at the bottom have visibility of all classes in the parent classloaders, unfortunately the classes loaded by the parent classloaders do not have visibility of the application classes. In practical terms, this means that your application code can load (say) the classes that make up Hibernate, but Hibernate would not be able to load your domain classes because they are below it in the hierarchy.

So, TCCL was invented. In a J2EE application server, the TCCL is created as a thread-local variable, and it has visibility of all your application classes. Hibernate/JPA/JAXB etc can consult the TCCL in order to find the application classes. This was easy enough to do in J2EE because the app server controls all of the entry points: it controls the web server, it controls the RMI endpoints, and as an application developer you are not permitted to create your own threads.

However the programming environment for OSGi is far less constrained. Any bundle is permitted to create its own network endpoints, spin up its own threads, or pretty much do anything. Therefore, OSGi has no opportunity to intervene and impose a TCCL that has visibility of the application classes. Furthermore, the very concept of an "application" is fuzzy because we have this neat thing called modularity. An application consists of multiple bundles... but how to define which bundles may provide classes to the TCCL?

So OSGi basically punts on this issue. The TCCL is undefined so you should never rely on it. Fortunately most libraries that try to use only do so as one of a series of places they try to load classes from.

Neil Bartlett
  • 23,743
  • 4
  • 44
  • 77
  • Thank you for you time. This question rises from another question - solving casting problem is OSGi with returns from EJB. Having googled I found three solutions:using TCCL, reflection and Transloader. These solutions I described here http://stackoverflow.com/questions/23168885/. The problem with TCCL I described here http://stackoverflow.com/questions/23174582/. So either I shouldn't use TCCL - than how can I solve casting problem or how to solve it with TCCL? It's four days I can't move from the same place. Can you give me at least a hint? –  Apr 21 '14 at 03:51
  • I'll post an answer on whichever of those questions seems most pertinent. – Neil Bartlett Apr 21 '14 at 11:59
  • In the meantime, accepting or at least upvoting this answer would be much appreciated... assuming you found it useful or informative ;-) – Neil Bartlett Apr 21 '14 at 11:59
  • I've posted all the information here. http://stackoverflow.com/questions/23174582/ All I could do I've done. The solution is behind my abilities. –  Apr 23 '14 at 07:47
  • So as people are saying, the class is being loaded both two classloaders. One of these is an OSGi bundle classloader, the other is something related to Java RMI due to the involvement of EJB. I can't help much beyond that because I haven't used RMI or EJB for many years (and good riddance to them!). – Neil Bartlett Apr 23 '14 at 10:25
  • Could you advice any technology or library or another aproach? If I have OSGi client and EJB server. What would you do on my place? –  Apr 23 '14 at 11:31
  • Why not OSGi client and OSGi server? What does EJB actually buy you these days? – Neil Bartlett Apr 23 '14 at 13:01
  • I have an OSGi client and OSGi server(hybrid javaaee). That's I use OSGi everywhere. Why I use EJB, because from JavaEE (GF4) tutorial I understood it's the fundamental JavaEE technology (stateful and stateless EJB) that it's usually used as model according to MVC pattern. I don't understand your last question - what can I use instead of EJB? –  Apr 23 '14 at 14:39
  • Oh you're using Glassfish. Well that's only marginally an OSGi product, but anyway, did you try asking for help on the Glassfish forums? This problem seems to be rather specific to GF. As for your last question... what would I use instead of EJB? I would use Java! – Neil Bartlett Apr 23 '14 at 16:29
  • Empty words. Nothing concrete. –  Apr 23 '14 at 16:51