This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch karaf-4.4.x
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/karaf-4.4.x by this push:
     new 2a4911b1b8 Remove static ThreadLocal caching in XmlUtils to prevent 
ClassLoader leaks (#2532)
2a4911b1b8 is described below

commit 2a4911b1b89a4165e1d1c736d520770cd0293228
Author: JB Onofré <[email protected]>
AuthorDate: Wed Apr 15 17:42:22 2026 +0200

    Remove static ThreadLocal caching in XmlUtils to prevent ClassLoader leaks 
(#2532)
    
    The static ThreadLocal fields holding DocumentBuilderFactory, 
TransformerFactory
    and SAXParserFactory pin the ClassLoader of the XML provider bundle on 
long-lived
    Karaf worker threads. When that bundle is updated or refreshed, the old
    ClassLoader can never be GC'd, leading to zombie bundles and Metaspace 
growth.
    
    Create fresh factory instances per call instead of caching them. The public 
API
    is unchanged.
    
    Fixes #2278
---
 .../main/java/org/apache/karaf/util/XmlUtils.java  | 98 +++++++++-------------
 1 file changed, 39 insertions(+), 59 deletions(-)

diff --git a/util/src/main/java/org/apache/karaf/util/XmlUtils.java 
b/util/src/main/java/org/apache/karaf/util/XmlUtils.java
index 915dad5458..4c6acc006f 100644
--- a/util/src/main/java/org/apache/karaf/util/XmlUtils.java
+++ b/util/src/main/java/org/apache/karaf/util/XmlUtils.java
@@ -46,10 +46,6 @@ public class XmlUtils {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(XmlUtils.class);
 
-    private static final ThreadLocal<DocumentBuilderFactory> 
DOCUMENT_BUILDER_FACTORY = new ThreadLocal<>();
-    private static final ThreadLocal<TransformerFactory> TRANSFORMER_FACTORY = 
new ThreadLocal<>();
-    private static final ThreadLocal<SAXParserFactory> SAX_PARSER_FACTORY = 
new ThreadLocal<>();
-
     public static Document parse(String uri) throws TransformerException, 
IOException, SAXException, ParserConfigurationException {
         DocumentBuilder db = documentBuilder();
         try {
@@ -106,74 +102,58 @@ public class XmlUtils {
     }
 
     public static XMLReader xmlReader() throws ParserConfigurationException, 
SAXException {
-        SAXParserFactory spf = SAX_PARSER_FACTORY.get();
-        if (spf == null) {
-            spf = SAXParserFactory.newInstance();
-            spf.setNamespaceAware(true);
-            spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 
Boolean.TRUE);
-            
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, true);
-            
spf.setFeature("http://xml.org/sax/features/external-general-entities";, false);
-            
spf.setFeature("http://xml.org/sax/features/external-parameter-entities";, 
false);
-            
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
-            spf.setXIncludeAware(false);
-            SAX_PARSER_FACTORY.set(spf);
-        }
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        spf.setNamespaceAware(true);
+        spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+        spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, 
true);
+        
spf.setFeature("http://xml.org/sax/features/external-general-entities";, false);
+        
spf.setFeature("http://xml.org/sax/features/external-parameter-entities";, 
false);
+        
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
+        spf.setXIncludeAware(false);
         return spf.newSAXParser().getXMLReader();
     }
 
     public static DocumentBuilder documentBuilder() throws 
ParserConfigurationException {
-        DocumentBuilderFactory dbf = DOCUMENT_BUILDER_FACTORY.get();
-        if (dbf == null) {
-            dbf = DocumentBuilderFactory.newInstance();
-            dbf.setNamespaceAware(true);
-            dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 
Boolean.TRUE);
-            
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, true);
-            
dbf.setFeature("http://xml.org/sax/features/external-general-entities";, false);
-            
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities";, 
false);
-            
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
-            dbf.setXIncludeAware(false);
-            dbf.setExpandEntityReferences(false);
-            DOCUMENT_BUILDER_FACTORY.set(dbf);
-        }
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+        dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, 
true);
+        
dbf.setFeature("http://xml.org/sax/features/external-general-entities";, false);
+        
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities";, 
false);
+        
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
+        dbf.setXIncludeAware(false);
+        dbf.setExpandEntityReferences(false);
         return dbf.newDocumentBuilder();
     }
 
     public static Transformer transformer() throws 
TransformerConfigurationException {
-        TransformerFactory tf = TRANSFORMER_FACTORY.get();
-        if (tf == null) {
-            tf = TransformerFactory.newInstance();
-            tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 
Boolean.TRUE);
-            try {
-                tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
-            } catch (IllegalArgumentException e) {
-                LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_DTD);
-            }
-            try {
-                tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
-            } catch (IllegalArgumentException e) {
-                LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
-            }
-            TRANSFORMER_FACTORY.set(tf);
+        TransformerFactory tf = TransformerFactory.newInstance();
+        tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+        try {
+            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+        } catch (IllegalArgumentException e) {
+            LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_DTD);
+        }
+        try {
+            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
+        } catch (IllegalArgumentException e) {
+            LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
         }
         return tf.newTransformer();
     }
 
     private static Transformer transformer(Source xsltSource) throws 
TransformerConfigurationException {
-        TransformerFactory tf = TRANSFORMER_FACTORY.get();
-        if (tf == null) {
-            tf = TransformerFactory.newInstance();
-            tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 
Boolean.TRUE);
-            try {
-                tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
-            } catch (IllegalArgumentException e) {
-                LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_DTD);
-            }
-            try {
-                tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
-            } catch (IllegalArgumentException e) {
-                LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
-            }
-            TRANSFORMER_FACTORY.set(tf);
+        TransformerFactory tf = TransformerFactory.newInstance();
+        tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+        try {
+            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+        } catch (IllegalArgumentException e) {
+            LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_DTD);
+        }
+        try {
+            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
+        } catch (IllegalArgumentException e) {
+            LOGGER.warn("XSL transformer implementation doesn't support {} 
feature", XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
         }
         return tf.newTransformer(xsltSource);
     }

Reply via email to