[plugin classloader] IllegalArgument: class not visible [message #147999] |
Wed, 10 March 2004 08:16 |
Martin Kersten Messages: 306 Registered: July 2009 |
Senior Member |
|
|
Hi newsgroup,
I have a serious problem creating a library plugins. I can not
encapsulate
the com.mockobjects libraries. Here is why:
Considering you have added a library-plugin providing the mock libraries.
A mock is created by:
Mock mock=new Mock(MyInterface.class);
Where Mock is the class com.mockobjects.dynamic.Mock and is provided
by the library plugin.
Creating a new plugin (lets call it 'test')depending on the library you will
get the following behaviour:
It can be compiled, It can be run as a normal application. But if this
little code
runs as a plugin, an Exception is thrown informing about a visiblility
problem.
The exception reads like:
java.lang.IllegalArgumentException: interface pack.age.MyInterface is not
visible from class loader.
The error is caused (exception is thrown) by the following java code:
Class java.lang.reflect.Proxy.getProxyClass(
ClassLoader classLoader, Class [] interfaces) {
[...]
Class interfaceClass = null;
try {
interfaceClass =
Class.forName(interfaces[i].getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != interfaces[i]) { //this fails
throw new IllegalArgumentException( //thrown here
interfaces[i] + " is not visible from class loader");
}
[...]
}
So Class.forName("pack.age.MyInterface",false,loader) is still successfull
using the provided class loader but the Class instance returned by
the class loader by looking for pack.age.MyInterface is a diffrent one.
The class loader is provided by the Mock class by calling:
Mock(Class clazz (which is MyInterface.class)) {
Class proxy=Proxy.getProxyClass(getClass().getClassLoader(),
new Class[] {clazz});
}
So you can see that the class loader which had loaded the Mock class
is used. The fun is, this class loader finds MyInterface but it is creating
a diffrent Class object instead of providing the class object still exists.
I dont know why it is doing so, so I need help.
Since the library is not an owner of the MyInterface.class (it's the test
plugin), the classloader of the Mock class should ask the class loader
following the PP|S order (enabled OSGi but normal classloader
behaviour also fails). But it seams that I dont understand how loading
a class which is owned by a plugin depending on a given library plugin
is loaded by the classloader of the plugin (which is surly used in this
case).
Obviously we need to redirect the new Mock(...).getClass().getClassLoader()
to returning the ClassLoader instance of the test plugin rather then
returning
the ClassLoader of the library plugin. To be able to do this, we have to
ensure that calling new Mock(...).getClass() returns a class created by
the test plugin class loader. Therefore we simply extend the Mock using
class MyMock extends Mock {
MyMock(Class clazz) {
super(clazz);
}
}
Since MyMock belongs to the test plugin, the class is loaded by the
test plugin. Testing this, well it works! But still it isn't funny! It feels
like
a hack. So I would like if someone knows, how I can avoid this
mix up and correct class loading.
Thanks,
Martin (Kersten)
|
|
|
Powered by
FUDForum. Page generated in 0.03934 seconds