On Tue, May 14, 2013 at 2:16 PM, Dan Gravell <[email protected]> wrote: > Neil, > > Each bundle should be responsible for stopping any threads that it has >> started itself, and it should do this from its BundleActivator.stop() >> callback method (or if you have used DS, from the deactivate methods, >> etc). The management agent should not care about bundle threads -- >> that is an implementation detail that the agent should know nothing >> about. It should just call Bundle.stop(). >> > > Ok, so it's not safe to update() a stop()ped bundle which has threads still > running that it started itself? That means the update process would have to > occur in a separate JVM invocation.
"Safe" is relative ;-) As I tried to explain in my previous email, the old bundle's classes and classloader will probably be pinned in memory, so you will have a memory leak. Also possibly the resource clashes that I talked about (but you could also have these if you had another copy of the same JVM process running). >> With respect to when the thread has to stop, think about it the other >> way around... what if you never stop any threads? This would mean that >> objects allocated by the thread do not become candidates for garbage >> collection; therefore neither do the classes that define those >> objects; therefore, neither do the classloaders that loaded those >> classes. So you're going to create a lot of garbage on the heap, >> eventually resulting in OOME. Also, if a bundle's thread continues >> running after the bundle has been stopped/updated then you could get >> unexpected exceptions occurring in that thread; e.g. the bundle >> classloader might not allow any new classes to be loaded, and calls >> into OSGi using your BundleContext will probably throw >> IllegalStateException. Generally these exceptions are not harmful >> since you wanted the thread to die anyway, but they could cause >> confusion if written to a log. >> > > Just to be clear: you're preaching to the converted, I understand why the > threads should be stopped. The issue is that I am re-using other projects > that don't conform to these rules.... projects that were never written as > OSGi bundles. It's a bit like the class loading assumptions you see in > other projects... except arguably more subtle. > > For "teh google", what I commonly see are NullPointerExceptions (example): > > java.lang.NullPointerException > at > org.apache.felix.framework.BundleRevisionImpl.calculateContentPath(BundleRevisionImpl.java:410) > at > org.apache.felix.framework.BundleRevisionImpl.initializeContentPath(BundleRevisionImpl.java:347) > at > org.apache.felix.framework.BundleRevisionImpl.getContentPath(BundleRevisionImpl.java:333) > at > org.apache.felix.framework.BundleRevisionImpl.getResourceLocal(BundleRevisionImpl.java:472) > at > org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1432) > at > org.apache.felix.framework.BundleWiringImpl.getResourceByDelegation(BundleWiringImpl.java:1360) > at > org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.getResource(BundleWiringImpl.java:2256) > > Also in JNotify's case threads are started in the static initalizers and it > means the native code ends up calling incorrect listeners in the bundle, > meaning file notifications are missing. I believe Ferry Huberts wrote a > port for the Linux part of JNotify, but I also need to support OS X and > Windows. > > I also see various stack traces in static initalizers... ImageIO is a > particular favourite: > > 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) > > These are often threads started *after* an update, by *updated* bundles. > But conversations with Richard S Hall before suggested the underlying cause > of the problems were threads that were still running at update. > > Anyway, the point is I have devoted quite a lot of time to trying to iron > these kinks out and I'm not getting that far, so I want to go back to > something I think will work. > > Therefore from a pure Java/OSGi standpoint it doesn't really matter >> whether the threads stop before or after update, so long as they do >> eventually stop. However a bigger problem is likely to be the internal >> logic of the bundles... is it able to cope with two copies running >> simultaneously? For example if you access a resource such as file, can >> you cope with "somebody else" (actually, an old undead copy of >> yourself!) accessing the same resource at the same time? >> > > Thanks, what you wrote helps me understand the fundamental point. I and my > users are certainly seeing problems (some examples above) after the update, > and if the threads are the cause, and I can't expediently stop them > (expedience in terms of development time), that's why I'll go for the JVM > restart. > > Dan --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]

