felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dan Gravell <...@elstensoftware.com>
Subject Re: Giving up on in process update... suggestions for how to structure separate JVM update?
Date Tue, 14 May 2013 13:16:33 GMT
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.


> 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

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message