[
https://issues.apache.org/jira/browse/FELIX-2128?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16731755#comment-16731755
]
Jaroslav Tulach commented on FELIX-2128:
----------------------------------------
Reference to this issue has appeared at [Apache NetBeans PR
1063|https://github.com/apache/incubator-netbeans/pull/1063].
> Permit class loading after framework shutdown
> ---------------------------------------------
>
> Key: FELIX-2128
> URL: https://issues.apache.org/jira/browse/FELIX-2128
> Project: Felix
> Issue Type: Improvement
> Components: Framework
> Affects Versions: framework-2.0.3
> Environment: Linux, JDK 6.
> Reporter: Jesse Glick
> Priority: Minor
> Attachments: FELIX-2128-diagnosis.diff, FELIX-2128-lazarus.diff
>
>
> In
> http://hg.netbeans.org/core-main/raw-file/default/core.netigso/test/unit/src/org/netbeans/core/osgi/ActivatorTest.java
> I have some unit tests which repeatedly launch Felix, start some bundles,
> shut down, and repeat. On occasion - more reproducibly if calls to
> System.gc() and System.runFinalization() are inserted into
> ActivatorTest.setUp - I get errors like these (though the test still passes):
> {noformat}
> ERROR: JarContent: Unable to read bytes. (java.lang.IllegalStateException:
> zip file closed)
> java.lang.IllegalStateException: zip file closed
> at java.util.zip.ZipFile.ensureOpen(ZipFile.java:403)
> at java.util.zip.ZipFile.getEntry(ZipFile.java:148)
> at java.util.jar.JarFile.getEntry(JarFile.java:206)
> at org.apache.felix.framework.util.JarFileX.getEntry(JarFileX.java:77)
> at
> org.apache.felix.framework.cache.JarContent.getEntryAsBytes(JarContent.java:120)
> at
> org.apache.felix.framework.ModuleImpl$ModuleClassLoader.findClass(ModuleImpl.java:1746)
> at
> org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:723)
> at
> org.apache.felix.framework.ModuleImpl.access$100(ModuleImpl.java:61)
> at
> org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1698)
> at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
> at java.lang.Class.getDeclaredMethods0(Native Method)
> at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
> at java.lang.Class.getMethod0(Class.java:2670)
> at java.lang.Class.getMethod(Class.java:1603)
> at
> org.openide.util.WeakListenerImpl$ListenerReference.getRemoveMethod(WeakListenerImpl.java:610)
> at
> org.openide.util.WeakListenerImpl$ListenerReference.run(WeakListenerImpl.java:563)
> at
> org.openide.util.lookup.implspi.ActiveQueue$Impl.run(ActiveQueue.java:73)
> at java.lang.Thread.run(Thread.java:619)
> Feb 23, 2010 3:22:53 PM org.openide.util.lookup.implspi.ActiveQueue$Impl run
> WARNING: null
> java.lang.NoClassDefFoundError: org/openide/loaders/FolderListListener
> at java.lang.Class.getDeclaredMethods0(Native Method)
> at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
> at java.lang.Class.getMethod0(Class.java:2670)
> at java.lang.Class.getMethod(Class.java:1603)
> at
> org.openide.util.WeakListenerImpl$ListenerReference.getRemoveMethod(WeakListenerImpl.java:610)
> at
> org.openide.util.WeakListenerImpl$ListenerReference.run(WeakListenerImpl.java:563)
> at
> org.openide.util.lookup.implspi.ActiveQueue$Impl.run(ActiveQueue.java:73)
> at java.lang.Thread.run(Thread.java:619)
> Caused by: java.lang.ClassNotFoundException:
> org.openide.loaders.FolderListListener
> at
> org.apache.felix.framework.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:779)
> at
> org.apache.felix.framework.ModuleImpl.access$100(ModuleImpl.java:61)
> at
> org.apache.felix.framework.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1698)
> at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
> ... 8 more
> {noformat}
> Here some code in a bundle has registered a special ReferenceQueue and is
> doing some minor cleanup of recently finalized objects. Unfortunately running
> this code block can trigger fresh class loading and JarContent throws an ISE
> when trying to load from the now-closed JAR file. The situation is less
> likely to come up in a real app than in a unit test but still possible - in
> case a bundle is dynamically unloaded, or some cleanup tasks happen to run
> during JVM shutdown.
> The timing of class loading is not easily predictable: it will occur any time
> a section of code is run for the first time. Even in the absence of apparent
> threads, it is very hard to guarantee that no class loading will take place
> after code ceases to be called externally, since overridden finalize()
> methods and JVM shutdown hooks can be called passively at any time. The code
> in this example could disable its RQ upon BundleActivator.stop if it were
> originally written for use inside OSGi, but it is not.
> I have come up with a patch to JarFileX which lets it load classes from
> nominally closed JARs on an emergency basis. (This was implemented years ago
> in the NetBeans module system.) To make it safer for the original JAR to be
> recreated or deleted, especially on Windows with its mandatory file locks, a
> temporary copy is made.
> (Safest would be to copy the original JAR eagerly in close(), but this would
> impose a huge performance penalty. Instead, the JAR is copied on demand only
> in cases where an ISE would otherwise be thrown. It is possible for the JAR
> to be modified/deleted after close() but before the next class load, in which
> case the ISE will still occur; similarly if a SecurityManager prevents the
> copying, etc.)
> It is not clear to me from the OSGi spec whether it is permissible for the
> bundle class loader to continue to function after framework shutdown (or
> generally after a bundle moves into an unresolved state). The spec seems to
> say that Bundle.loadClass should throw ISE, but this is different from
> performing implicit class loading at the VM's request as part of running
> already-loaded code. For what it's worth, 4.4.10 does say "all old exports
> must remain available for existing bundles and future resolves until the
> refreshPackages method is called or the Framework is restarted". While more
> permissive behavior is very useful for situations like these, if it
> contradicts the spec, I might suggest one or both of the following:
> 1. Enable emergency loading only with an optional Felix framework property.
> Then, for example, unit tests which knew they would be starting and stopping
> code which potentially left behind live threads or finalizer queues etc.
> could set the property to avoid printing such exceptions.
> 2. At least report when close() was called to assist the user in debugging
> the problem.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)