Ok. So if the thread just ends up being parked and/or not executing any code that's in the bundle that was stopped for the rest of its life it's not going to cause a problem, although it is a leak and should obviously be avoided.
Thanks, Dan On Wed, Aug 15, 2012 at 2:54 PM, Richard S. Hall <[email protected]>wrote: > 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] > >

