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]

Reply via email to