Home » Eclipse Projects » Eclipse Platform » Loading classes in a high level plugin via reflection from code in a lower level plugin
Loading classes in a high level plugin via reflection from code in a lower level plugin [message #246427] |
Thu, 27 May 2004 14:21  |
Eclipse User |
|
|
|
Hi all,
Yes, the title of the post is somewhat confusing but please bear with
me. I have a situation involving two plugins in an RCP app: A and B.
Where plugin B depends on plugin A. However, plugin A needs to be able
to load classes from plugin B via reflection (using
Class.forName(String)).
Unfortunately, Class.forName(String) uses the classloader of the calling
class. In this case, the calling class is in plugin A and so the
classloader that tries to do the loading is plugin A's classloader.
Since plugin A has no knowledge of any of plugin B's classes, a
ClassNotFoundException occurs.
Solutions to this problem that i have thought of include:
1) Merging the two plugins into one plugin
2) Changing the code in plugin A to take a classloader as an parameter
I don't want to do option #1 because i have a whole hierarchy of plugins
that need to use plugin A and i don't want to have each plugin load its
own version of plugin A's classes.
I can't readily change the code in plugin A because i don't have control
over it (although it is open source, so i could submit a patch). Also,
the location where the Class.forName(String) is done is deep inside the
code and therefore not easy to change.
Fundamentally, i see this as a real shortcoming of the Eclipse RCP due
to the way that classes are loaded within it. By not allowing lower
level plugins to reflect classes contained in higher level plugins, much
of power of Java's dynamic binding and reflection is lost.
I must add the caveat that my RCP app is based on Eclipse 2.1, but from
what i know about the 3.0 stream, this will still be an issue in 3.0.
Does anyone with more knowledge of classloading in Eclipse know a way
that i can load classes in a high level plugin via reflection from code
in a lower level plugin?
Thanks,
Sean Kirby
P.S. In case anyone is wondering, plugin A is actually Hibernate.
P.P.S. The interim solution to this problem is to set the context
classloader of the current Thread to the plugin classloader that is
highest in the hierarchy because Hibernate tries to load classes using
the context classloader before attempting the Class.forName(...).
|
|
|
Re: Loading classes in a high level plugin via reflection from code in a lower level plugin [message #246862 is a reply to message #246427] |
Fri, 28 May 2004 10:53   |
Eclipse User |
|
|
|
Ahh, the common need for plugins to be inter-dependent. Most of the time,
this is considered bad design. HOWEVER, what happens if A depends on B and A
implements an interface B provides, but an interface method happens to pass
another interface as a parameter, one found in B? So your A calls this
method that needs to see B, but when B passes its implementation of the
interface to A, B will need to see A when A makes the call on that interface
passed. Confusing? It is..basically its a callback situation. When dealing
with two plugins where one uses classes in another, but that other happens
to provide a callback the the first one can use, you have a need for both
plugins to see each other via their classloaders. As far as I know, this
can't be done in Eclipse without each plugin depending on one another, which
can rise to ciruclarity errors as well.
BUT, your use of Class.forName(className) is not all that wrong. If you can
access plugin B from plugin A, you can get plugin B's classloader as well,
right? So maybe you don't realize there is a Class.forName(className, true,
classLoader) call? Use that one and pass plugin B's classloader and you
should be alright.
"Sean Kirby" <sskirby@alumni.uwaterloo.ca> wrote in message
news:c95b4e$brt$1@eclipse.org...
> Hi all,
>
> Yes, the title of the post is somewhat confusing but please bear with
> me. I have a situation involving two plugins in an RCP app: A and B.
> Where plugin B depends on plugin A. However, plugin A needs to be able
> to load classes from plugin B via reflection (using
> Class.forName(String)).
>
> Unfortunately, Class.forName(String) uses the classloader of the calling
> class. In this case, the calling class is in plugin A and so the
> classloader that tries to do the loading is plugin A's classloader.
> Since plugin A has no knowledge of any of plugin B's classes, a
> ClassNotFoundException occurs.
>
> Solutions to this problem that i have thought of include:
> 1) Merging the two plugins into one plugin
> 2) Changing the code in plugin A to take a classloader as an parameter
>
> I don't want to do option #1 because i have a whole hierarchy of plugins
> that need to use plugin A and i don't want to have each plugin load its
> own version of plugin A's classes.
>
> I can't readily change the code in plugin A because i don't have control
> over it (although it is open source, so i could submit a patch). Also,
> the location where the Class.forName(String) is done is deep inside the
> code and therefore not easy to change.
>
> Fundamentally, i see this as a real shortcoming of the Eclipse RCP due
> to the way that classes are loaded within it. By not allowing lower
> level plugins to reflect classes contained in higher level plugins, much
> of power of Java's dynamic binding and reflection is lost.
>
> I must add the caveat that my RCP app is based on Eclipse 2.1, but from
> what i know about the 3.0 stream, this will still be an issue in 3.0.
>
> Does anyone with more knowledge of classloading in Eclipse know a way
> that i can load classes in a high level plugin via reflection from code
> in a lower level plugin?
>
> Thanks,
> Sean Kirby
>
> P.S. In case anyone is wondering, plugin A is actually Hibernate.
>
> P.P.S. The interim solution to this problem is to set the context
> classloader of the current Thread to the plugin classloader that is
> highest in the hierarchy because Hibernate tries to load classes using
> the context classloader before attempting the Class.forName(...).
|
|
|
Re: Loading classes in a high level plugin via reflection from code in a lower level plugin [message #246871 is a reply to message #246862] |
Fri, 28 May 2004 11:29  |
Eclipse User |
|
|
|
Kevin,
Thanks for the reply. Unfortunately, i can't use
Class.forName(className, true, classLoader) because:
1)plugin A is 3rd party code (hibernate) and
2)it would be difficult because plugin B's classloader would have to be
passed down through many levels of method calls in plugin A
Alas!
Hopefully this shortcoming in Eclipse 2.1 will be overcome in Eclipse
3.0 (i've heard that putting "DynamicImport-Package: *" in the lower
level plugin's OSGi manifest file will work).
sk
Kevin wrote:
> Ahh, the common need for plugins to be inter-dependent. Most of the time,
> this is considered bad design. HOWEVER, what happens if A depends on B and A
> implements an interface B provides, but an interface method happens to pass
> another interface as a parameter, one found in B? So your A calls this
> method that needs to see B, but when B passes its implementation of the
> interface to A, B will need to see A when A makes the call on that interface
> passed. Confusing? It is..basically its a callback situation. When dealing
> with two plugins where one uses classes in another, but that other happens
> to provide a callback the the first one can use, you have a need for both
> plugins to see each other via their classloaders. As far as I know, this
> can't be done in Eclipse without each plugin depending on one another, which
> can rise to ciruclarity errors as well.
>
> BUT, your use of Class.forName(className) is not all that wrong. If you can
> access plugin B from plugin A, you can get plugin B's classloader as well,
> right? So maybe you don't realize there is a Class.forName(className, true,
> classLoader) call? Use that one and pass plugin B's classloader and you
> should be alright.
>
>
> "Sean Kirby" <sskirby@alumni.uwaterloo.ca> wrote in message
> news:c95b4e$brt$1@eclipse.org...
>
>>Hi all,
>>
>>Yes, the title of the post is somewhat confusing but please bear with
>>me. I have a situation involving two plugins in an RCP app: A and B.
>>Where plugin B depends on plugin A. However, plugin A needs to be able
>>to load classes from plugin B via reflection (using
>>Class.forName(String)).
>>
>>Unfortunately, Class.forName(String) uses the classloader of the calling
>>class. In this case, the calling class is in plugin A and so the
>>classloader that tries to do the loading is plugin A's classloader.
>>Since plugin A has no knowledge of any of plugin B's classes, a
>>ClassNotFoundException occurs.
>>
>>Solutions to this problem that i have thought of include:
>>1) Merging the two plugins into one plugin
>>2) Changing the code in plugin A to take a classloader as an parameter
>>
>>I don't want to do option #1 because i have a whole hierarchy of plugins
>>that need to use plugin A and i don't want to have each plugin load its
>>own version of plugin A's classes.
>>
>>I can't readily change the code in plugin A because i don't have control
>>over it (although it is open source, so i could submit a patch). Also,
>>the location where the Class.forName(String) is done is deep inside the
>>code and therefore not easy to change.
>>
>>Fundamentally, i see this as a real shortcoming of the Eclipse RCP due
>>to the way that classes are loaded within it. By not allowing lower
>>level plugins to reflect classes contained in higher level plugins, much
>>of power of Java's dynamic binding and reflection is lost.
>>
>>I must add the caveat that my RCP app is based on Eclipse 2.1, but from
>>what i know about the 3.0 stream, this will still be an issue in 3.0.
>>
>>Does anyone with more knowledge of classloading in Eclipse know a way
>>that i can load classes in a high level plugin via reflection from code
>>in a lower level plugin?
>>
>>Thanks,
>>Sean Kirby
>>
>>P.S. In case anyone is wondering, plugin A is actually Hibernate.
>>
>>P.P.S. The interim solution to this problem is to set the context
>>classloader of the current Thread to the plugin classloader that is
>>highest in the hierarchy because Hibernate tries to load classes using
>>the context classloader before attempting the Class.forName(...).
>
>
>
|
|
|
Goto Forum:
Current Time: Sun Jun 08 03:03:56 EDT 2025
Powered by FUDForum. Page generated in 0.03735 seconds
|