[jdom-interest] Namespace threading bug

Eric Burke burke.eric at gmail.com
Tue Dec 16 13:12:16 PST 2008


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) { ... }





-- 
Eric M. Burke
http://www.linkedin.com/in/ericburke
314-494-3185 (mobile)
636-272-3298 (home)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.jdom.org/pipermail/jdom-interest/attachments/20081216/60d95ce9/attachment.htm


More information about the jdom-interest mailing list