Mantis Bugtracker
  

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0000951 [Resin] major always 02-20-06 01:51 03-08-06 09:43
Reporter mate View Status public  
Assigned To ferg
Priority normal Resolution fixed  
Status closed   Product Version 3.0.17
Summary 0000951: XSL uses wrong ClassLoader (-> memory leak)
Description Resin XSL uses the wrong classloader for XSL templates, so that Java methods called from XSL will reference an old version of classes if the application is reloaded. Please see attached classes for a demonstration of the problem.

This causes trouble for us since all our XSL:s use static methods for i18n. If we re-deploy a WAR all text will fallback to the default locale until we restart Resin.

This probably also explains why we have been seeing memory leaks when redeploying, and finally running out of PermGen memory if we do not restart Resin.
Additional Information Try the attached classes/application and then just touch the WAR and reload the page.
Attached Files

- Relationships

- Notes
(0000885)
mate
02-20-06 01:55

(Where do I attach files???)

-------------------------------------------------------------------------------
package resin3Test;

import org.jdom.transform.JDOMSource;
import org.jdom.transform.JDOMResult;
import org.jdom.Element;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamSource;
import java.io.IOException;
import java.io.StringReader;

/**
 * Created: 2006-feb-20 10:19:47
 *
 * @author Mattias Jiderhamn
 */
public class XslClassLoaderServlet extends HttpServlet {
  protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
      XslUtils.setString("bar");
      
      Element elem = new Element("manual");
      elem.addContent(new Element("getString").setText(XslUtils.getString()));
      elem.addContent(new Element("getClassIdentity").setText(XslUtils.getClassIdentity()));
      elem.addContent(new Element("getClassLoader").setText(XslUtils.getClassLoader()));
      
      TransformerFactory transformerFactory = TransformerFactory.newInstance();
      StreamSource streamSource = new StreamSource(new StringReader(
          "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" +
          "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" [^] " +
          " xmlns:resin3Test=\"resin3Test\">\n" +
          " <xsl:template match=\"/\">\n" +
          " <root>" +
          " <transformed> " +
          " <getString><xsl:value-of select=\"resin3Test:XslUtils.getString()\"/></getString>" +
          " <getClassIdentity><xsl:value-of select=\"resin3Test:XslUtils.getClassIdentity()\"/></getClassIdentity>" +
          " <getClassLoader><xsl:value-of select=\"resin3Test:XslUtils.getClassLoader()\"/></getClassLoader>" +
          " </transformed> " +
          " </root>\n" +
          " </xsl:template>\n" +
          "</xsl:stylesheet>"));

      Transformer transformer = transformerFactory.newTransformer(streamSource);
      JDOMSource source = new JDOMSource(new org.jdom.Document(new Element("foo")));
      JDOMResult result = new JDOMResult();
      transformer.transform(source, result);

      Document doc = result.getDocument();
      doc.getRootElement().addContent(elem); // Add manually generated output
      
      response.setContentType("text/xml");
      new XMLOutputter(Format.getPrettyFormat()).output(doc, response.getWriter());
    }
    catch(Exception ex) {
      throw new ServletException(ex);
    }
  }
}

-------------------------------------------------------------------------------

package resin3Test;

import java.util.WeakHashMap;
import java.util.Map;
import java.util.Collections;

/**
 * @author Mattias Jiderhamn
 */
public class XslUtils {
  
  private static Map cache = Collections.synchronizedMap(new WeakHashMap());
  
  public static void setString(String s) {
    cache.put(Thread.currentThread(), s);
  }
  
  public static String getString() {
    return "foo" + cache.get(Thread.currentThread());
  }
  
  public static String getClassIdentity() {
    return "XslUtils:" + System.identityHashCode(XslUtils.class);
  }

  public static String getClassLoader() {
    return "ClassLoader:" + XslUtils.class.getClassLoader();
  }
}
 
(0000886)
mate
02-20-06 02:04

One thing I forgot to mention: it doesn't matter if the XSL is "inlined" or if it is a separate .xsl file.

And switching to Xalan removes the problem.
 
(0000922)
ferg
03-08-06 09:43

xsl/0a00
 

- Issue History
Date Modified Username Field Change
02-20-06 01:51 mate New Issue
02-20-06 01:51 mate Issue Monitored: mate
02-20-06 01:55 mate Note Added: 0000885
02-20-06 02:04 mate Note Added: 0000886
03-08-06 09:43 ferg Note Added: 0000922
03-08-06 09:43 ferg Assigned To  => ferg
03-08-06 09:43 ferg Status new => closed
03-08-06 09:43 ferg Resolution open => fixed
03-08-06 09:43 ferg Fixed in Version  => 3.0.19


Mantis 1.0.0rc3[^]
Copyright © 2000 - 2005 Mantis Group
34 total queries executed.
28 unique queries executed.
Powered by Mantis Bugtracker