Besides your two possible solutions I see also a third way to solve this which also solves the problem what should happen if a node gets discarted while Userdata still persists:
3) use a WeakHashMap (http://java.sun.com/j2se/1.4.2/docs/api/java/util/WeakHashMap.html) instead of a HashMap for storing the userdata hash table inside DocumentImpl WeakHashMaps maintain only a weak reference to the key (i.e. the node) keeping it garbage collectable and thus will also free the user data if the node is garbage collected. Already on Monday I opened a jira issue also provided a patch for this, see https://issues.apache.org/jira/browse/XERCESJ-1298 Best regards, Ludger Bünger -- Dipl.-Inf. Ludger Bünger Product Development - - - - - - - - - - - - - - - - RealObjects GmbH Altenkesseler Str. 17/B4 66115 Saarbrücken, Germany Tel +49 (0)681 98579 0 Fax +49 (0)681 98579 29 http://www.realobjects.com [EMAIL PROTECTED] -----Ursprüngliche Nachricht----- Von: Christian Roth [mailto:[EMAIL PROTECTED] Gesendet: Donnerstag, 10. April 2008 12:55 An: Xerces-J Developers Betreff: setUserData() implementation possible source of memory leak Affects: Xerces-J 2.9.1 ** Summary ** Once a Node had attached a user data object, that Node object will never be eligible for garbage collection (even if removed from the tree) unless its parent Document is garbage collected. This happens even if the user data is removed from that Node as described in the documentation. ** Description of cause ** User data is stored on the Document object for all Nodes, not on the individual Nodes themselves. When user data is first attached to a Node, a new entry in the Hashtable is created with the Node object itself as key, and a secondary Hashtable as value, into which the user data KV- pairs are stored in. When user data is deleted, the respective KV pairs are removed from the secondary Hashtable as expected. However, even when the secondary Hashtable for a Node gets empty, its top-level Hashtable entry in the Document is not removed alongside. Since that entry's key still refers to the node, the latter cannot get garbage collected. The following pseudo code will leak Node n until the Document doc is discarded: { Node n = doc.createElement( "a" ); n.setUserData( "key", "value", null ); n.setUserData( "key", null, null ); } ** Possible remedies ** I can see two ways of solving the issue: 1) Do not use the node itself as the key in the primary Hashtable. 2) Discard a Node's entry in the primary Hashtable as soon as its secondary (key-) Hashtable gets empty. In my tests during tracking down this issue, I settled for solution 2). ** Suggested patch ** I'm therefore suggesting the following patch to org.apache.xerces.dom.CoreDocumentImpl.java, setUserData() (#2297): After removing a key from the Node's secondary Hashtable t, we check if it is now empty. If it is, no user data is attached to that Node any longer, and we remove its entry in the primary Hashtable 'userData', thereby removing the incoming reference to it for it to be eligible for garbage collection. Here's the complete function code with my suggested patch applied, bracketed by // -> added CR ... // <- --snip-- public Object setUserData(Node n, String key, Object data, UserDataHandler handler) { if (data == null) { if (userData != null) { Hashtable t = (Hashtable) userData.get(n); if (t != null) { Object o = t.remove(key); // -> added CR if( t.size() == 0 ) userData.remove( n ); // <- if (o != null) { UserDataRecord r = (UserDataRecord) o; return r.fData; } } } return null; } else { Hashtable t; if (userData == null) { userData = new Hashtable(); t = new Hashtable(); userData.put(n, t); } else { t = (Hashtable) userData.get(n); if (t == null) { t = new Hashtable(); userData.put(n, t); } } Object o = t.put(key, new UserDataRecord(data, handler)); if (o != null) { UserDataRecord r = (UserDataRecord) o; return r.fData; } return null; } } --snip-- Kind regards Christian Roth -- Christian Roth (CTO) * Phone: +49 (0)89 89 04 32 95 infinity-loop GmbH * Neideckstr. 25 * 81249 München * Germany HRB 136 783 (AG München) * Geschäftsführer: Dr. Stefan Hermann Web: http://www.infinity-loop.de --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
