2
votes

I am currently working on making some very OSGi-unfriendly 3rd-party libraries available to our OSGi-bundles. One of these libraries (which I have already turned into a bundle using bnd) manages to load classes that it should not be able to load (at least by OSGi-rules). Lets assume that bundle is called Foo, and the package from which it loads classes is called bar.

Foo has bar as optional import. This shouldn't matter though, since there is no bundle that exports bar. I am not using any boot-delegation. The jar-file that contains bar is on the application-classpath though (the OSGi-framework runs embedded in my application).

Apparently Foo somehow bypasses the OSGi-classloading infrastructure. How can this be done? I am pretty sure that it does not use a custom class-loader, because there is just no reason for it to have one (no feature Foo offers would require such a thing). So, what standard, out-of-the-box methods could be used by a bundle to bypass OSGi-classloading?

4
sorry for offtopic, I'm 'struggle' with very similar task on embedding Felix into my application, (actually still have open question on it stackoverflow.com/questions/9822616/…), Isn't be very impudence to ask you share code how do you embed (actually init Felix) OSGi. Thank you in advance. You can send me info or even negative response to mvoronoy_at_gmail_com - Dewfy
I am having these problems in the context of Pax Exam tests, so I am not doing the embedding myself. I know that Pax Exam uses Pax Runner, which is supposed to make it easier to embed a framework. I have never done it myself though, so I cannot offer any help. - Björn Pollex

4 Answers

1
votes

What OSGi framework are you using? Do you have a command prompt command or other means to request detailed info about the package? The OSGi spec allows you to investigate in detail, and most frameworks provide matching commands/interfaces for the OSGi PackageAdmin and other APIs.

Does it happen with other OSGi frameworks?

If you use ProSyst's mBedded Server as OSGi framework, you can discover who is loading what from where using the command

pkginfo [<package>[ <package>]] - Shows the dependencies of the specified package(s). If there are no parameters, you receive information about all packages available in the framework.

1
votes

This will do the trick if the classes are available on the Application class loader:

BundleContext.class.getClassLoader().loadClass("bar.X")

If you can get any class loaded by a loader you can get all the other classes. Of course if you would be running security you could forbid access to class loaders.

0
votes

Well, following is my assumption without proofs.

The simplest way to implement non-OSGi optional import is usage of Class.forName(name) - please note the signature without classLoader. Let's look at source code for this:

return forName0(className, true, ClassLoader.getCallerClassLoader());

In other turn let's look at ClassLoader.getCallerClassLoader():

...
Class caller = Reflection.getCallerClass(3);
...

3 - is number of frames to invoke (for example getCallerClass(0) - will return Reflection class). You can easily count what code is #3 in stack and if it is non-loaded by OSGi it will use default classLoader.

0
votes

The following is speculation since there isn't enough information to give a definitive answer. It's possible that the library is using the Thread Context ClassLoader (TCCL). If the bar package is visible to your own bundle (i.e. if it is a private package inside your bundle) and you invoke the Foo bundle, then the TCCL may have been set to allow the bar package to be loaded from your bundle.

To test this theory, try to change your code to explicitly set the TCCL to null before calling the Foo bundle: it would then throw a ClassNotFoundException.