Search code examples
javaruntimeosgiclassloaderkaraf

How can I detect runtime libraries of an OSGi bundle if it uses classloader?


I am trying to put a complex application (jForexAPi, DDS2) into OSGi bundle(s). I made a two bundles with embedded dependencies both compile time and runtime (transitive). So I have bundles with .class-es inside the .jar bundles.

When I tried to use I got ClassNotFoundException because the DDS2 implementation loads class during runtime via the classloader of its thread. Somehow like this:

           Class e = Thread.currentThread().getContextClassLoader().loadClass("com.dukascopy.charts.main.DDSChartsControllerImpl");

I have two questions:

  1. How can I determine the parent bundle of a thread in karaf?
  2. How can I solve issues like runtime classloads in OSGi? Is there a way to allow or discover runtime classloads?

Solution

  • How can I determine the parent bundle of a thread in karaf?

    You cannot. A thread does not have a parent bundle. If you mean the Thread context classloader, it is not defined at all in OSGi. TCC is normally the classloader of a webapp in the Java EE world. However, in OSGi it can be even null or anything. It should be never used.

    How can I solve issues like runtime classloads in OSGi? Is there a way to allow or discover runtime classloads?

    You can do two things:

    • Contribute to the project to allow the configuration of a classloader that will be used to load these classes
    • Implement a workaround: Analyze the stacktrace of the ClassNotFoundException and find a place where you can set the thread context classloader

    If you chose the second option, your code will look similar to the following:

    Thread currentThread = Thread.currentThread();
    ClassLoader previousCL = currentThread.getContextClassLoader();
    try {
        currentThread.setContextClassLoader(DDSChartsControllerImpl.class.getClassLoader());
        callNextFunctionOnStacktrace();
    } finally {
        // You should set the original CL back as other technology might use the TCC tricks, too
        currentThread.setContextClassLoader(previousCL);
    }