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]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.