Yes, that&#39;s exactly right.<br><br><div class="gmail_quote">On Tue, Dec 16, 2008 at 5:07 PM, Joe Bowbeer <span dir="ltr">&lt;<a href="mailto:joe.bowbeer@gmail.com">joe.bowbeer@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
This is different from the design decision that JDOM documents are not threadsafe, right?&nbsp; Because one namespace cache is used by all documents?<br><br>Does JDOM cache any other objects in this manner?<br><br>By the way, in Java 5 a ConcurrentHashMap would be more efficient than a synchronized HashMap.<br>
<font color="#888888">
<br>Joe</font><div><div></div><div class="Wj3C7c"><br><br><div class="gmail_quote">On Tue, Dec 16, 2008 at 1:12 PM, Eric Burke <span dir="ltr"></span>wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Hi,<br><br>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.<br>



<br>We tracked this down to the org.jdom.Namespace class. It has an &quot;interesting&quot; comment:<br><br>&nbsp;&nbsp;&nbsp; // XXX We may need to make the namespaces HashMap synchronized with<br>&nbsp;&nbsp;&nbsp; // reader/writer locks or perhaps make Namespace no longer a flyweight.<br>



&nbsp;&nbsp;&nbsp; // As written, multiple put() calls may happen from different threads <br>&nbsp;&nbsp;&nbsp; // concurrently and cause a ConcurrentModificationException. See<br>&nbsp;&nbsp;&nbsp; // <a href="http://lists.denveronline.net/lists/jdom-interest/2000-September/003009.html" target="_blank">http://lists.denveronline.net/lists/jdom-interest/2000-September/003009.html</a>.<br>



&nbsp;&nbsp;&nbsp; // No one has ever reported this over the many years, so don&#39;t worry yet.<br><br>Well, I&#39;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&#39;s VisualVM:<br>



<br>&quot;SwingWorker-pool-4-thread-1&quot; prio=6 tid=0x11d1c800 nid=0x5c8 runnable [0x1186f000..0x1186fc68]<br>&nbsp;&nbsp; java.lang.Thread.State: RUNNABLE<br>&nbsp;&nbsp;&nbsp; at java.util.HashMap.get(Unknown Source)<br>&nbsp;&nbsp;&nbsp; at org.jdom.Namespace.getNamespace(Namespace.java:148)<br>



&nbsp;&nbsp;&nbsp; at org.jdom.Namespace.getNamespace(Namespace.java:202)<br>&nbsp;&nbsp;&nbsp; at com.sun.syndication.io.impl.ModuleParsers.parseModules(ModuleParsers.java:49)<br>&nbsp;&nbsp;&nbsp; at com.sun.syndication.io.impl.BaseWireFeedParser.parseFeedModules(BaseWireFeedParser.java:53)<br>



&nbsp;&nbsp;&nbsp; at com.sun.syndication.io.impl.Atom10Parser.parseFeed(Atom10Parser.java:177)<br>&nbsp;&nbsp;&nbsp; at com.sun.syndication.io.impl.Atom10Parser.parse(Atom10Parser.java:75)<br>&nbsp;&nbsp;&nbsp; at com.sun.syndication.io.WireFeedInput.build(WireFeedInput.java:252)<br>



&nbsp;&nbsp;&nbsp; at com.sun.syndication.io.SyndFeedInput.build(SyndFeedInput.java:161)<br>&nbsp;&nbsp;&nbsp; at coop.nisc.newsreader.impl.rome.RomeFeedProvider.getFeedFromAtom(RomeFeedProvider.java:87)<br>&nbsp;&nbsp;&nbsp; at coop.nisc.newsreader.impl.XmlIo.getEntriesFromXml(XmlIo.java:205)<br>



&nbsp;&nbsp;&nbsp; at coop.nisc.newsreader.impl.FileDataStore.loadFromDisk(FileDataStore.java:51)<br>&nbsp;&nbsp;&nbsp; at coop.nisc.newsreader.impl.FileDataStore.getViewEntries(FileDataStore.java:41)<br>&nbsp;&nbsp;&nbsp; - locked &lt;0x0508ae58&gt; (a coop.nisc.newsreader.impl.FileDataStore)<br>



&nbsp;&nbsp;&nbsp; at coop.nisc.newsreader.SubscriptionModel$GetInitialEntriesWorker.doInBackground(SubscriptionModel.java:331)<br>&nbsp;&nbsp;&nbsp; at coop.nisc.newsreader.SubscriptionModel$GetInitialEntriesWorker.doInBackground(SubscriptionModel.java:326)<br>



&nbsp;&nbsp;&nbsp; at javax.swing.SwingWorker$1.call(Unknown Source)<br>&nbsp;&nbsp;&nbsp; at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)<br>&nbsp;&nbsp;&nbsp; at java.util.concurrent.FutureTask.run(Unknown Source)<br>&nbsp;&nbsp;&nbsp; at javax.swing.SwingWorker.run(Unknown Source)<br>



&nbsp;&nbsp;&nbsp; at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)<br>&nbsp;&nbsp;&nbsp; at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)<br>&nbsp;&nbsp;&nbsp; at java.lang.Thread.run(Unknown Source)<br><br>The app hangs on that HashMap.get() forever, as it loops infinitely, consuming all CPU.<br>



<br>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:<br>



<br><a href="http://lightbody.net/blog/2005/07/hashmapget_can_cause_an_infini.html" target="_blank">http://lightbody.net/blog/2005/07/hashmapget_can_cause_an_infini.html</a><br><br><br>I don&#39;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:<br>



<br>public static Namespace getNamespace(String prefix, String uri) { ... }<br></blockquote></div><br>
</div></div><br>_______________________________________________<br>
To control your jdom-interest membership:<br>
<a href="http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com" target="_blank">http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com</a><br></blockquote></div><br><br clear="all"><br>
-- <br>Eric M. Burke<br><a href="http://www.linkedin.com/in/ericburke">http://www.linkedin.com/in/ericburke</a><br>314-494-3185 (mobile)<br>636-272-3298 (home)<br>