Question

I am calling some C++ code that tries to load a Java class, e.g.

JNIEnv *jenv = ...
jclass cls = jenv->FindClass("org/some/bundle/SomeClass");

Now, the problem is that this class resides in an OSGi bundle, and the code above cannot find my class.

This problem only arise when running unit tests (Tycho-surefire headless tests). Is there a simple way to force the OSGi framework to find my class from JNI? On the Java side, I suspect something like Dynamic-ImportPackage could have fixed my problem. I am unwilling to change the third party C++ library just to get it working with the test framework, so I prefer a solution on the Java test setup / configuration side, if possible.

Was it helpful?

Solution

The FindClass method of JNIEnv only searches the contents of the system ClassLoader as defined by the global application classpath. Since OSGi does not use the global classpath, it is no surprise that this doesn't work.

In general whenever loading a class, you need to specify not just the class name but also the classloader that should load it. This is an inevitable requirement of modularity. So your code needs to be able to find the bundle that you expect to contain the class, and then call its loadClass method. You can do this directly in C++ code, but it may be easier to write a Java utility method to do it and then just call that method from C++.

OTHER TIPS

Well, I am not 100% sure that your case is like mine.

In my RCP I used to get the exception:

ClassNotFoundException: com.tool.packageA.IWantToLoadThisClass cannot be found by com.tool.packageB_1.0.0.qualifier


A simple solution was to:

  • Add com.tool.packageA to com.tool.packageB MANIFEST.MF Require-Bundle.

I though wanted to avoid that solution, because I was able to load other classes found in other packages normally com.tool.packageC, com.tool.packageD (This wasn't done by me though so I didn't know how it worked).


Searching around I came to find the other solution which I ended up using to keep things similar to the current working packages (com.tool.packageC, com.tool.packageD).

The solution was:

This is how to get it to work:

  1. Add Eclipse-BuddyPolicy: registered to com.tool.packageB MANIFEST.MF
  2. Add Eclipse-RegisterBuddy: com.tool.packageB to com.tool.packageA MANIFEST.MF
  3. Add Require-Bundle: com.tool.packageB to com.tool.packageA MANIFEST.MF

Now com.tool.packageA.IWantToLoadThisClass will be visible from com.tool.packageB and you will be able to find it when jenv->FindClass("com/tool/packageA/IWantToLoadThisClass");.

I hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top