Re: Namespace threading bug
"Eric Burke" <[email protected]>
| Newsgroups | gmane.comp.java.jdom.general |
|---|---|
| Message-ID | <[email protected]> |
Yes, that's exactly right. On Tue, Dec 16, 2008 at 5:07 PM, Joe Bowbeer <[email protected]> wrote: > This is different from the design decision that JDOM documents are not > threadsafe, right? Because one namespace cache is used by all documents? > > Does JDOM cache any other objects in this manner? > > By the way, in Java 5 a ConcurrentHashMap would be more efficient than a > synchronized HashMap. > > Joe > > > On Tue, Dec 16, 2008 at 1:12 PM, Eric Burke wrote: > >> Hi, >> >> Our application uses JDOM (along with ROME), and spawns several threads to >> download RSS feeds. We utilize ROME custom modules, which use JDOM Namespace >> support. Sometimes, perhaps 1 in 15 launches, the XML parsing never >> finishes. Instead, all 4 cores on my machine are 100% loaded as >> HashMap.get() loops infinitely. >> >> We tracked this down to the org.jdom.Namespace class. It has an >> "interesting" comment: >> >> // XXX We may need to make the namespaces HashMap synchronized with >> // reader/writer locks or perhaps make Namespace no longer a >> flyweight. >> // As written, multiple put() calls may happen from different threads >> // concurrently and cause a ConcurrentModificationException. See >> // >> http://lists.denveronline.net/lists/jdom-interest/2000-September/003009.html >> . >> // No one has ever reported this over the many years, so don't worry >> yet. >> >> Well, I'm reporting it. It does not cause ConcurrentModificationException, >> however. Instead, the map becomes corrupt and get() loops infinitely. Here >> is a stack trace from a thread dump taken using Sun's VisualVM: >> >> "SwingWorker-pool-4-thread-1" prio=6 tid=0x11d1c800 nid=0x5c8 runnable >> [0x1186f000..0x1186fc68] >> java.lang.Thread.State: RUNNABLE >> at java.util.HashMap.get(Unknown Source) >> at org.jdom.Namespace.getNamespace(Namespace.java:148) >> at org.jdom.Namespace.getNamespace(Namespace.java:202) >> at >> com.sun.syndication.io.impl.ModuleParsers.parseModules(ModuleParsers.java:49) >> at >> com.sun.syndication.io.impl.BaseWireFeedParser.parseFeedModules(BaseWireFeedParser.java:53) >> at >> com.sun.syndication.io.impl.Atom10Parser.parseFeed(Atom10Parser.java:177) >> at >> com.sun.syndication.io.impl.Atom10Parser.parse(Atom10Parser.java:75) >> at com.sun.syndication.io.WireFeedInput.build(WireFeedInput.java:252) >> at com.sun.syndication.io.SyndFeedInput.build(SyndFeedInput.java:161) >> at >> coop.nisc.newsreader.impl.rome.RomeFeedProvider.getFeedFromAtom(RomeFeedProvider.java:87) >> at coop.nisc.newsreader.impl.XmlIo.getEntriesFromXml(XmlIo.java:205) >> at >> coop.nisc.newsreader.impl.FileDataStore.loadFromDisk(FileDataStore.java:51) >> at >> coop.nisc.newsreader.impl.FileDataStore.getViewEntries(FileDataStore.java:41) >> - locked <0x0508ae58> (a coop.nisc.newsreader.impl.FileDataStore) >> at >> coop.nisc.newsreader.SubscriptionModel$GetInitialEntriesWorker.doInBackground(SubscriptionModel.java:331) >> at >> coop.nisc.newsreader.SubscriptionModel$GetInitialEntriesWorker.doInBackground(SubscriptionModel.java:326) >> at javax.swing.SwingWorker$1.call(Unknown Source) >> at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) >> at java.util.concurrent.FutureTask.run(Unknown Source) >> at javax.swing.SwingWorker.run(Unknown Source) >> at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown >> Source) >> at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) >> at java.lang.Thread.run(Unknown Source) >> >> The app hangs on that HashMap.get() forever, as it loops infinitely, >> consuming all CPU. >> >> The JDOM bug is that Namespace.java reads and writes to/from the HashMap >> class (private static HashMap namespaces;) without proper synchronization. >> Failure to synchronize on a HashMap is a well-known threading bug: >> >> http://lightbody.net/blog/2005/07/hashmapget_can_cause_an_infini.html >> >> >> I don't have a small test case (yet), but from a code review it looks as >> if synchronizing this method in Namespace.java will solve the issue: >> >> public static Namespace getNamespace(String prefix, String uri) { ... } >> > > > _______________________________________________ > To control your jdom-interest membership: > http://www.jdom.org/mailman/options/jdom-interest/[email protected] > -- Eric M. Burke http://www.linkedin.com/in/ericburke 314-494-3185 (mobile) 636-272-3298 (home) _______________________________________________ To control your jdom-interest membership: http://www.jdom.org/mailman/options/jdom-interest/[email protected]