Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 136860 - ContextFinder should not use parent ClassLoader under WebStart
Summary: ContextFinder should not use parent ClassLoader under WebStart
Status: RESOLVED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: Framework (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: 3.2 RC2   Edit
Assignee: equinox.framework-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 110741 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-04-14 12:24 EDT by Neil Bartlett CLA
Modified: 2006-04-19 17:41 EDT (History)
3 users (show)

See Also:


Attachments
patch relative to tag v20060328 (3.2M6) (2.30 KB, patch)
2006-04-14 14:35 EDT, Neil Bartlett CLA
no flags Details | Diff
patch (5.85 KB, patch)
2006-04-17 12:17 EDT, Thomas Watson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Neil Bartlett CLA 2006-04-14 12:24:02 EDT
During startup, EclipseStarter initializes a ContextFinder and sets its parent as the current thread context classloader.

However under WebStart, the context classloader at this point is com.sun.jnlp.JNLPClassLoader. That loader has visibility of all downloaded JARs - ie ALL the bundles.

Therefore when ContextFinder consults its parent classloader under WebStart, the JNLPClassLoader will always supply it, we never get it from a BundleLoader. This can cause problems when using things like dynamic proxies, because the class loaded by the JNLPClassLoader will not be equal to the one loaded by the BundleLoader (even if they came from the same physical JAR) and therefore you get an exception that looks like this:

java.lang.IllegalArgumentException: interface org.springframework.aop.framework.Advised is not visible from class loader
at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
Comment 1 Neil Bartlett CLA 2006-04-14 14:35:08 EDT
Created attachment 38613 [details]
patch relative to tag v20060328 (3.2M6)

The attached patch fixes the problem by detecting the JNLPClassLoader and, if seen, calling the no-arg ClassLoader constructor on ContextFinder.

Tested with both a standalone app and a WebStart app, but not exhaustively.
Comment 2 Pascal Rapicault CLA 2006-04-16 10:25:29 EDT
*** Bug 110741 has been marked as a duplicate of this bug. ***
Comment 3 Pascal Rapicault CLA 2006-04-16 11:06:12 EDT
Tom could you please take a look at this? I encountered this pb a while back better never had the opportunity to look into a fix (see dup bug).
I quickly looked at the patch and I'm a bit worried that everything gets removed from the context finder, since their might be classes (not from plug-ins) that are needed by the app. Moreover we would have a very different behavior when running with jnlp and with not, which we would want to avoid.
What about parenting the context finder with a filtered version of what's on the jnlp classloader so that we only get non-bundles. Note that we have the list of bundles in the osgi.bundles.
Neil could you help?
Comment 4 Neil Bartlett CLA 2006-04-16 18:08:40 EDT
Pascal,

I will help out wherever I can. The patch is admittedly naive and I didn't understand the full implications - it just got my app working.

The filtering classloader is interesting, but sounds difficult to achieve. We would presumably still need JNLPClassLoader as our ultimate parent, because only it knows where all the JARs are. However if we delegate to JNLPClassLoader and it returns a class, how do we know whether it came from a bundle JAR - even given that we know the list of bundles? It sounds like we would have to build a list of classes in all bundles, and only accept a class loaded by our parent if it was not on that list.

Note also that the problem only happens with "flat" bundle JARs. JNLPClassLoader can't see into nested JARs.
Comment 5 Thomas Watson CLA 2006-04-17 10:17:41 EDT
What if we took a child first approach in the ContextFinder?  In other words we would search the OSGi loaders first then the parent (original context loader) as a last resort.  This would allow the ContextFinder to get the class from the Framework before the JNLPClassLoader.
Comment 6 Thomas Watson CLA 2006-04-17 10:54:19 EDT
Filtering the parent classloader or changing to child-first would be too much change for 3.2 right now ...

We should look for a "simple" solution for 3.2.  Current thinking is to add an option which can be used specify the parent classloader of ContextFinder.  In WebStartMain we would set this property to force boot to be used unless it is already set to some other value in the config.ini.  A slight variation would be not to set the property in WebStartMain (this would use the current behavior) and force JNLP apps to set the value explicitly in their config.ini.
Comment 7 Thomas Watson CLA 2006-04-17 12:17:42 EDT
Created attachment 38689 [details]
patch

This patch introduces a new property to specify the context class loader parent "osgi.contextClassLoaderParent".  The default is the current behavior (which is to use the current context classloader as the parent).  The osgi.contextClassLoaderParent property can be set to the following

app - use the application classloader
ext - use the extension classloader
boot - use the boot classloader
fwk - use the framework classloader
ccl or <null> or any other value - use the current context class loader

There are similar values that can be specified on the osgi.parentClassloader property.

This patch makes the default for WebStartMain  use osgi.contextClassLoaderParent="app".  I do not know all the side-effects of such a change.  Maybe we should just leave WebStartMain as-is (default to <null>) and deployments have to option of setting the value to "app" in their config.ini.
Comment 8 Neil Bartlett CLA 2006-04-19 06:11:43 EDT
(In reply to comment #7)

I can confirm that this patch fixes the issue I was having when using dynamic proxies under WebStart. I did not bother applying the patch to WebStartMain, I just put osgi.contextClassLoaderParent=app into my JNLP.

Thanks
Comment 9 Thomas Watson CLA 2006-04-19 09:52:44 EDT
+1 to only add the optional property osgi.contextClassLoaderParent and leaving WebStartMain unchanged.

Jeff, do you approve?
Comment 10 Simon Kaegi CLA 2006-04-19 10:04:05 EDT
Just a comment...
I'm doing something very similar for the CCL with the server-side stuff.
I wonder if it would make sense to move the CCL initialization code into the framework?
Comment 11 Jeff McAffer CLA 2006-04-19 17:18:39 EDT
I think the CCL init code is in the framework.  As I understand this proposal it is ot add that code to the framework and leave the webstart main alone.  Then people who have webstart prblems can set the right property.

+1 for that behaviour

See also bug 137608 for some discussion on directions for startup code...
Comment 12 Simon Kaegi CLA 2006-04-19 17:27:06 EDT
Sorry, yes you're right it's in the framework not the launcher which is what I was hoping for.
So... great, I'll use it. Thanks.
Comment 13 Thomas Watson CLA 2006-04-19 17:41:49 EDT
Fix released for RC2. (no change to WebStartMain)