Community
Participate
Working Groups
Build Identifier: 3.7.0 Installation of org.eclipse.core.registry into Virgo highlighted a race condition which resulted in a NullPointerException caused by org.eclipse.core.runtime. During initialization of the registry, the runtime's getResourceBundle() was generating a NullPointerExcpetion: Caused by: java.lang.NullPointerException at org.eclipse.core.internal.runtime.ResourceTranslator.getResourceBundle(ResourceTranslator .java:69) at org.eclipse.core.internal.runtime.ResourceTranslator.getResourceBundle(ResourceTranslator .java:61) at org.eclipse.core.internal.registry.osgi.EclipseBundleListener.addBundle(EclipseBundleList ener.java:177) at org.eclipse.core.internal.registry.osgi.EclipseBundleListener.processBundles(EclipseBundl eListener.java:90) at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.onStart(RegistryStrategyOSGI .java:224) at org.eclipse.core.internal.registry.ExtensionRegistry.<init>(ExtensionRegistry.java:725) The code in question is as follows, with the 'return' statement being line 69: private static ResourceBundle getResourceBundle(Bundle bundle, String language) throws MissingResourceException { if (hasRuntime21(bundle)) { Locale locale = (language == null) ? Locale.getDefault() : new Locale(language); return ResourceBundle.getBundle("plugin", locale, createTempClassloader(bundle)); //$NON-NLS-1$ } return Activator.getDefault().getLocalization(bundle, language); } The conclusion is that the Activator.getDefault() is therefore returning null. This just returns the value of 'singleton' which is installed as part of the start() of the bundle, but not before some services have been acquired: org.eclipse.core.internal.runtime.Activator public void start(BundleContext context) throws Exception { RuntimeLog.setLogWriter(getPlatformWriter(context)); bundleContext = context; singleton = this; The getPlatformWriter() call is doing service acquisition, which Virgo is obviously interpreting and then calling back the bundle. But because the bundle context and singleton are not set by this point, the bundle's calls fail with this result. The fix would seem to be to move the acquistion of the log as follows: public void start(BundleContext context) throws Exception { bundleContext = context; singleton = this; RuntimeLog.setLogWriter(getPlatformWriter(context)); Reproducible: Always Steps to Reproduce: 1. Install Eclipse-Virgo 3.0.1 2. Install org.eclipse.equinox.registry 3. See NPE in log
More information from the osgi console of Virgo with versions 0 ACTIVE org.eclipse.osgi_3.7.0.v20110613 127 RESOLVED org.eclipse.equinox.registry_3.5.100.v20110502 osgi> packages org.eclipse.core.runtime org.eclipse.core.runtime; version="3.4.0"<org.eclipse.equinox.common_3.6.0.v20110523 [77]> org.springframework.core_3.0.5.RELEASE [83] imports org.eclipse.core.jobs_3.5.100.v20110404 [126] imports org.eclipse.equinox.registry_3.5.100.v20110502 [127] imports org.eclipse.core.runtime; version="3.4.0"<org.eclipse.equinox.registry_3.5.100.v20110502 [127]> osgi>
Here's the link to the git repository with the specific line: http://git.eclipse.org/c/equinox/rt.equinox.bundles.git/tree/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/Activator.java#n78
Note: you do not see this behaviour if org.eclipse.equinox.common is started before org.eclipse.equinox.registry. I still cannot reproduce this outside of Virgo. I wonder if it's because Virgo is using a LogReaderService, which is calling back to the bundle to ask its name? Equinox standalone: {org.osgi.service.log.LogReaderService, org.eclipse.equinox.log.ExtendedLogReaderService}={service.id=9} Registered by bundle: org.eclipse.osgi_3.7.0.v20110613 [0] Bundles using service: org.eclipse.equinox.common_3.6.0.v20110523 [2] Virgo+Equinox: {org.osgi.service.log.LogReaderService, org.eclipse.equinox.log.ExtendedLogReaderService}={service.id=6} "Registered by bundle:" org.eclipse.osgi_3.7.0.v20110613 [0] "Bundles using service" org.eclipse.virgo.medic.core_3.0.1.RELEASE [9] org.eclipse.virgo.kernel.shell_3.0.1.RELEASE [38] org.eclipse.virgo.medic.core_3.0.1.RELEASE [119] org.eclipse.equinox.common_3.6.0.v20110523 [77]
Thanks for the analysis, Alex. Fixed and pushed to master.
I tried to test this fix using Virgo with the 3.8 nightly build N20110924-2000, but the problem reproduced (see below). Please could you tell me whether the fix was present in that build and, if not, which nightly build it will appear in. [2011-09-26 16:13:45.233] fs-watcher <HD0002E> Hot deploy failed for file 'org.eclipse.equinox.registry_3.5.200.N20110924-2000.jar'. org.eclipse.virgo.kernel.deployer.core.DeploymentException: BundleException at org.eclipse.virgo.kernel.install.artifact.internal.bundle.StandardBundleDriver.startBundle(StandardBundleDriver.java:171) at org.eclipse.virgo.kernel.install.artifact.internal.bundle.StandardBundleDriver.start(StandardBundleDriver.java:150) at org.eclipse.virgo.kernel.install.artifact.internal.bundle.StandardBundleInstallArtifact.doStart(StandardBundleInstallArtifact.java:271) at org.eclipse.virgo.kernel.install.artifact.internal.AbstractInstallArtifact.driveDoStart(AbstractInstallArtifact.java:209) at org.eclipse.virgo.kernel.install.artifact.internal.bundle.StandardBundleInstallArtifact.start(StandardBundleInstallArtifact.java:260) at org.eclipse.virgo.kernel.deployer.core.internal.PipelinedApplicationDeployer.start(PipelinedApplicationDeployer.java:301) at org.eclipse.virgo.kernel.deployer.core.internal.PipelinedApplicationDeployer.deploy(PipelinedApplicationDeployer.java:208) at org.eclipse.virgo.kernel.deployer.hot.HotDeploymentFileSystemListener.deploy(HotDeploymentFileSystemListener.java:174) at org.eclipse.virgo.kernel.deployer.hot.HotDeploymentFileSystemListener.deployIfNotDeployed(HotDeploymentFileSystemListener.java:186) at org.eclipse.virgo.kernel.deployer.hot.HotDeploymentFileSystemListener.onChange(HotDeploymentFileSystemListener.java:87) at org.eclipse.virgo.util.io.FileSystemChecker.notifyListeners(FileSystemChecker.java:245) at org.eclipse.virgo.util.io.FileSystemChecker.check(FileSystemChecker.java:166) at org.eclipse.virgo.kernel.deployer.hot.WatchTask.run(WatchTask.java:58) at java.lang.Thread.run(Thread.java:680) Caused by: org.osgi.framework.BundleException: Exception in org.eclipse.core.internal.registry.osgi.Activator.start() of bundle org.eclipse.equinox.registry. at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:734) 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:299) at org.eclipse.virgo.kernel.core.internal.StandardBundleStarter.start(StandardBundleStarter.java:57) at org.eclipse.virgo.kernel.core.internal.StandardBundleStarter.start(StandardBundleStarter.java:45) 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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58) at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy63.start(Unknown Source) at org.eclipse.virgo.kernel.install.artifact.internal.bundle.StandardBundleDriver.startBundle(StandardBundleDriver.java:169) ... 13 common frames omitted Caused by: java.lang.NullPointerException: null at org.eclipse.core.internal.runtime.ResourceTranslator.getResourceBundle(ResourceTranslator.java:69) at org.eclipse.core.internal.runtime.ResourceTranslator.getResourceBundle(ResourceTranslator.java:61) at org.eclipse.core.internal.registry.osgi.EclipseBundleListener.addBundle(EclipseBundleListener.java:177) at org.eclipse.core.internal.registry.osgi.EclipseBundleListener.processBundles(EclipseBundleListener.java:90) at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.onStart(RegistryStrategyOSGI.java:224) at org.eclipse.core.internal.registry.ExtensionRegistry.<init>(ExtensionRegistry.java:725) at org.eclipse.core.runtime.RegistryFactory.createRegistry(RegistryFactory.java:58) at org.eclipse.core.internal.registry.osgi.Activator.startRegistry(Activator.java:137) at org.eclipse.core.internal.registry.osgi.Activator.start(Activator.java:56) 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) ... 37 common frames omitted
Yes, the code change is in that build.
Ok, then may I encourage you test the next version of the fix under Virgo as this is very straightforward: * Download Virgo Tomcat Server 3.0.1.RELEASE or later from the Virgo downloads page. * Unzip. * Place Equinox common into Viorgo's repository/usr and Equinox registry into Virgo's pickup. * Start Virgo by running its bin/startup.sh or bin\startup.bat. * Virgo will install Equinox registry and its dependency Equinox common and will start Equinox registry, which results in the NPE in the Virgo console. To try again, kill Virgo using Ctrl-C, update Equinox common and/or registry in the relevant directories and restart Virgo passing -clean on the startup script. Please let me know if you hit problems with this.
DJ did some investigation. It turns out that the common bundle is never marked for activation when placed in the repository/usr folder. Nothing is calling Bundle.start to either eagerly activate the bundle or activate it using the bundle's activation policy (which is lazy). Virgo also appears to have the setting osgi.compatibility.eagerStart.LazyActivation=false. If this setting is set to nothing (or true) then the framework will eagerly mark all lazy activation bundles to be started according to their lazy activation policies. The equinox.common bundle is expecting to be marked for lazily activation or be eagerly activated before clients of the common bundle. In the virgo case neither of these are happening and the common bundle is never activated. The original fix was based on Alex's analysis in comment 3. The common bundle was not setting its bundle context before initializing the log writer which would make the original NPE of this bug report possible (assuming common bundle was marked for lazy activation). I am tempted to mark this as fixed based on the original code fix, but I suspect in the virgo case this is really invalid since we do expect the common bundle to be marked for activation.
(In reply to comment #8) > DJ did some investigation. It turns out that the common bundle is never marked > for activation when placed in the repository/usr folder. Nothing is calling > Bundle.start to either eagerly activate the bundle or activate it using the > bundle's activation policy (which is lazy). When Virgo auto-installs dependency bundles from the repository, it generally starts those bundles. However, as can be seen from the code below (from org.eclipse.virgo.kernel.userregion.internal.quasiStandardQuasiFramework), dependencies bundles containing any declared activation policy, which according to the OSGi spec is currently equivalent to a lazy activation policy, are not started. The assumption was that such bundles will be activated automatically by the framework on first class load. But this assumption is wrong as such bundles need to be started in order to be readied for lazy activation. Assigning to Virgo to fix this aspect and re-test the failing scenario. /** * {@inheritDoc} */ public void commit() throws BundleException { synchronized (this.monitor) { if (this.otherBundles == null) { List<QuasiResolutionFailure> failures = resolve(); if (!failures.isEmpty()) { throw new BundleException("Commit resolution failed: '" + failures.toString() + "'"); } } else { try { Set<Long> installedQuasiBundles = installQuasiBundles(); List<Bundle> installedDependencies = installOtherBundles(installedQuasiBundles); startBundles(installedDependencies); } catch (BundleException e) { uninstallQuasiBundles(); throw e; } } } } private void startBundles(List<Bundle> bundles) throws BundleException { for (Bundle bundle : bundles) { startBundle(bundle); } } private void startBundle(Bundle bundle) throws BundleException { if (!isFragmentBundle(bundle)) { String bundleActivationPolicy = (String) bundle.getHeaders().get(Constants.BUNDLE_ACTIVATIONPOLICY); if (bundleActivationPolicy == null) { try { bundle.start(); } catch (BundleException be) { throw new BundleException("Failed to start bundle '" + bundle.getSymbolicName() + "' version '" + bundle.getVersion() + "'", be); } } } }
Virgo bug fixed in kernel commit a8e7618cd8fb7298c3c6e2cddd36b3ed75156381. Testing: Use Virgo Tomcat Server at HEAD plus the commit above. Updated Equinox to org.eclipse.osgi_3.8.0.N20111022-2000.jar. Grabbed Equinox common and registry from same nightly build. Put common in repository/usr and registry in pickup. Started ok, common and registry resolved, no NPE. Tried clean restart without registry in pickup. Common was still installed and started, no NPE. Tried clean restart without registry in pickup or common in repository/usr. Added common to repository/usr after start and then deployed registry in pickup. Both bundles installed and started, no NPE.
Targeting 3.0.2 and re-opening as a reminder to do the cherry-pick to backport to the 3.0.x branch.
Cherry picked in 3.0.2 as 3d49e34dbcc0afe9d20e3de22073ec82925d1f6d