Hi,
Did you try with both Felix and Equinox ?
Generally speaking, OSGi provides an API to “unload” a bundle. This is
possible because each OSGi bundle has its own classloader.
However bundles that import packages from an unloaded bundle still have
references to the bundle’s classloader and therefore to the bundle
classes. In addition, all classes which inherit from or have members
with types from the the referenced bundle have indirect references to
the original bundle classloader. The original classloader for the
unloaded bundle therefore cannot yet be garbage-collected (nor any class
the classloader ever loaded). If an unloaded bundle is replaced by
another which provides the same packages (eg has been upgraded to a new
version) then class-cast-exceptions can also occur when communicating
between bundles that have bound to different (old vs new) versions of
those packages; in addition, bundles resolved against the old
uninstalled bundle version will still be using old/obsolete code.
OSGi therefore supports refreshing a bundle, forcing OSGi to re-resolve
its imported packages, and if any change has occurred in the providing
classloaders then the refreshed bundle’s classloader is discarded (ie as
if the refreshed bundle had itself been unloaded/reloaded). Bundles that
then use exports from the refreshed bundle should also be refreshed.
This cascading refresh process doesn’t work well if any bundle is using
static variables, as their value is lost when the bundle is refreshed.
And if a static variable in a non-refreshed bundle references a class
from another bundle then that blocks garbage-collection of that bundle’s
classloader including all classes it has previously loaded.
If you are not in these conditions, the -XX:+CMSClassUnloadingEnabled
JVM arguments may help as well.
I hope it helps.
Regards
JB
On 03/19/2014 06:02 AM, Frizz wrote:
I'd like to implement my own custom ClassLoader. Basically it should do
exactly what the default OSGi ClassLoader does.
I am using Karaf/Felix, so in my case that's
org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader
The reason for implementing my own class loader is this: I use JNI to
load a DLL (with System.load()). But everytime I redeploy my bundle I
get a UnsatisfiedLinkError exception: Native Library xyz.dll already
loaded in another classloader.
This is, because the DLL is already loaded by the JVM - and stays as
long as the ClassLoader that loaded it is NOT garbage collected.
So I want to do something like this:
CustomClassLoader cl = new CustomClassLoader();
Class ca = cl.findClass("myPackage.MyClass");
Object a = ca.newInstance();
Method p = ca.getMethod("myMethod");
p.invoke(a);
p = null;
ca = null;
a = null;
cl = null;
System.gc();
Hopefully after that the CustomClassLoader is garbage collected - and
the DLL is unloaded from the container.
*What I found strange:* Even so each bundle has it's own ClassLoader, an
"osgi:uninstall <bundle>" does not unload the DLL - which means that the
bundles ClassLoader is still alive (and not garbage collected).
--
Jean-Baptiste Onofré
[email protected]
http://blog.nanthrax.net
Talend - http://www.talend.com