Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 297769

Summary: Split packages are not refreshed properly
Product: [Eclipse Project] Platform Reporter: Steffen Pingel <steffen.pingel>
Component: RuntimeAssignee: Thomas Watson <tjwatson>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: daniel_megert, john.arthorne, krzysztof.daniel, pascal, pwebster, remy.suen, shawn.minto, thebravoman, tjwatson
Version: 4.3Flags: krzysztof.daniel: review? (tjwatson)
Target Milestone: 4.3 M7   
Hardware: PC   
OS: Linux   
Whiteboard:
Bug Depends on:    
Bug Blocks: 297912    
Attachments:
Description Flags
log file running on Eclipse 3.6M4
none
Screenshot of F17 startup
none
Patch proposition
none
Express the cycle in org.eclipse.core.runtime package parts
none
Express the cycle in org.eclipse.core.runtime package parts (optionally) none

Description Steffen Pingel CLA 2009-12-14 15:27:52 EST
Starting with Eclipse 3.6M3 Mylyn's automated tests have been failing to load (see log). I haven't figured out what's wrong but noticed an exception in OSGi while looking into the problem:

osgi> ss org.eclipse.mylyn.tests

Framework is launched.

id      State       Bundle
271     <<LAZY>>    org.eclipse.mylyn.tests_0.0.0
272     RESOLVED    org.eclipse.mylyn.tests.performance_0.0.0
273     RESOLVED    org.eclipse.mylyn.tests.ui_0.0.0
274     RESOLVED    org.eclipse.mylyn.tests.util_0.0.0

osgi> diag org.eclipse.mylyn.tests
reference:file:dropins/test/plugins/org.eclipse.mylyn.tests_0.0.0/ [271]
  No unresolved constraints.

osgi> bundle 271
org.eclipse.mylyn.tests_0.0.0 [271]
  Id=271, Status=<<LAZY>>    Data Root=/home/tools/mylyn/eclipse/test-3.6M4/eclipse/configuration/org.eclipse.osgi/bundles/271/data
  No registered services.
  No services in use.
  Exported packages
    org.eclipse.mylyn.tests; version="0.0.0"[exported]
    org.eclipse.mylyn.tests.integration; version="0.0.0"[exported]
    org.eclipse.mylyn.tests.misc; version="0.0.0"[exported]
java.lang.NullPointerException
        at org.eclipse.osgi.internal.resolver.RequiresHolder.isExported(StateHelperImpl.java:525)
        at org.eclipse.osgi.internal.resolver.StateHelperImpl.getPackages(StateHelperImpl.java:404)
        at org.eclipse.osgi.internal.resolver.StateHelperImpl.getPackages(StateHelperImpl.java:410)
        at org.eclipse.osgi.internal.resolver.StateHelperImpl.getPackages(StateHelperImpl.java:410)
        at org.eclipse.osgi.internal.resolver.StateHelperImpl.getVisiblePackages(StateHelperImpl.java:355)
        at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._bundle(FrameworkCommandProvider.java:845)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:155)
        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:157)
        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.runConsole(FrameworkConsole.java:142)
        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:106)
        at java.lang.Thread.run(Thread.java:595)
Comment 1 Steffen Pingel CLA 2009-12-14 15:29:00 EST
Created attachment 154437 [details]
log file running on Eclipse 3.6M4
Comment 2 Thomas Watson CLA 2009-12-14 15:50:49 EST
(In reply to comment #1)
> Created an attachment (id=154437) [details]
> log file running on Eclipse 3.6M4

Could you give me details on the steps I could use to reproduce this (what to download, what mylyn tests to check out etc.)?  The java.lang.LinkageError is pretty concerning and something I would like to get to the bottom of.
Comment 3 Steffen Pingel CLA 2009-12-14 18:59:24 EST
I can reproduce the LinkageErrors with these steps on Linux/Gtk 32-bit:
1. Extract Eclipse SDK 3.6M4
2. Unzip http://mylyn.eclipse.org/tmp/mylyn-I20091214-1100-e3x.zip to dropins/
3. Run ./eclipse -data ws -console


Also saw this exception while doing "bundle 255" in the equinox console (plugins may not have been initialized completely when I ran the command, couldn't reproduce it afterwards).

java.lang.NullPointerException
        at org.eclipse.osgi.internal.loader.BundleLoaderProxy.addRequirers(BundleLoaderProxy.java:133)
        at org.eclipse.osgi.internal.loader.BundleLoaderProxy.addRequirers(BundleLoaderProxy.java:148)
        at org.eclipse.osgi.internal.loader.BundleLoaderProxy.getRequiringBundles(BundleLoaderProxy.java:120)
        at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._bundle(FrameworkCommandProvider.java:942)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:155)
        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:157)
        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.runConsole(FrameworkConsole.java:142)
        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:106)
        at java.lang.Thread.run(Thread.java:619)
Comment 4 Thomas Watson CLA 2009-12-15 11:43:38 EST
*** Bug 292879 has been marked as a duplicate of this bug. ***
Comment 5 Thomas Watson CLA 2009-12-15 11:51:46 EST
I have not been able to reproduce the error (on Mac) but I did run into another error in the dropins reconciler.  The mylyn tests contain a bundle javax.servlet (version 2.4).  There already exists a javax.servlet (version 2.5) in the platform.  When the dropins support installs (and refreshes) the new javax.servlet (version 2.4) bundle this forces the other version 2.5 of javax.servlet from the core platform to be refreshed.  This starts a whole chain reaction of refreshing of all the bundles that transitively depend on the existing javax.servlet version 2.5.  In the end almost the complete platform is refreshed.

My theory is that we end up with a newly refreshed org.eclipse.core.runtime and org.eclipse.equinox.registry bundle (with new class loaders) and somehow the old class loaders are still around with the old instances of the Plugin class.  And this causes us to have this strange LinkageError.  On a restart we should not see this error because we no longer need to install the bundles from dropins and refresh them.  But since tests are always run on a fresh configuration we never can run from a cache and we always are reconciling the dropins.

Is there any way you can remove the javax.servlet 2.4 bundle from your dropins?
Comment 6 Thomas Watson CLA 2009-12-15 12:06:48 EST
(In reply to comment #5)
> Is there any way you can remove the javax.servlet 2.4 bundle from your dropins?

I manually removed the javax.servlet version 2.4 from the test/plugins/ folder and from the feature.xml files for org.eclipse.mylyn.xplanner_feature and org.eclipse.mylyn.jira_feature.  This seemed to work around the reconciler issue I was seeing and I was able to launch eclipse from a clean install without error.
Comment 7 Steffen Pingel CLA 2009-12-15 15:50:17 EST
Thanks for the great explanation. I'll try removing it. I don't think we need to include the javax.servlet plug-in since it's part of platform but have been shipping it in case Mylyn is installed on platforms that don't have it, e.g. RCP application.
Comment 8 Thomas Watson CLA 2010-04-14 16:20:03 EDT
*** Bug 273466 has been marked as a duplicate of this bug. ***
Comment 9 Krzysztof Daniel CLA 2012-05-22 08:46:22 EDT
Created attachment 216027 [details]
Screenshot of F17 startup

Bad News: Eclipse in Fedora is dropins based. All users will see this error if they open a Task List view on first Eclipse launch.
Comment 10 Pascal Rapicault CLA 2012-05-22 08:53:19 EDT
I'm really surprised by such a move. Eclipse has been shipping in its regular app for years on Fedora and the recent change to dropins will result in more trouble than anything. Sure one company is shipping all of its products like that but it is the worst model ever and I know of a gadzillion way to break their install leaving them without a clue on how to recover. 
Honestly you should really consider moving back to the normal shape.
Comment 11 Krzysztof Daniel CLA 2012-05-22 10:17:59 EDT
(In reply to comment #10)
> I'm really surprised by such a move. Eclipse has been shipping in its regular
> app for years on Fedora and the recent change to dropins will result in more
> trouble than anything. Sure one company is shipping all of its products like
> that but it is the worst model ever and I know of a gadzillion way to break
> their install leaving them without a clue on how to recover. 
> Honestly you should really consider moving back to the normal shape.

I wish I could. That was the first thing that I wanted to do in eclipse build, and you are aware of efforts I have taken to get things working.

P2 director in its current shape is a no-go for Fedora, and logs indicate that it never was (I'll find some witness to verify that). Eclipse since 3.4 version seems to be shipped with dropins.

Since I can't get P2 working with RPM I'm focusing on removing bugs from reconciler to make the installation more predictable/less error prone, but I'm open for any investigations that could make RPM and P2 working together.
Comment 12 Steffen Pingel CLA 2012-05-22 10:38:49 EDT
Krzysztof, what is the exact error stacktrace you are getting when the Task List is loaded?
Comment 13 Krzysztof Daniel CLA 2012-05-22 11:45:04 EDT
The stacktrace in the view is really long. The original user log was uploaded here: https://bugzilla.redhat.com/attachment.cgi?id=585995
Comment 14 Krzysztof Daniel CLA 2013-03-05 06:40:33 EST
I got hit by this again.

Thomas,

do you have any idea where to look for leaked classloader that holds old definition during refresh?
Comment 15 Krzysztof Daniel CLA 2013-03-05 09:05:21 EST
The error is:
Caused by: java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.eclipse.core.internal.plugins.PluginDescriptor.getPlugin()Lorg/eclipse/core/runtime/Plugin;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, org/eclipse/core/internal/plugins/PluginDescriptor, and the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) for interface org/eclipse/core/runtime/IPluginDescriptor have different Class objects for the type or.getPlugin()Lorg/eclipse/core/runtime/Plugin; used in the signature
	at org.eclipse.core.internal.plugins.PluginRegistry.getPluginDescriptor(PluginRegistry.java:117)
	at org.eclipse.core.internal.plugins.PluginRegistry.getPluginDescriptor(PluginRegistry.java:104)
	at org.eclipse.core.runtime.Platform.getPlugin(Platform.java:732)
	at org.eclipse.core.internal.preferences.legacy.InitLegacyPreferences.init(InitLegacyPreferences.java:43)


The short version of the error is:
org/eclipse/core/runtime/Plugin is loaded independently twice by org.eclipse.core.internal.plugins.PluginDescriptor and org/eclipse/core/runtime/IPluginDescriptor

The PluginDescriptor comes from org.eclipse.core.runtime.compatibility, but the IPluginDescriptor class is delivered twice - in org.eclipse.core.runtime.compatibility and org.eclipse.core.runtime.compatibility.registry.

The Plugin class comes from org.eclipse.core.runtime, from the same bundle that calls org.eclipse.core.runtime.Platform.getPlugin. In that light, it looks like the IPluginDescriptor managed to load "other" version of the Plugin class.

Any scenario that leads to that means that there is a serious bug in the Equinox classloading.
Comment 16 Krzysztof Daniel CLA 2013-03-06 04:29:01 EST
More data:
Those are plugins that request (in order) the Plugin class during fresh installation:
org.eclipse.core.runtime:3.9.0.v20130228-2041(id=40)]
org.eclipse.core.runtime.compatibility:3.2.200.v20130228-2041(id=41)]
org.eclipse.core.runtime:3.9.0.v20130228-2041(id=40)]
org.eclipse.core.runtime.compatibility:3.2.200.v20130228-2041(id=41)]
org.eclipse.ui.workbench:3.105.0.v20130228-2041(id=176)]
org.eclipse.emf.common:2.8.0.v20120911-0500(id=73)]
workspace selection dialog
org.eclipse.core.resources:3.8.100.v20130228-2041(id=39)]
org.eclipse.core.expressions:3.4.500.v20130228-2041(id=31)]
org.eclipse.help:3.6.0.v20130228-2041(id=127)]
org.eclipse.jdt.core:3.9.0.v20130228-2041(id=131)]
org.eclipse.team.core:3.7.0.v20130228-2041(id=154)]
org.eclipse.jdt.ui:3.9.0.v20130228-2041(id=216)]
org.eclipse.jdt.core.manipulation:1.5.0.v20130228-2041(id=210)]
org.eclipse.core.filebuffers:3.5.300.v20130228-2041(id=33)]
org.eclipse.ltk.core.refactoring:3.6.0.v20130228-2041(id=144)]
org.eclipse.debug.core:3.8.0.v20130228-2041(id=45)]
org.eclipse.compare.core:3.5.300.v20130228-2041(id=24)]
org.eclipse.jdt.launching:3.7.0.v20130228-2041(id=215)]
org.eclipse.mylyn.tasks.ui:3.9.0.I20130301-1122(id=269)]
org.eclipse.jdt.apt.core:3.3.500.v20130228-2041(id=205)]
org.eclipse.jdt.apt.pluggable.core:1.0.400.v20130228-2041(id=206)]
org.eclipse.core.variables:3.2.600.v20130228-2041(id=43)]

This is what happens during second run:
org.eclipse.core.runtime:3.9.0.v20130228-2041(id=40)]
org.eclipse.core.runtime.compatibility:3.2.200.v20130228-2041(id=41)]
org.eclipse.ui.workbench:3.105.0.v20130228-2041(id=176)]
org.eclipse.emf.common:2.8.0.v20120911-0500(id=73)]
workspace selection dialog
org.eclipse.core.resources:3.8.100.v20130228-2041(id=39)]
org.eclipse.core.expressions:3.4.500.v20130228-2041(id=31)]
org.eclipse.help:3.6.0.v20130228-2041(id=127)]
org.eclipse.jdt.core:3.9.0.v20130228-2041(id=131)]
org.eclipse.team.core:3.7.0.v20130228-2041(id=154)]
org.eclipse.jdt.ui:3.9.0.v20130228-2041(id=216)]
org.eclipse.jdt.core.manipulation:1.5.0.v20130228-2041(id=210)]
org.eclipse.core.filebuffers:3.5.300.v20130228-2041(id=33)]
org.eclipse.ltk.core.refactoring:3.6.0.v20130228-2041(id=144)]
org.eclipse.debug.core:3.8.0.v20130228-2041(id=45)]
org.eclipse.compare.core:3.5.300.v20130228-2041(id=24)]
org.eclipse.jdt.launching:3.7.0.v20130228-2041(id=215)]
org.eclipse.mylyn.tasks.ui:3.9.0.I20130301-1122(id=269)]
org.eclipse.mylyn.commons.net:3.9.0.I20130301-1122(id=231)]
org.eclipse.mylyn.commons.core:3.9.0.I20130301-1122(id=228)]
org.eclipse.jdt.apt.core:3.3.500.v20130228-2041(id=205)]
org.eclipse.jdt.apt.pluggable.core:1.0.400.v20130228-2041(id=206)]
org.eclipse.core.variables:3.2.600.v20130228-2041(id=43)]
org.eclipse.mylyn.trac.core:3.9.0.I20130301-1122(id=272)]
org.eclipse.mylyn.bugzilla.core:3.9.0.I20130301-1122(id=224)]
org.eclipse.mylyn.context.core:3.9.0.I20130301-1122(id=245)]
org.eclipse.team.cvs.core:3.3.500.v20130228-2041(id=155)]
org.eclipse.jsch.core:1.1.400.v20130228-2041(id=142)]

Notable differences:
org.eclipse.core.runtime and org.eclipse.core.runtime.compatibility load the Plugin twice before the workspace selection dialog is shown during first launch.


Also, failures prevent proper org.eclipse.mylyn.tasks.ui and org.eclipse.team.core.ui initialization. The LinkageError comes always from 
	at org.eclipse.core.internal.plugins.PluginRegistry.getPluginDescriptor(PluginRegistry.java:117)
	at org.eclipse.core.internal.plugins.PluginRegistry.getPluginDescriptor(PluginRegistry.java:104)
	at org.eclipse.core.runtime.Platform.getPlugin(Platform.java:732)
	at org.eclipse.core.internal.preferences.legacy.InitLegacyPreferences.init(InitLegacyPreferences.java:43)
	at org.eclipse.core.internal.preferences.PreferenceServiceRegistryHelper.applyRuntimeDefaults(PreferenceServiceRegistryHelper.java:147)
Comment 17 Krzysztof Daniel CLA 2013-03-06 05:48:12 EST
So... The exception appears for the first time here:

Daemon Thread [Refresh Packages] (Suspended)	
	owns: Class<T> (org.eclipse.core.internal.runtime.CompatibilityHelper) (id=11937)	
	owns: PackageAdminImpl  (id=25)	
	CompatibilityHelper.getPluginDescriptor(String) line: 67	
	CompatibilityActivator.start(BundleContext) line: 22	
	BundleContextImpl$1.run() line: 711	
	AccessController.doPrivileged(PrivilegedExceptionAction<T>) line: not available [native method]	
	BundleContextImpl.startActivator(BundleActivator) line: 702	
	BundleContextImpl.start() line: 683	
	BundleHost.startWorker(int) line: 381	
	BundleHost(AbstractBundle).start(int) line: 300	
	SecureAction.start(Bundle, int) line: 440	
	BundleLoader.setLazyTrigger() line: 263	
	EclipseLazyStarter.postFindLocalClass(String, Class<?>, ClasspathManager) line: 107	
	ClasspathManager.findLocalClass(String) line: 469	
	DefaultClassLoader.findLocalClass(String) line: 216	
	BundleLoader.findLocalClass(String) line: 395	
	BundleLoader.findClassInternal(String, boolean, ClassLoader) line: 464	
	BundleLoader.findClass(String, boolean) line: 421	
	BundleLoader.findClass(String) line: 412	
	DefaultClassLoader.loadClass(String, boolean) line: 107	
	DefaultClassLoader(ClassLoader).loadClass(String) line: 356	
	BundleLoader.loadClass(String) line: 340	
	BundleHost.loadClass(String, boolean) line: 229	
	BundleHost(AbstractBundle).loadClass(String) line: 1212	
	CompatibilityHelper.getPluginDescriptor(String) line: 63	
	PlatformActivator(Plugin).initializeDescriptor(String) line: 767	
	PlatformActivator(Plugin).start(BundleContext) line: 753	
	PlatformActivator.start(BundleContext) line: 33	
	BundleContextImpl$1.run() line: 711	
	AccessController.doPrivileged(PrivilegedExceptionAction<T>) line: not available [native method]	
	BundleContextImpl.startActivator(BundleActivator) line: 702	
	BundleContextImpl.start() line: 683	
	BundleHost.startWorker(int) line: 381	
	BundleHost(AbstractBundle).start(int) line: 300	
	PackageAdminImpl.resumeBundles(AbstractBundle[], boolean, int[]) line: 312	
	PackageAdminImpl.processDelta(BundleDelta[], boolean, State) line: 556	
	PackageAdminImpl.doResolveBundles(Bundle[], boolean, FrameworkListener[]) line: 251	
	PackageAdminImpl$1.run() line: 174	
	Thread.run() line: 722	

But is kindly ignored by the catch:
} catch (Exception e) {
			if (DEBUG) {
				String msg = "Error running compatibility code"; //$NON-NLS-1$
				IStatus error = new Status(IStatus.ERROR, Platform.PI_RUNTIME, 1, msg, e);
				InternalPlatform.getDefault().log(error);
			}
			//Ignore the exceptions, return null			
		}

I think it may be caused by a reflection used to load internal platform, which is not aware of bundles refresh.
Comment 18 Krzysztof Daniel CLA 2013-03-06 09:18:42 EST
Yet another observation - I've put a breakpoint in DefaultClassLoader#loadClass.

(A) Classloader @53d289a4 for org.eclipse.core.runtime loads:
(1)  org.eclipse.core.runtime.Plugin with hashcode 779219052
(2)  org.eclipse.core.runtime.IPluginDescriptor with hashcode 1542960903


(B) Classloader @4db03533 for org.eclipse.core.runtime.compatibility loads:
(3) org.eclipse.core.runtime.Plugin 779219052
(4) org.eclipse.core.runtime.IPluginDescriptor 1542960903
(5) org.eclipse.core.internal.plugins.PluginDescriptor 1075544259

So far, so good. hashcode match in both classloaders. But then a refresh happens, and:

(C) Classloader @3d44214e for org.eclipse.core.runtime loads:
(6) org.eclipse.core.runtime.Plugin with hashcode 1966508122

(D) Classloader @160113ef for org.eclipse.core.runtime.compatibility loads:
(7) org.eclipse.core.runtime.Plugin 1966508122
(8) org.eclipse.core.runtime.IPluginDescriptor 1542960903
(9) org.eclipse.core.internal.plugins.PluginDescriptor 1491048155

The class D-8 is obviously wrong - it has the same code that class A-2 and B-4, but all classloader had been changed!

After putting a right breakpoint in the loadClass method I got this stack responsible for loading a wrong IPluginDescriptor:

java.lang.Exception: Stack trace
	at java.lang.Thread.dumpStack(Thread.java:1342)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:109)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2451)
	at java.lang.Class.getMethod0(Class.java:2694)
	at java.lang.Class.getMethod(Class.java:1622)
	at org.eclipse.core.internal.runtime.CompatibilityHelper.getPluginDescriptor(CompatibilityHelper.java:66)
	at org.eclipse.core.internal.plugins.CompatibilityActivator.start(CompatibilityActivator.java:22)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
	at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
	at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:300)
	at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:440)
	at org.eclipse.osgi.internal.loader.BundleLoader.setLazyTrigger(BundleLoader.java:263)
	at org.eclipse.core.runtime.internal.adaptor.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)
	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:469)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:395)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:464)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
	at org.eclipse.osgi.internal.loader.BundleLoader.loadClass(BundleLoader.java:340)
	at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleHost.java:229)
	at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadClass(AbstractBundle.java:1212)
	at org.eclipse.core.internal.runtime.CompatibilityHelper.getPluginDescriptor(CompatibilityHelper.java:65)
	at org.eclipse.core.runtime.Plugin.initializeDescriptor(Plugin.java:767)
	at org.eclipse.core.runtime.Plugin.start(Plugin.java:753)
	at org.eclipse.core.internal.runtime.PlatformActivator.start(PlatformActivator.java:33)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
	at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
	at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:300)
	at org.eclipse.osgi.framework.internal.core.PackageAdminImpl.resumeBundles(PackageAdminImpl.java:312)
	at org.eclipse.osgi.framework.internal.core.PackageAdminImpl.processDelta(PackageAdminImpl.java:556)
	at org.eclipse.osgi.framework.internal.core.PackageAdminImpl.doResolveBundles(PackageAdminImpl.java:251)
	at org.eclipse.osgi.framework.internal.core.PackageAdminImpl$1.run(PackageAdminImpl.java:174)
	at java.lang.Thread.run(Thread.java:722)


After cutting the classloading stuff:

[loading old IPluginDescriptor from classloader]
	at org.eclipse.core.internal.runtime.CompatibilityHelper.getPluginDescriptor(CompatibilityHelper.java:66)
	at org.eclipse.core.internal.plugins.CompatibilityActivator.start(CompatibilityActivator.java:22)
[starting compatibility]
	at org.eclipse.core.internal.runtime.CompatibilityHelper.getPluginDescriptor(CompatibilityHelper.java:65)
	at org.eclipse.core.runtime.Plugin.initializeDescriptor(Plugin.java:767)
	at org.eclipse.core.runtime.Plugin.start(Plugin.java:753)
	at org.eclipse.core.internal.runtime.PlatformActivator.start(PlatformActivator.java:33)
[processing delta - refresh]

Thomas,
how is it possible that Activator manages to load obsoleted class? Is it possible that at some level of platform shutdown (compatibility stop is a very nasty method) the IPluginDescriptor leaked into framework classloader?
Comment 19 Krzysztof Daniel CLA 2013-03-06 10:10:57 EST
More weird things: the class org.eclipse.core.runtime.IPluginDescriptor is misloaded from org.eclipse.equinox.registry after framework refresh.
Comment 20 Thomas Watson CLA 2013-03-06 17:20:30 EST
(In reply to comment #18)
> Thomas,
> how is it possible that Activator manages to load obsoleted class? Is it
> possible that at some level of platform shutdown (compatibility stop is a
> very nasty method) the IPluginDescriptor leaked into framework classloader?

First of all, thanks for looking into this and doing all the diagnostics.

I'm still at a loss as to what is going wrong or why the old class is getting referenced after a refresh.  When the refresh operation is going on do you know the list of bundles that are being requested to be refreshed?  It appears that a lot of low-level bundles are getting refreshed here, such as org.eclipse.core.runtime and org.eclipse.equinox.registry but that should really refresh all the class loaders involved and start fresh.

I see that org.eclipse.core.internal.plugins.InternalPlatform.getPluginDescriptor(String) from org.eclipse.core.runtime.compatibility makes a call out to a static variable 'registry' that ultimately has map of PluginDescriptors.  It would be good to know if this org.eclipse.core.internal.plugins.InternalPlatform.registry variable also got refreshed and has a new hashcode after the refresh.  If not then I can see how this map would have references to old objects created with the old classes.
Comment 21 Thomas Watson CLA 2013-03-06 17:21:52 EST
(In reply to comment #19)
> More weird things: the class org.eclipse.core.runtime.IPluginDescriptor is
> misloaded from org.eclipse.equinox.registry after framework refresh.

What do you mean here?  It sounds as if the org.eclipse.core.runtime.compatibility.registry fragment did not attach properly to org.eclipse.equinox.registry after the refresh?
Comment 22 Krzysztof Daniel CLA 2013-03-07 06:13:00 EST
I put a breakpoint into InternalPlatform.getPluginRegistry - the output I got is:
org.eclipse.core.runtime@1b4775ba loads Plugin 463989851
org.eclipse.core.runtime.compatibility@5e066f43 loads IPluginDescriptor 2069743059
org.eclipse.core.runtime.compatibility@5e066f43 loads PluginDescriptor 1830175993
org.eclipse.core.runtime.compatibility@5e066f43 loads Plugin 463989851
org.eclipse.core.runtime@1b4775ba loads IPluginDescriptor 2069743059

All is OK. The hashcode for the registry is 715402562.

Then refresh happens - here is a list of (somewhat stripped) bundles captured in PackageAdminImpl.refreshPackages:

org.eclipse.core.runtime.compatibility.auth_3.2.200.I20130301-1122 [200]
org.eclipse.core.runtime_3.9.0.v20130307-0857 [40]


During refresh - the registry is referred twice - still in the old version. Then something magical happens:
org.eclipse.core.runtime@170e153b loads Plugin 1515158976
org.eclipse.core.runtime.compatibility@73b7122f loads IPluginDescriptor 2069743059 (OLD ONE!!!)

and now registry object is accessed again and it gets a new hash code 186317623.
Comment 23 Krzysztof Daniel CLA 2013-03-07 08:52:48 EST
One step forward:
It looks like the IPluginDescriptor is *never* loaded from org.eclipse.core.runtime. The *.class file is duplicated in org.eclipse.equinox.compatibility.registry, which is a fragment for org.eclipse.equinox.registry. 

I found this by watching MultiSourcePackage which always provides bundles in the following order when loading IPluginDescriptor:
org.eclipse.equinox.common
org.eclipse.equinox.registry
org.eclipse.core.runtime

I guess that's why the IPluginDescriptor class is not refreshed - because it's being held in the org.eclipse.equinox.registry! What's more (and for what I have learned during debugging), this is intentional and valid behaviour - IPluginDescriptor should not be refreshed.

Now I must trust myself that my previous observation was right:
> org/eclipse/core/runtime/Plugin is loaded independently twice by org.eclipse.core.internal.plugins.PluginDescriptor and org/eclipse/core/runtime/IPluginDescriptor

IPluginDescriptor is not refreshed while PluginDescriptor is. I guess that "old" IPluginDescriptor brings "old" Plugin, which was removed during org.eclipse.core.runtime refresh.

The only mystery that is still present is how the equinox.registry is able to solve IPluginDescriptor - because there's no direct dependency to core.runtime - but I guess this is somehow resolved by using "split" packages.

And I guess this is the ultimate source of problems - refresh of a bundle that exports a split package does not cause a refresh of all other bundles that export the same split package!
Comment 24 Krzysztof Daniel CLA 2013-03-08 06:19:52 EST
Created attachment 228131 [details]
Patch proposition

By no means can I claim it's a valid patch.  Probably there's better approach, but this one seems to work fine.
Comment 25 Thomas Watson CLA 2013-03-08 08:56:08 EST
(In reply to comment #24)
> Created attachment 228131 [details]
> Patch proposition
> 
> By no means can I claim it's a valid patch.  Probably there's better
> approach, but this one seems to work fine.

Thanks, I will try to have a look for M6, but likely will not get into all the details until M7.
Comment 26 Krzysztof Daniel CLA 2013-03-11 12:10:37 EDT
*** Bug 384686 has been marked as a duplicate of this bug. ***
Comment 27 Thomas Watson CLA 2013-03-12 15:40:51 EDT
Created attachment 228305 [details]
Express the cycle in org.eclipse.core.runtime package parts

Looking at this in more detail I am worried that a solution that involves refreshing all contributors of a split package is not the correct behavior.

I think the central issue is that the org.eclipse.core.runtime.compatibility.registry bundle introduces a very strange cycle between the different 'parts' of the split package org.eclipse.core.runtime.  I am not entirely sure how this can be working at runtime, but somehow it does.

There is a class file org.eclipse.core.runtime.IPluginDescriptor that is included in a 'classes' folder of the org.eclipse.core.runtime.compatibility.registry project.  The reason this is a pre-compiled class is a bit dubious.  Questions come to mind about why is this not a java file that we compile like the other classes in the org.eclipse.core.runtime.compatibility.registry bundle?

The reason is that this class references types that are found in the org.eclipse.core.runtime package part contained in the bundle of the same name org.eclipse.core.runtime.  Here are the types I found which it references from the org.eclipse.core.runtime bundle:

org.eclipse.core.runtime.ILibrary
org.eclipse.core.runtime.Plugin
org.eclipse.core.runtime.IPluginPrerequisite

But at runtime the org.eclipse.core.runtime.compatibility.registry host bundle org.eclipse.equinox.registry has no class space requirements on the org.eclipse.core.runtime bundle (or its split part of the org.eclipse.core.runtime package).  So it is questionable how such an interface is able to be defined by the host org.eclipse.equinox.registry bundle class loader, but it seems to 'work' so I will have to brush that aside for now.

So my argument is that the org.eclipse.core.runtime.compatibility.registry introduces an invalid cycle in the different parts of the org.eclipse.core.runtime but this cycle is not expressed at runtime so we get into this inconsistent state when one of the package parts for org.eclipse.core.runtime is refreshed, but other parts involved in the cycle of the org.eclipse.core.runtime package are not refreshed.

It would be great to just drop this org.eclipse.core.runtime.compatibility.registry fragment bundle.  But if that cannot be done for Kepler then we should at least try to express some runtime dependency that tells the framework there is a cycle here.

I attached a patch that add the following requirement to org.eclipse.core.runtime.compatibility.registry bundle manifest:

Require-Capability: osgi.identity; filter:="(osgi.identity=org.eclipse.core.runtime)"

This should cause the org.eclipse.core.runtime.compatibility.registry fragment (and its host org.eclipse.equinox.registry) to get pulled into a refresh operation if the org.eclipse.core.runtime bundle is refreshed for any reason.  There are two concerns with this approach:

1) May get a debug log about cycles on shutdown if debug is enabled.  I argue, so what! this is a cycle we just were not expressing it before!

2) May cause class path cycle issues when building the org.eclipse.core.runtime.compatibility.registry fragment with PDE-Build or CBI.  In this case I hope not since the osgi.identity requirement should not contribute to the class path computation at all and hopefully is ignored, but this would need to be confirmed.

Krzysztof, are you in any position to test this change out with a CBI build? and then also test out that it fixes your failing scenario?
Comment 28 Krzysztof Daniel CLA 2013-03-13 04:36:14 EDT
No such luck:

Caused by: java.lang.RuntimeException: org.osgi.framework.BundleException: Bundle org.eclipse.core.runtime.compatibility.registry cannot be resolved
Resolution errors:
   Bundle org.eclipse.core.runtime.compatibility.registry - Missing Constraint: Require-Capability: osgi.identity; filter="(osgi.identity=org.eclipse.core.runtime)"
Comment 29 Krzysztof Daniel CLA 2013-03-13 07:52:32 EDT
But being less subtle seems to work:
+ Require-Bundle: org.eclipse.core.runtime

Anyway, I'm not sure where I have found this, but I have read that split packages exist in one space and can reference themselves even when they are in different bundles.

That's the only reasonable explanation why current solution works - otherwise the IPluginDescriptor could not be resolved in org.eclipse.equinox.registry, which has no direct dependency on org.eclipse.core.runtime - and this is the problem, because core.runtime refresh does not cause equinox.registry refresh.

I believe the right thing to do is to refresh all contributors of a split package, or at least ensure that the main one is refreshed - because when there is no direct dependency between bundles, there's still an implicit dependency.

Of course the problem is how to distinguish split packages from duplicated exports - f.e. system.bundle provides javax.xml, but adding javax.xml should not cause a refresh of the system bundle... 

Split packages are evil :-(.
Comment 30 Thomas Watson CLA 2013-03-13 08:21:52 EDT
(In reply to comment #29)
> But being less subtle seems to work:
> + Require-Bundle: org.eclipse.core.runtime
> 
> Anyway, I'm not sure where I have found this, but I have read that split
> packages exist in one space and can reference themselves even when they are
> in different bundles.
> 
> That's the only reasonable explanation why current solution works -
> otherwise the IPluginDescriptor could not be resolved in
> org.eclipse.equinox.registry, which has no direct dependency on
> org.eclipse.core.runtime - and this is the problem, because core.runtime
> refresh does not cause equinox.registry refresh.

It sounds correct, but it is not.  The org.eclipse.core.runtime.compatibility.registry fragment gets attached to the org.eclipse.equinox.registry host bundle.  There is one class loader for the org.eclipse.equinox.registry that loads all the classes from the host bundle and all of its attached fragment bundles.  Currently there is no dependency from the org.eclipse.equinox.registry to the org.eclipse.core.runtime bundle so the bundle class loader for org.eclipse.equinox.registry has no visibility to the types in the package org.eclipse.core.runtime defined in the org.eclipse.core.runtime bundle.  As a test you can attempt to do Bundle.loadClass("org.eclipse.core.runtime.ILibrary") on the bundle object for the org.eclipse.equinox.registry bundle.  It will not load that class!

What I suspect is happening is some VM delayed verification.  Basically we have a PluginDescriptor implementation in the bundle org.eclipse.core.runtime.compatibility which implements IPlugionDescriptor from the org.eclipse.core.runtime.compatibility.registry.  The VM does not really do any verification of the IPlugionDescriptor when that interface is defined by the org.eclipse.equinox.registry.  Instead when the PluginDescriptor from org.eclipse.core.runtime.compatibility is loaded and used then all the types are loaded from the initiating class loader perspective.  That would be from the org.eclipse.core.runtime.compatibility perspective which does have visibility to all the necessary types.

> 
> I believe the right thing to do is to refresh all contributors of a split
> package, or at least ensure that the main one is refreshed - because when
> there is no direct dependency between bundles, there's still an implicit
> dependency.
> 
> Of course the problem is how to distinguish split packages from duplicated
> exports - f.e. system.bundle provides javax.xml, but adding javax.xml should
> not cause a refresh of the system bundle... 
> 
> Split packages are evil :-(.
Comment 31 Thomas Watson CLA 2013-03-13 08:23:54 EDT
(In reply to comment #28)
> No such luck:
> 
> Caused by: java.lang.RuntimeException: org.osgi.framework.BundleException:
> Bundle org.eclipse.core.runtime.compatibility.registry cannot be resolved
> Resolution errors:
>    Bundle org.eclipse.core.runtime.compatibility.registry - Missing
> Constraint: Require-Capability: osgi.identity;
> filter="(osgi.identity=org.eclipse.core.runtime)"

What is this error from?  A CBI build?
Comment 32 Krzysztof Daniel CLA 2013-03-13 08:27:46 EDT
(In reply to comment #31)
> What is this error from?  A CBI build?
Yes.
Comment 33 Thomas Watson CLA 2013-03-13 08:37:44 EDT
(In reply to comment #29)
> But being less subtle seems to work:
> + Require-Bundle: org.eclipse.core.runtime
> 

This approach will cause strange inconsistencies for who defines the org.eclipse.core.runtime.IPluginDescriptor class.  Right now we know it will be loaded from the org.eclipse.equinox.registry bundle class loader because we have a non cyclic chain:

org.eclipse.core.runtime.compatibility
  -> org.eclipse.core.runtime
     -> org.eclipse.equinox.registry

If you introduce a cycle back to org.eclipse.core.runtime from the org.eclipse.core.runtime.compatibility.registry fragment it will place a payload requirement on the host bundle org.eclipse.equinox.registry back to org.eclipse.core.runtime:

org.eclipse.core.runtime.compatibility
  -> org.eclipse.core.runtime
     -> org.eclipse.equinox.registry
        -> org.eclipse.core.runtime

Now we have a very evil situation:

1) org.eclipse.osgi.runtime package is split
2) org.eclipse.orgi.runtime package has a shadowed class IPluginDescriptor defined by two bundles
3) the two bundles that contain the shadowed class IPluginDescriptor are involved in a cycle.

Here we have a nasty situation that leads to inconsistent class loading situations.  Imagine the following call:

  Bundle[org.eclipse.equinox.registry].loadClass(...IPluginDescriptor)

This will follow OSGi delegation for require-bundle org.eclipse.core.runtime and look for the class in the org.eclipse.core.runtime bundle and find it and define it.

Now imagine we instead started with :

  Bundle[org.eclipse.core.runtime].loadClass(...IPluginDescriptor)

This will follow OSGi delegation for require-bundle org.eclipse.equinox.registry and look for the class in the org.eclipse.equinox.registry bundle and find it and define it.

I think this would be a very confusing situation at best and could lead to strange cast exceptions in the worst case.
Comment 34 Thomas Watson CLA 2013-03-13 08:56:43 EDT
(In reply to comment #32)
> (In reply to comment #31)
> > What is this error from?  A CBI build?
> Yes.

Sorry I hope it is an easy test for you, but could you change the header to:

Require-Capability: osgi.identity; filter:="(osgi.identity=org.eclipse.core.runtime)"; resolution:=optional

By adding the directive resolution:=optional it should make the dependency optional, but it likely is a stretch that CBI will understand this means it is an optional dependency.
Comment 35 Krzysztof Daniel CLA 2013-03-13 09:07:40 EDT
(In reply to comment #34)
> Sorry I hope it is an easy test for you

It's not. The build has passed through the resolution part - but it takes about 40 minutes up to an hour before it's completed and tested (for this issue).
Comment 36 Krzysztof Daniel CLA 2013-03-13 10:24:27 EDT
The build succeeded. I was able to start Eclipse, and Mylyn got loaded from the very first time properly. I think the last approach solves the problem.

What is this notation of specifying the requirement?
Comment 37 Thomas Watson CLA 2013-03-13 10:39:04 EDT
(In reply to comment #36)
> The build succeeded. I was able to start Eclipse, and Mylyn got loaded from
> the very first time properly. I think the last approach solves the problem.
> 
> What is this notation of specifying the requirement?

In OSGi R5 (implemented in Juno) every bundle gets an implicit capability called osgi.identity.  This capability inherits its properties from the Bundle-SymbolicName and Bundle-Version header and in most respects is similar to the osgi.wiring.bundle capability (used to resolve Require-Bundle dependencies), but the osgi.identity capability has no implications on class loading delegation like Require-Bundle does.  

It is only a requirement that enforces that there is a resource available in the environment that has the osgi.identity with a value of org.eclipse.core.runtime.  Now making that an optional dependency is the true definition of a hack here.  Basically it is stating that we want to have the org.eclipse.equinox.registry bundle (through the payload requirement from one of its attached fragments) to get wired to the org.eclipse.core.runtime resource.  But we make it optional so that the fragment will not fail resolution of the org.eclipse.core.runtime bundle is not available.  But in reality there is no way the compatibility.registry fragment could work without the org.eclipse.core.runtime bundle present so in my mind it really is not an optional requirement, but I suggest we got with this approach for now.

Why I suspect the CBI build is failing is because whatever is modeling the resources in the build likely has no idea that all OSGi resources should get assigned to provide this implicit osgi.identity capability.
Comment 38 Thomas Watson CLA 2013-03-19 12:59:37 EDT
Created attachment 228669 [details]
Express the cycle in org.eclipse.core.runtime package parts (optionally)
Comment 39 Thomas Watson CLA 2013-03-19 13:07:19 EDT
Moving to Platform->Runtime where org.eclipse.core.runtime.compatibility.registry lives.