On Aug 15, 2012, at 05:02 , Dan Gravell <[email protected]> wrote:
> A quick follow up to this... > > What is to be done with classes that start threads in their static > initialisers? I've noticed some core Java API classes do this, for example > java.util.pref.FileSystemPreferences has a static Timer which is shutdown > in the shutdown hook but otherwise runs every second. There's no way of > shutting this timer downm (maybe some reflection magic but that's obviously > horrible). > I wouldn't think you'd need to worry about a core class (the JRE may start many shared threads), just make sure it isn't going to invoke any of your code after your bundle stops. Technically, leaving threads running isn't the issue here. The issue is that you've left threads running that are still trying to execute code from a bundle that has been stopped and/or refreshed. You just need to make sure that they stop trying to execute your bundle code. The fact that you leave a thread running becomes a second issue, since it creates a resource leak. Some libraries assume their lifecycle is the same as the JVM process, which is a bad assumption in an OSGi environment. -> richard > Dan > > On Thu, Aug 9, 2012 at 6:10 PM, Richard S. Hall <[email protected]>wrote: > >> Dan, >> >> I looked at your example and was able to recreate the issue. After >> debugging it a little bit, it seems to be a fairly standard issue when >> dealing with threads and OSGi: >> >> You must make sure that all threads created by a bundle have stopped >> executing by the time the bundle's activator stop() method has returned. >> >> This can be complicated if you are using libraries that use threads and >> don't give you a way to shut them all down. There is no way around this. >> The start() method signals a bundle that it is ok to use resources and the >> stop() method signals that the bundle must stop using all resources. >> >> The NPE results because some thread is still trying to load classes on a >> bundle wiring that has been discarded. >> >> -> richard >> >> p.s. Unrelated, I also noticed that your threads continually ask for the >> bliss keystore resource when I'm just sitting idle at the update screen. >> Not sure if that is intended or not. >> >> On Aug 9, 2012, at 10:48 , Richard S. Hall <[email protected]> wrote: >> >>> On Aug 9, 2012, at 10:44 , Dan Gravell <[email protected]> >> wrote: >>> >>>> I understand why you want it simplified but I don't think I can - part >> of >>>> the reason I think this is occurring is because it's a pretty complex >> beast >>>> with threads and bundles all over the place. >>>> >>>> I will send you some download instructions and instructions to run... >> what >>>> OS are you on? Is a plain folder structure in a ZIP easiest? >>> >>> Mac OS X. >>> >>> ZIP is fine. >>> >>> -> richard >>> >>>> >>>> Dan >>>> >>>> On Thu, Aug 9, 2012 at 2:58 PM, Richard S. Hall <[email protected] >>> wrote: >>>> >>>>> Perhaps you can give me some way to download it and recreate it…that's >>>>> probably the quickest way. Of course, try to simplify it if you can… >>>>> >>>>> -> richard >>>>> >>>>> On Aug 9, 2012, at 06:29 , Dan Gravell <[email protected]> >>>>> wrote: >>>>> >>>>>> Sorry: forgot to include my code... I am performing a refresh >>>>>> (see blockingRefreshBundles()). Before this code runs I am using OBR >> to >>>>>> resolve a set of requirements. I then perform the update via the >>>>> resolver. >>>>>> 'startedBundles' are the bundles that were started at the time the >> update >>>>>> runs: >>>>>> >>>>>> for (Bundle bundle : startedBundles) { >>>>>> try { >>>>>> if(!FelixObrUtils.isFragment(bundle)) >>>>>> sysBundle.getBundleContext().getBundle(bundle.getBundleId()).stop(); >>>>>> } catch (BundleException e) { >>>>>> LOG.error("Failed to stop " + bundle.getSymbolicName(), e); >>>>>> } >>>>>> } >>>>>> resolver.deploy(0); >>>>>> blockingRefreshBundles(null, sysBundle.getBundleContext()); >>>>>> for (Bundle bundle : startedBundles) { >>>>>> try { >>>>>> if(!FelixObrUtils.isFragment(bundle)) >>>>>> sysBundle.getBundleContext().getBundle(bundle.getBundleId()).start(); >>>>>> } catch (BundleException e) { >>>>>> LOG.error("Failed to restart " + bundle.getSymbolicName(), e); >>>>>> } >>>>>> } >>>>>> >>>>>> protected void blockingRefreshBundles(Collection<Bundle> >>>>> restartedBundles, >>>>>> final BundleContext bundleContext) { >>>>>> final FrameworkWiring frameworkWiring = >>>>>> bundleContext.getBundle(0).adapt(FrameworkWiring.class); >>>>>> if(null!=frameworkWiring) { >>>>>> final CountDownLatch latch = new CountDownLatch(1); >>>>>> frameworkWiring.refreshBundles(restartedBundles, new >> FrameworkListener() >>>>> { >>>>>> @Override >>>>>> public void frameworkEvent(FrameworkEvent arg0) { >>>>>> if(arg0.getType()==FrameworkEvent.PACKAGES_REFRESHED) >> latch.countDown(); >>>>>> } >>>>>> }); >>>>>> try { >>>>>> latch.await(); >>>>>> } catch (InterruptedException e) { >>>>>> LOG.error("Interrupted while waiting for packages to refresh. Will >>>>> continue >>>>>> anyway"); >>>>>> } >>>>>> } else { >>>>>> LOG.warn("Couldn't adapt system bundle to framework wiring so will not >>>>>> refresh bundles"); >>>>>> } >>>>>> } >>>>>> >>>>>> Just a thought - might there be a problem in re-using the old >> references >>>>> to >>>>>> 'startedBundles'? Following the update, should I refresh these >> instances? >>>>>> >>>>>> Dan >>>>>> >>>>>> On Thu, Aug 9, 2012 at 11:19 AM, Felix Meschberger < >> [email protected] >>>>>> wrote: >>>>>> >>>>>>> Hi >>>>>>> >>>>>>> I would assume you need to call PackageAdmin.refreshPackages() after >>>>>>> updating the bundles, such that all providers and consumers get to >> know >>>>> the >>>>>>> latest updates. >>>>>>> >>>>>>> If you just to Bundle.update the call to PackageAdmin.refreshPackages >>>>> must >>>>>>> also be done explicitly. If you are using installation tools such as >>>>> File >>>>>>> Install this call would be done automatically by the installation >> tool >>>>>>> along with updating the bundles. >>>>>>> >>>>>>> Regards >>>>>>> Felix >>>>>>> >>>>>>> Am 09.08.2012 um 11:59 schrieb Dan Gravell: >>>>>>> >>>>>>>> Hi all. I'm getting some NoClassDefFoundErrors and other >>>>>>> exceptions/errors >>>>>>>> after updating some bundles. The bundles work fine before. >> Restarting >>>>>>> Felix >>>>>>>> clears the problem (no more NCDFE) and the newly updating bundles >> work >>>>>>> fine >>>>>>>> once again. >>>>>>>> >>>>>>>> I'd like to be able to support updating while running, if possible. >>>>>>>> >>>>>>>> Here's a sample stacktrace: >>>>>>>> >>>>>>>> 2012-08-09 10:44:56,095 [ERROR] Error while executing >>>>>>>> AutomaticFixerCoverArtCommand (AggregatedPolic >>>>>>>> yCommand.java:65, thread policy pool 0) >>>>>>>> java.lang.ExceptionInInitializerError >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> com.elsten.bliss.music.policy.coverartpolicy.CoverArtUtils.dimensionsOf(CoverArtUtils.java >>>>>>>> :163) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> com.elsten.bliss.music.policy.coverartpolicy.CoverArtUtils.openImageDimension(CoverArtUtil >>>>>>>> s.java:187) >>>>>>>> [...] >>>>>>>> Caused by: java.lang.NullPointerException >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleRevisionImpl.getResourcesLocal(BundleRevisionImpl.java:510) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleWiringImpl.findResourcesByDelegation(BundleWiringImpl.java:1127) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleWiringImpl.getResourcesByDelegation(BundleWiringImpl.java:1037) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleWiringImpl$BundleClassLoaderJava5.getResources(BundleWiringImpl.java:1778) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader.getResources(OSGiWebappClassLoader.java:115) >>>>>>>> at >>>>>>>> java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:340) >>>>>>>> at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:432) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> javax.imageio.spi.IIORegistry.registerApplicationClasspathSpis(IIORegistry.java:206) >>>>>>>> at javax.imageio.spi.IIORegistry.<init>(IIORegistry.java:138) >>>>>>>> at >>>>>>>> >> javax.imageio.spi.IIORegistry.getDefaultInstance(IIORegistry.java:159) >>>>>>>> at javax.imageio.ImageIO.<clinit>(ImageIO.java:64) >>>>>>>> >>>>>>>> 2012-08-09 10:44:57,061 [ERROR] Error while executing >>>>>>>> AutomaticFixerCoverArtCommand (AggregatedPolicyCommand.java:65, >> thread >>>>>>>> policy pool 1) >>>>>>>> java.lang.NoClassDefFoundError: Could not initialize class >>>>>>>> javax.imageio.ImageIO >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> com.elsten.bliss.music.policy.coverartpolicy.CoverArtUtils.dimensionsOf(CoverArtUtils.java:163) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> com.elsten.bliss.music.policy.coverartpolicy.CoverArtUtils.openImageDimension(CoverArtUtils.java:187) >>>>>>>> [... no caused by trace here...] >>>>>>>> >>>>>>>> Immediately before that I get something I only see once I enable >> Felix >>>>>>>> debug logging: >>>>>>>> >>>>>>>> ERROR: Bundle com.elsten.bliss.ui [34] Unable to get module class >> path. >>>>>>>> (java.lang.NullPointerExcepti >>>>>>>> on) >>>>>>>> java.lang.NullPointerException >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleRevisionImpl.calculateContentPath(BundleRevisionImpl.java >>>>>>>> :410) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleRevisionImpl.initializeContentPath(BundleRevisionImpl.jav >>>>>>>> a:347) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleRevisionImpl.getContentPath(BundleRevisionImpl.java:333) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleRevisionImpl.getResourcesLocal(BundleRevisionImpl.java:49 >>>>>>>> 3) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleWiringImpl.findResourcesByDelegation(BundleWiringImpl.jav >>>>>>>> a:1127) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleWiringImpl.getResourcesByDelegation(BundleWiringImpl.java >>>>>>>> :1037) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.apache.felix.framework.BundleWiringImpl$BundleClassLoaderJava5.getResources(BundleWiri >>>>>>>> ngImpl.java:1778) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader.getResources(OSGiWebappC >>>>>>>> lassLoader.java:115) >>>>>>>> at >>>>>>>> java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:340) >>>>>>>> at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:432) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> javax.imageio.spi.IIORegistry.registerApplicationClasspathSpis(IIORegistry.java:206) >>>>>>>> at javax.imageio.spi.IIORegistry.<init>(IIORegistry.java:138) >>>>>>>> at >>>>>>>> >> javax.imageio.spi.IIORegistry.getDefaultInstance(IIORegistry.java:159) >>>>>>>> at javax.imageio.ImageIO.<clinit>(ImageIO.java:64) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> com.elsten.bliss.music.policy.coverartpolicy.CoverArtUtils.dimensionsOf(CoverArtUtils.java >>>>>>>> :163) >>>>>>>> at >>>>>>>> >>>>>>> >>>>> >> com.elsten.bliss.music.policy.coverartpolicy.CoverArtUtils.openImageDimension(CoverArtUtil >>>>>>>> s.java:187) >>>>>>>> >>>>>>>> There are many of these NCDFEs but only one of those NPEs in >>>>>>>> BundleRevisionImpl. Once those have been thrown, "all hell seems to >>>>> break >>>>>>>> loose" and I start getting NCDFEs for other classes including my >> own. >>>>>>> Does >>>>>>>> the original exception cause these downstream ones or are they >>>>> unrelated? >>>>>>>> >>>>>>>> During the update the Import-Package statements for javax.imageio.* >>>>>>> remain >>>>>>>> stable. >>>>>>>> >>>>>>>> Let me know if more contextual logs are useful. I can provide the >>>>> actual >>>>>>>> code that's running if it helps (it's large though). >>>>>>>> >>>>>>>> Dan >>>>>>> >>>>>>> >>>>>>> --------------------------------------------------------------------- >>>>>>> To unsubscribe, e-mail: [email protected] >>>>>>> For additional commands, e-mail: [email protected] >>>>>>> >>>>>>> >>>>> >>>>> >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: [email protected] >>>>> For additional commands, e-mail: [email protected] >>>>> >>>>> >>> >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [email protected] >> For additional commands, e-mail: [email protected] >> >> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]

