XalanJ2
  1. XalanJ2
  2. XALANJ-2439

[PATCH] XSLTC resource leak causes 'No more DTM IDs are available' error

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: The Latest Development Code
    • Component/s: XSLTC
    • Labels:
      None
    • Environment:
      Linux and Windows XP with Sun JRE 1.5.0_15 and 1.6.0_05
    • Xalan info:
      PatchAvailable

      Description

      The Xalan XSLT compiler (XSLTC) has several resource leaks in handling
      result tree fragments in XSLT variables and parameters. If a variable
      or parameter declaration contains XML elements, a new DOM tree is created
      and a new internal integer id is reserved for it. The garbage collector can
      never retrieve this DOM tree, because the id registration holds a reference
      to it. This bug prevents the transformation of large input files, because
      complex templates creates many result tree fragments and exceeds often the
      absolute limit of possible DOM trees in XSLTC (2^16 = 65535). If this
      limit is reached, XSLTC throws the following exception:

      DTMException: No more DTM IDs are available

      The attached patch adds a new release method to the DOM interface and calls
      it, when the scope of a variable or parameter is leaved.

      You can test this patch with the attached JAR file. This file can be
      called with

      java -Xmx800M -jar DOMLeak-XSLT-Test-X.Y.jar

      This file contains four test style sheets with expected output files.

      This bug exists also in all Sun JRE 1.5 and 1.6 versions, because the
      Xalan XSLTC source code is used in the 'com.sun.org.apache.xalan.internal'
      packages. The attached test JAR file contains also a patch for the current
      Sun JRE version 1.6.0_5 and a fix JAR file to be installed into the
      '../jre/lib/endorsed' directory of the JRE installation.

      Please add the attached test files to the Xalan test suite. I have
      released them under Apache license version 2.0.

      Helge Schulz - http://OpenSHORE.org

      ----------
      Here is the output of running my test cases with several Java version:

      test:
      apply-with-all-versions:
      [apply] Buildfile: build.xml
      [apply] test-java:
      [apply] [echo] Test Sun Java 1.4.2_17 with integrated XSLT
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... Ok.
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... Ok.
      [apply] [echo]
      [apply] [echo] Test Sun Java 1.4.2_17 with latest Xalan (SVN revision 584164)
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [echo]
      [apply] [echo] Test Sun Java 1.4.2_17 with fixed Xalan
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... Ok.
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... Ok.
      [apply] BUILD SUCCESSFUL
      [apply] Total time: 1 minute 21 seconds
      [apply] Buildfile: build.xml
      [apply] test-java:
      [apply] [echo] Test Sun Java 1.5.0_15 with integrated XSLT
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [echo]
      [apply] [echo] Test Sun Java 1.5.0_15 with latest Xalan (SVN revision 584164)
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [echo]
      [apply] [echo] Test Sun Java 1.5.0_15 with fixed Xalan
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... Ok.
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... Ok.
      [apply] BUILD SUCCESSFUL
      [apply] Total time: 2 minutes 13 seconds
      [apply] Buildfile: build.xml
      [apply] test-java:
      [apply] [echo] Test Sun Java 1.6.0_05 with integrated XSLT
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: com.sun.org.apache.xml.internal.dtm.DTMException: No more DTM IDs are available
      [apply] [echo]
      [apply] [echo] Test Sun Java 1.6.0_05 with latest Xalan (SVN revision 584164)
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... ERROR: 'No more DTM IDs are available'
      [apply] [java] XSLT Exception: org.apache.xml.dtm.DTMException: No more DTM IDs are available
      [apply] [echo]
      [apply] [echo] Test Sun Java 1.6.0_05 with fixed Xalan
      [apply] [java] Testing DOMLeak-1-ResultTreeInVariable.xsl... Ok.
      [apply] [java] Testing DOMLeak-2-ResultTreeInCallParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-3-ResultTreeInApplyParameter.xsl... Ok.
      [apply] [java] Testing DOMLeak-4-NodeSetAndMultiDOM.xsl... Ok.
      [apply] BUILD SUCCESSFUL
      [apply] Total time: 1 minute 42 seconds
      BUILD SUCCESSFUL
      Total time: 5 minutes 22 seconds

      1. DOMLeak-4-NodeSetAndMultiDOM.xsl
        2 kB
        Helge Schulz
      2. DOMLeak-Xalan-SVN-r584164.patch
        13 kB
        Helge Schulz
      3. DOMLeak-XSLT-Test-1.0.jar
        19 kB
        Helge Schulz

        Activity

        Hide
        Helge Schulz added a comment -

        Here is my patch:

        Index: org/apache/xalan/xsltc/dom/SAXImpl.java
        ===================================================================
        — org/apache/xalan/xsltc/dom/SAXImpl.java (revision 640381)
        +++ org/apache/xalan/xsltc/dom/SAXImpl.java (working copy)
        @@ -1836,6 +1836,11 @@
        initSize, m_buildIdIndex);
        }
        }
        +
        + public void release()
        +

        { + _dtmManager.release(this, true); + }

        /**

        • %HZ% Need Javadoc
          Index: org/apache/xalan/xsltc/dom/DOMAdapter.java
          ===================================================================
            • org/apache/xalan/xsltc/dom/DOMAdapter.java (revision 640381)
              +++ org/apache/xalan/xsltc/dom/DOMAdapter.java (working copy)
              @@ -463,4 +463,9 @@
              public Hashtable getElementsWithIDs() { return _dom.getElementsWithIDs(); }

              +
              + public void release()

              { + _dom.release(); + }

              +
              }
              Index: org/apache/xalan/xsltc/dom/SimpleResultTreeImpl.java
              ===================================================================

            • org/apache/xalan/xsltc/dom/SimpleResultTreeImpl.java (revision 640381)
              +++ org/apache/xalan/xsltc/dom/SimpleResultTreeImpl.java (working copy)
              @@ -1015,4 +1015,13 @@
              public void migrateTo(DTMManager manager)
              {
              }
              +
              + public void release()
              +
              Unknown macro: {+ if (_documentID != 0) { + _dtmManager.release(this, true); + _documentID = 0; + }+ }

              +
              }
              Index: org/apache/xalan/xsltc/dom/AdaptiveResultTreeImpl.java
              ===================================================================

            • org/apache/xalan/xsltc/dom/AdaptiveResultTreeImpl.java (revision 640381)
              +++ org/apache/xalan/xsltc/dom/AdaptiveResultTreeImpl.java (working copy)
              @@ -1316,5 +1316,14 @@
              super.documentRelease();
              }
              }
              +
              + public void release()
              +
              Unknown macro: {+ if (_dom != null) { + _dom.release(); + _dom = null; + }+ super.release();+ }

        }
        Index: org/apache/xalan/xsltc/dom/MultiDOM.java
        ===================================================================
        — org/apache/xalan/xsltc/dom/MultiDOM.java (revision 640381)
        +++ org/apache/xalan/xsltc/dom/MultiDOM.java (working copy)
        @@ -280,6 +280,58 @@
        public int addDOMAdapter(DOMAdapter adapter)

        { return addDOMAdapter(adapter, true); }

        +
        + private boolean isMatchingAdapterEntry(DOM entry, DOMAdapter adapter)

        { + DOM dom = adapter.getDOMImpl(); + + return (entry == adapter) || ( + + /* + * Method addDOMAdapter overwrites for AdaptiveResultTreeImpl + * objects the usual entry with an adapter to the nested + * DOM, so we must check this here. See last 'if' statement + * of addDOMAdapter. + */ + + (dom instanceof AdaptiveResultTreeImpl) && + (entry instanceof DOMAdapter) && + (((AdaptiveResultTreeImpl) dom).getNestedDOM() + == ((DOMAdapter) entry).getDOMImpl()) + ); + }

        +
        + public void removeDOMAdapter(DOMAdapter adapter) {
        + _documents.remove(adapter.getDocumentURI(0));
        + DOM dom = adapter.getDOMImpl();
        +
        + if (dom instanceof DTMDefaultBase) {
        + SuballocatedIntVector ids = ((DTMDefaultBase) dom).getDTMIDs();
        + int idsSize = ids.size();
        + for (int i = 0; i < idsSize; i++)

        { + _adapters[ids.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS] = null; + }

        + } else {
        + int id = dom.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS;
        + if ((id > 0) &&
        + (id < _adapters.length) &&
        + isMatchingAdapterEntry(_adapters[id], adapter))

        { + _adapters[id] = null; + }

        else {
        + boolean found = false;
        +
        + for (int i = 0; i < _adapters.length; i++) {
        + if (isMatchingAdapterEntry(_adapters[id], adapter))

        { + _adapters[i] = null; + found = true; + }

        + }
        + if (!found)

        { + System.err.println("Warning: Memory leak in" + + " MultiDOM.removeDOMAdapter (adapter not found)."); + }

        + }
        + }
        + }

        private int addDOMAdapter(DOMAdapter adapter, boolean indexByURI) {
        // Add the DOM adapter to the array of DOMs
        @@ -662,4 +714,9 @@
        public Hashtable getElementsWithIDs()

        { return _main.getElementsWithIDs(); }

        +
        + public void release()

        { + _main.release(); + }

        +
        }
        Index: org/apache/xalan/xsltc/DOM.java
        ===================================================================
        — org/apache/xalan/xsltc/DOM.java (revision 640381)
        +++ org/apache/xalan/xsltc/DOM.java (working copy)
        @@ -102,4 +102,5 @@
        public int getDocument();
        public String getUnparsedEntityURI(String name);
        public Hashtable getElementsWithIDs();
        + public void release();
        }
        Index: org/apache/xalan/xsltc/compiler/WithParam.java
        ===================================================================
        — org/apache/xalan/xsltc/compiler/WithParam.java (revision 640381)
        +++ org/apache/xalan/xsltc/compiler/WithParam.java (working copy)
        @@ -22,9 +22,14 @@
        package org.apache.xalan.xsltc.compiler;

        import org.apache.bcel.generic.ConstantPoolGen;
        +import org.apache.bcel.generic.ALOAD;
        +import org.apache.bcel.generic.ASTORE;
        +import org.apache.bcel.generic.CHECKCAST;
        +import org.apache.bcel.generic.INVOKEINTERFACE;
        import org.apache.bcel.generic.INVOKEVIRTUAL;
        import org.apache.bcel.generic.InstructionList;
        import org.apache.bcel.generic.PUSH;
        +import org.apache.bcel.generic.LocalVariableGen;
        import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
        import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
        import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
        @@ -56,6 +61,12 @@

        • Parameter's default value.
          */
          private Expression _select;
          +
          + /**
          + * Reference to JVM variable with temporary result tree, which
          + * must be released after template call.
          + */
          + private LocalVariableGen _local;

        /**

        • %OPT% This is set to true when the WithParam is used in a CallTemplate
          @@ -155,7 +166,10 @@
        • a 'select' attribute, or in the with-param element's body
          */
          public void translateValue(ClassGenerator classGen,
        • MethodGenerator methodGen) {
          + MethodGenerator methodGen) {
          + final ConstantPoolGen cpg = classGen.getConstantPool();
          + final InstructionList il = methodGen.getInstructionList();
          +
          // Compile expression is 'select' attribute if present
          if (_select != null)
          Unknown macro: { _select.translate(classGen, methodGen);@@ -164,11 +178,16 @@ // If not, compile result tree from parameter body if present. else if (hasContents()) { compileResultTree(classGen, methodGen); + + // store result tree into local variable to release them later + + _local = methodGen.addLocalVariable2("@" + _escapedName, + Type.ResultTree.toJCType(), il.getEnd()); + il.append(DUP); + il.append(new ASTORE(_local.getIndex())); } // If neither are present then store empty string in parameter slot else { - final ConstantPoolGen cpg = classGen.getConstantPool(); - final InstructionList il = methodGen.getInstructionList(); il.append(new PUSH(cpg, Constants.EMPTYSTRING)); } }

          @@ -206,4 +225,30 @@
          ADD_PARAMETER_SIG)));
          il.append(POP); // cleanup stack
          }
          +
          + public void unmap(ClassGenerator classGen, MethodGenerator methodGen) {
          + if (_local != null)

          Unknown macro: {+ // System.out.println("WithParam.unmap}

          + }
          }
          Index: org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
          ===================================================================

            • org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java (revision 640381)
              +++ org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java (working copy)
              @@ -524,7 +524,7 @@
              for (int i = 0; i < n; i++)
              Unknown macro: { if( _contents.elementAt(i) instanceof VariableBase) { final VariableBase var = (VariableBase)_contents.elementAt(i); - var.unmapRegister(methodGen); + var.unmapRegister(classGen, methodGen); } }

              }
              Index: org/apache/xalan/xsltc/compiler/ApplyTemplates.java
              ===================================================================

            • org/apache/xalan/xsltc/compiler/ApplyTemplates.java (revision 640381)
              +++ org/apache/xalan/xsltc/compiler/ApplyTemplates.java (working copy)
              @@ -189,7 +189,17 @@
              _functionName,
              applyTemplatesSig);
              il.append(new INVOKEVIRTUAL(applyTemplates));
              +
              + // unmap parameters to release temporary result trees
              + final Enumeration childs = getContents().elements();

        + while (childs.hasMoreElements()) {
        + final Object child = childs.nextElement();
        + if (child instanceof WithParam)

        { + ((WithParam) child).unmap(classGen, methodGen); + }

        + }
        +
        // Pop parameter frame
        if (stylesheet.hasLocalParams() || hasContents()) {
        il.append(classGen.loadTranslet());
        Index: org/apache/xalan/xsltc/compiler/VariableBase.java
        ===================================================================
        — org/apache/xalan/xsltc/compiler/VariableBase.java (revision 640381)
        +++ org/apache/xalan/xsltc/compiler/VariableBase.java (working copy)
        @@ -26,7 +26,10 @@
        import org.apache.bcel.generic.ConstantPoolGen;
        import org.apache.bcel.generic.Instruction;
        import org.apache.bcel.generic.InstructionList;
        +import org.apache.bcel.generic.CHECKCAST;
        +import org.apache.bcel.generic.INVOKEINTERFACE;
        import org.apache.bcel.generic.INVOKESPECIAL;
        +import org.apache.bcel.generic.INVOKEVIRTUAL;
        import org.apache.bcel.generic.LocalVariableGen;
        import org.apache.bcel.generic.NEW;
        import org.apache.bcel.generic.PUSH;
        @@ -34,6 +37,7 @@
        import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
        import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
        import org.apache.xalan.xsltc.compiler.util.NodeSetType;
        +import org.apache.xalan.xsltc.compiler.util.ResultTreeType;
        import org.apache.xalan.xsltc.compiler.util.Type;
        import org.apache.xalan.xsltc.compiler.util.Util;
        import org.apache.xml.utils.XML11Char;
        @@ -96,12 +100,35 @@

        • Remove the mapping of this variable to a register.
        • Called when we leave the AST scope of the variable's declaration
          */
        • public void unmapRegister(MethodGenerator methodGen) {
        • if (_local != null) {
        • _local.setEnd(methodGen.getInstructionList().getEnd());
        • methodGen.removeLocalVariable(_local);
        • _refs = null;
        • _local = null;
          + public void unmapRegister(ClassGenerator classGen, MethodGenerator methodGen) {
          + if (_local != null) {
          + if (_type instanceof ResultTreeType)
          Unknown macro: { + final ConstantPoolGen cpg = classGen.getConstantPool();+ final InstructionList il = methodGen.getInstructionList();++ if (classGen.getStylesheet().callsNodeset() &&+ classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeCNI = cpg.addMethodref( + MULTI_DOM_CLASS, "removeDOMAdapter", + "(" + DOM_ADAPTER_SIG + ")V"); + + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(loadInstruction()); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeCNI)); + }+ final int releaseCNI = cpg.addInterfaceMethodref(+ DOM_IMPL_CLASS, "release", "()V");+ il.append(loadInstruction());+ il.append(new INVOKEINTERFACE(releaseCNI, 1));+ }

          + if (_refs.isEmpty())

          { + _local.setEnd(methodGen.getInstructionList().getEnd()); + methodGen.removeLocalVariable(_local); + _refs = null; + _local = null; + }

          }
          }

        Index: org/apache/xalan/xsltc/compiler/CallTemplate.java
        ===================================================================
        — org/apache/xalan/xsltc/compiler/CallTemplate.java (revision 640381)
        +++ org/apache/xalan/xsltc/compiler/CallTemplate.java (working copy)
        @@ -167,7 +167,15 @@
        il.append(new INVOKEVIRTUAL(cpg.addMethodref(className,
        methodName,
        methodSig.toString())));

        • +
          + // unmap parameters to release temporary result trees
          +
          + for (int i = 0; i < _parameters.length; i++)

          Unknown macro: {+ if(_parameters[i] instanceof WithParam) { + ((WithParam) _parameters[i]).unmap(classGen, methodGen); + }+ }

          +
          // Do not need to call Translet.popParamFrame() if we are
          // calling a simple named template.
          if (_calleeTemplate == null && (stylesheet.hasLocalParams() || hasContents())) {

        Show
        Helge Schulz added a comment - Here is my patch: Index: org/apache/xalan/xsltc/dom/SAXImpl.java =================================================================== — org/apache/xalan/xsltc/dom/SAXImpl.java (revision 640381) +++ org/apache/xalan/xsltc/dom/SAXImpl.java (working copy) @@ -1836,6 +1836,11 @@ initSize, m_buildIdIndex); } } + + public void release() + { + _dtmManager.release(this, true); + } /** %HZ% Need Javadoc Index: org/apache/xalan/xsltc/dom/DOMAdapter.java =================================================================== org/apache/xalan/xsltc/dom/DOMAdapter.java (revision 640381) +++ org/apache/xalan/xsltc/dom/DOMAdapter.java (working copy) @@ -463,4 +463,9 @@ public Hashtable getElementsWithIDs() { return _dom.getElementsWithIDs(); } + + public void release() { + _dom.release(); + } + } Index: org/apache/xalan/xsltc/dom/SimpleResultTreeImpl.java =================================================================== org/apache/xalan/xsltc/dom/SimpleResultTreeImpl.java (revision 640381) +++ org/apache/xalan/xsltc/dom/SimpleResultTreeImpl.java (working copy) @@ -1015,4 +1015,13 @@ public void migrateTo(DTMManager manager) { } + + public void release() + Unknown macro: {+ if (_documentID != 0) { + _dtmManager.release(this, true); + _documentID = 0; + }+ } + } Index: org/apache/xalan/xsltc/dom/AdaptiveResultTreeImpl.java =================================================================== org/apache/xalan/xsltc/dom/AdaptiveResultTreeImpl.java (revision 640381) +++ org/apache/xalan/xsltc/dom/AdaptiveResultTreeImpl.java (working copy) @@ -1316,5 +1316,14 @@ super.documentRelease(); } } + + public void release() + Unknown macro: {+ if (_dom != null) { + _dom.release(); + _dom = null; + }+ super.release();+ } } Index: org/apache/xalan/xsltc/dom/MultiDOM.java =================================================================== — org/apache/xalan/xsltc/dom/MultiDOM.java (revision 640381) +++ org/apache/xalan/xsltc/dom/MultiDOM.java (working copy) @@ -280,6 +280,58 @@ public int addDOMAdapter(DOMAdapter adapter) { return addDOMAdapter(adapter, true); } + + private boolean isMatchingAdapterEntry(DOM entry, DOMAdapter adapter) { + DOM dom = adapter.getDOMImpl(); + + return (entry == adapter) || ( + + /* + * Method addDOMAdapter overwrites for AdaptiveResultTreeImpl + * objects the usual entry with an adapter to the nested + * DOM, so we must check this here. See last 'if' statement + * of addDOMAdapter. + */ + + (dom instanceof AdaptiveResultTreeImpl) && + (entry instanceof DOMAdapter) && + (((AdaptiveResultTreeImpl) dom).getNestedDOM() + == ((DOMAdapter) entry).getDOMImpl()) + ); + } + + public void removeDOMAdapter(DOMAdapter adapter) { + _documents.remove(adapter.getDocumentURI(0)); + DOM dom = adapter.getDOMImpl(); + + if (dom instanceof DTMDefaultBase) { + SuballocatedIntVector ids = ((DTMDefaultBase) dom).getDTMIDs(); + int idsSize = ids.size(); + for (int i = 0; i < idsSize; i++) { + _adapters[ids.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS] = null; + } + } else { + int id = dom.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS; + if ((id > 0) && + (id < _adapters.length) && + isMatchingAdapterEntry(_adapters [id] , adapter)) { + _adapters[id] = null; + } else { + boolean found = false; + + for (int i = 0; i < _adapters.length; i++) { + if (isMatchingAdapterEntry(_adapters [id] , adapter)) { + _adapters[i] = null; + found = true; + } + } + if (!found) { + System.err.println("Warning: Memory leak in" + + " MultiDOM.removeDOMAdapter (adapter not found)."); + } + } + } + } private int addDOMAdapter(DOMAdapter adapter, boolean indexByURI) { // Add the DOM adapter to the array of DOMs @@ -662,4 +714,9 @@ public Hashtable getElementsWithIDs() { return _main.getElementsWithIDs(); } + + public void release() { + _main.release(); + } + } Index: org/apache/xalan/xsltc/DOM.java =================================================================== — org/apache/xalan/xsltc/DOM.java (revision 640381) +++ org/apache/xalan/xsltc/DOM.java (working copy) @@ -102,4 +102,5 @@ public int getDocument(); public String getUnparsedEntityURI(String name); public Hashtable getElementsWithIDs(); + public void release(); } Index: org/apache/xalan/xsltc/compiler/WithParam.java =================================================================== — org/apache/xalan/xsltc/compiler/WithParam.java (revision 640381) +++ org/apache/xalan/xsltc/compiler/WithParam.java (working copy) @@ -22,9 +22,14 @@ package org.apache.xalan.xsltc.compiler; import org.apache.bcel.generic.ConstantPoolGen; +import org.apache.bcel.generic.ALOAD; +import org.apache.bcel.generic.ASTORE; +import org.apache.bcel.generic.CHECKCAST; +import org.apache.bcel.generic.INVOKEINTERFACE; import org.apache.bcel.generic.INVOKEVIRTUAL; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.PUSH; +import org.apache.bcel.generic.LocalVariableGen; import org.apache.xalan.xsltc.compiler.util.ClassGenerator; import org.apache.xalan.xsltc.compiler.util.ErrorMsg; import org.apache.xalan.xsltc.compiler.util.MethodGenerator; @@ -56,6 +61,12 @@ Parameter's default value. */ private Expression _select; + + /** + * Reference to JVM variable with temporary result tree, which + * must be released after template call. + */ + private LocalVariableGen _local; /** %OPT% This is set to true when the WithParam is used in a CallTemplate @@ -155,7 +166,10 @@ a 'select' attribute, or in the with-param element's body */ public void translateValue(ClassGenerator classGen, MethodGenerator methodGen) { + MethodGenerator methodGen) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + // Compile expression is 'select' attribute if present if (_select != null) Unknown macro: { _select.translate(classGen, methodGen);@@ -164,11 +178,16 @@ // If not, compile result tree from parameter body if present. else if (hasContents()) { compileResultTree(classGen, methodGen); + + // store result tree into local variable to release them later + + _local = methodGen.addLocalVariable2("@" + _escapedName, + Type.ResultTree.toJCType(), il.getEnd()); + il.append(DUP); + il.append(new ASTORE(_local.getIndex())); } // If neither are present then store empty string in parameter slot else { - final ConstantPoolGen cpg = classGen.getConstantPool(); - final InstructionList il = methodGen.getInstructionList(); il.append(new PUSH(cpg, Constants.EMPTYSTRING)); } } @@ -206,4 +225,30 @@ ADD_PARAMETER_SIG))); il.append(POP); // cleanup stack } + + public void unmap(ClassGenerator classGen, MethodGenerator methodGen) { + if (_local != null) Unknown macro: {+ // System.out.println("WithParam.unmap} + } } Index: org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java =================================================================== org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java (revision 640381) +++ org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java (working copy) @@ -524,7 +524,7 @@ for (int i = 0; i < n; i++) Unknown macro: { if( _contents.elementAt(i) instanceof VariableBase) { final VariableBase var = (VariableBase)_contents.elementAt(i); - var.unmapRegister(methodGen); + var.unmapRegister(classGen, methodGen); } } } Index: org/apache/xalan/xsltc/compiler/ApplyTemplates.java =================================================================== org/apache/xalan/xsltc/compiler/ApplyTemplates.java (revision 640381) +++ org/apache/xalan/xsltc/compiler/ApplyTemplates.java (working copy) @@ -189,7 +189,17 @@ _functionName, applyTemplatesSig); il.append(new INVOKEVIRTUAL(applyTemplates)); + + // unmap parameters to release temporary result trees + final Enumeration childs = getContents().elements(); + while (childs.hasMoreElements()) { + final Object child = childs.nextElement(); + if (child instanceof WithParam) { + ((WithParam) child).unmap(classGen, methodGen); + } + } + // Pop parameter frame if (stylesheet.hasLocalParams() || hasContents()) { il.append(classGen.loadTranslet()); Index: org/apache/xalan/xsltc/compiler/VariableBase.java =================================================================== — org/apache/xalan/xsltc/compiler/VariableBase.java (revision 640381) +++ org/apache/xalan/xsltc/compiler/VariableBase.java (working copy) @@ -26,7 +26,10 @@ import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.Instruction; import org.apache.bcel.generic.InstructionList; +import org.apache.bcel.generic.CHECKCAST; +import org.apache.bcel.generic.INVOKEINTERFACE; import org.apache.bcel.generic.INVOKESPECIAL; +import org.apache.bcel.generic.INVOKEVIRTUAL; import org.apache.bcel.generic.LocalVariableGen; import org.apache.bcel.generic.NEW; import org.apache.bcel.generic.PUSH; @@ -34,6 +37,7 @@ import org.apache.xalan.xsltc.compiler.util.ErrorMsg; import org.apache.xalan.xsltc.compiler.util.MethodGenerator; import org.apache.xalan.xsltc.compiler.util.NodeSetType; +import org.apache.xalan.xsltc.compiler.util.ResultTreeType; import org.apache.xalan.xsltc.compiler.util.Type; import org.apache.xalan.xsltc.compiler.util.Util; import org.apache.xml.utils.XML11Char; @@ -96,12 +100,35 @@ Remove the mapping of this variable to a register. Called when we leave the AST scope of the variable's declaration */ public void unmapRegister(MethodGenerator methodGen) { if (_local != null) { _local.setEnd(methodGen.getInstructionList().getEnd()); methodGen.removeLocalVariable(_local); _refs = null; _local = null; + public void unmapRegister(ClassGenerator classGen, MethodGenerator methodGen) { + if (_local != null) { + if (_type instanceof ResultTreeType) Unknown macro: { + final ConstantPoolGen cpg = classGen.getConstantPool();+ final InstructionList il = methodGen.getInstructionList();++ if (classGen.getStylesheet().callsNodeset() &&+ classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeCNI = cpg.addMethodref( + MULTI_DOM_CLASS, "removeDOMAdapter", + "(" + DOM_ADAPTER_SIG + ")V"); + + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(loadInstruction()); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeCNI)); + }+ final int releaseCNI = cpg.addInterfaceMethodref(+ DOM_IMPL_CLASS, "release", "()V");+ il.append(loadInstruction());+ il.append(new INVOKEINTERFACE(releaseCNI, 1));+ } + if (_refs.isEmpty()) { + _local.setEnd(methodGen.getInstructionList().getEnd()); + methodGen.removeLocalVariable(_local); + _refs = null; + _local = null; + } } } Index: org/apache/xalan/xsltc/compiler/CallTemplate.java =================================================================== — org/apache/xalan/xsltc/compiler/CallTemplate.java (revision 640381) +++ org/apache/xalan/xsltc/compiler/CallTemplate.java (working copy) @@ -167,7 +167,15 @@ il.append(new INVOKEVIRTUAL(cpg.addMethodref(className, methodName, methodSig.toString()))); + + // unmap parameters to release temporary result trees + + for (int i = 0; i < _parameters.length; i++) Unknown macro: {+ if(_parameters[i] instanceof WithParam) { + ((WithParam) _parameters[i]).unmap(classGen, methodGen); + }+ } + // Do not need to call Translet.popParamFrame() if we are // calling a simple named template. if (_calleeTemplate == null && (stylesheet.hasLocalParams() || hasContents())) {
        Hide
        Helge Schulz added a comment -

        Attach patch as file DOMLeak-Xalan-SVN-r584164.patch.

        Show
        Helge Schulz added a comment - Attach patch as file DOMLeak-Xalan-SVN-r584164.patch.
        Hide
        Helge Schulz added a comment -

        Attach test JAR file DOMLeak-XSLT-Test-1.0.jar with test cases, test driver program, JRE 1.6.0_05 patch and fix.

        Show
        Helge Schulz added a comment - Attach test JAR file DOMLeak-XSLT-Test-1.0.jar with test cases, test driver program, JRE 1.6.0_05 patch and fix.
        Hide
        Helge Schulz added a comment -

        Attach test case style sheet 'DOMLeak-4-NodeSetAndMultiDOM.xsl' with maximum difficulty. All other test cases are inside the JAR file.

        Show
        Helge Schulz added a comment - Attach test case style sheet 'DOMLeak-4-NodeSetAndMultiDOM.xsl' with maximum difficulty. All other test cases are inside the JAR file.
        Hide
        Martin von Gagern added a comment -

        When do you release "temporary" result trees?
        Are you sure that there is no way a reference to such a temporary node may still be referenced somewhere at that time?
        Have you considered variables and parameters?
        Functions transforming nodesets into other nodesets?
        Could keys or some similar construct get a hand on such temporary nodes and store them longer than expected?
        Will generated nodes included in the output be available for all output formats, especially both SAX and DOM?

        I don't feel too well about the way this whole DTM stuff is implemented, and I can see the kind of problem you run into here. I'm a bit surprised that it should be possible to deal with this issue in the kind of patch you wrote, though, as opposed to a complete redesign. Haven't had a deeper look yet, and I'm not an official developer in any case, only collecting patches for my own uses, but it sounds too good to be true.

        Show
        Martin von Gagern added a comment - When do you release "temporary" result trees? Are you sure that there is no way a reference to such a temporary node may still be referenced somewhere at that time? Have you considered variables and parameters? Functions transforming nodesets into other nodesets? Could keys or some similar construct get a hand on such temporary nodes and store them longer than expected? Will generated nodes included in the output be available for all output formats, especially both SAX and DOM? I don't feel too well about the way this whole DTM stuff is implemented, and I can see the kind of problem you run into here. I'm a bit surprised that it should be possible to deal with this issue in the kind of patch you wrote, though, as opposed to a complete redesign. Haven't had a deeper look yet, and I'm not an official developer in any case, only collecting patches for my own uses, but it sounds too good to be true.
        Hide
        Helge Schulz added a comment -

        On 2009-07-28 Martin von Gagern wrote:
        >
        > When do you release "temporary" result trees?

        Temporary result trees in variables are released after leaving the enclosing element. That in parameters are released after a template call.

        > Are you sure that there is no way a reference to such a temporary node may still be referenced somewhere at that time?
        > Have you considered variables and parameters?
        > Functions transforming nodesets into other nodesets?
        > Could keys or some similar construct get a hand on such temporary nodes and store them longer than expected?
        > Will generated nodes included in the output be available for all output formats, especially both SAX and DOM?

        DOM nodes are always only in one document tree at a time. They must be always copied by method 'cloneNode', if they are copied into the result tree. So it is safe to release the temporary document trees.

        Helge Schulz - http://OpenSHORE.org

        Show
        Helge Schulz added a comment - On 2009-07-28 Martin von Gagern wrote: > > When do you release "temporary" result trees? Temporary result trees in variables are released after leaving the enclosing element. That in parameters are released after a template call. > Are you sure that there is no way a reference to such a temporary node may still be referenced somewhere at that time? > Have you considered variables and parameters? > Functions transforming nodesets into other nodesets? > Could keys or some similar construct get a hand on such temporary nodes and store them longer than expected? > Will generated nodes included in the output be available for all output formats, especially both SAX and DOM? DOM nodes are always only in one document tree at a time. They must be always copied by method 'cloneNode', if they are copied into the result tree. So it is safe to release the temporary document trees. Helge Schulz - http://OpenSHORE.org
        Hide
        Henry Zongaro added a comment -

        As with bug XALANJ-2438, it seems there is some code derived from Sun's reference implementation of JAXP in a jar file attached to this bug report: DOMLeak-XSLT-Test-1.0.jar. May I ask you to remove that code, since it's licensed under different terms than the Apache license? Because you've accessed Sun's reference implementation, I won't be able to review your patches, as they might contain code that's covered under Sun's copyright. As I am not an employee of Sun or Oracle, I don't have the authority to contribute Sun copyright code to the Apache project. Only an employee of Sun or Oracle who has signed an Apache CLA can contribute such code.

        Thanks for your understanding,
        Henry

        Show
        Henry Zongaro added a comment - As with bug XALANJ-2438 , it seems there is some code derived from Sun's reference implementation of JAXP in a jar file attached to this bug report: DOMLeak-XSLT-Test-1.0.jar. May I ask you to remove that code, since it's licensed under different terms than the Apache license? Because you've accessed Sun's reference implementation, I won't be able to review your patches, as they might contain code that's covered under Sun's copyright. As I am not an employee of Sun or Oracle, I don't have the authority to contribute Sun copyright code to the Apache project. Only an employee of Sun or Oracle who has signed an Apache CLA can contribute such code. Thanks for your understanding, Henry
        Hide
        Helge Schulz added a comment -

        As I tried to explain in a comment to XALANJ-2438 my file DOMLeak-XSLT-Test-1.0.jar contained only material licensed under Apache 2.0 license, because sources in package 'sun.com.org.apache.xalan.internal' are covered exclusively by this license. But I have removed all patches for classes in this package as Henry requested to resolve all doubts.

        Regards, Helge


        Helge Schulz - http://OpenSHORE.org

        Show
        Helge Schulz added a comment - As I tried to explain in a comment to XALANJ-2438 my file DOMLeak-XSLT-Test-1.0.jar contained only material licensed under Apache 2.0 license, because sources in package 'sun.com.org.apache.xalan.internal' are covered exclusively by this license. But I have removed all patches for classes in this package as Henry requested to resolve all doubts. Regards, Helge – Helge Schulz - http://OpenSHORE.org
        Hide
        Eric Schwarzenbach added a comment -

        I can tell you this patch does not fix all DTM "leaks".

        My own situation is of a template which makes many call-back to my system using a Java extension function which returns a DOM NodeList as a result. To simplify the scenario, it is more or less like the following: the document being transformed has a large number X elements. There is a template for element X in my XSLT that makes several such extension function calls, generating (as seen by debugging) a DTM for each of these; these are not released when the template is exited. I've applied this patch (manually) to the Xalan-J 2.7.1 release source, and it does not release the DTMs created in this way.

        FWIW, here is a stack trace from the DTMManagerDefault.addDTM call (I simply created a RuntimeException in the code and logged it with log4j as a convenient way to get this):

        org.apache.xml.dtm.ref.DTMManagerDefault : StackTrace for addDTM
        java.lang.RuntimeException: fake exception for stacktrace
        at org.apache.xml.dtm.ref.DTMManagerDefault.addDTM(DTMManagerDefault.java:167)
        at org.apache.xml.dtm.ref.DTMManagerDefault.getDTM(DTMManagerDefault.java:276)
        at org.apache.xml.dtm.ref.DTMManagerDefault.getDTMHandleFromNode(DTMManagerDefault.java:579)
        at org.apache.xpath.XPathContext.getDTMHandleFromNode(XPathContext.java:189)
        at org.apache.xpath.NodeSetDTM.<init>(NodeSetDTM.java:171)
        at org.apache.xpath.objects.XNodeSetForDOM.<init>(XNodeSetForDOM.java:70)
        at org.apache.xpath.objects.XObjectFactory.create(XObjectFactory.java:148)
        at org.apache.xpath.objects.XObject.create(XObject.java:180)
        at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:212)
        at org.apache.xpath.XPath.execute(XPath.java:337)
        at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:280)
        at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:248)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405)
        at org.apache.xalan.templates.ElemElement.constructNode(ElemElement.java:341)
        at org.apache.xalan.templates.ElemElement.execute(ElemElement.java:290)
        at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395)
        at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405)
        at org.apache.xalan.templates.ElemCopy.execute(ElemCopy.java:116)
        at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395)
        at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405)
        at org.apache.xalan.templates.ElemCopy.execute(ElemCopy.java:116)
        at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395)
        at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405)
        at org.apache.xalan.templates.ElemCopy.execute(ElemCopy.java:116)
        at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395)
        at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2458)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2328)
        at org.apache.xalan.lib.Redirect.write(Redirect.java:216)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.xalan.extensions.ExtensionHandlerJavaClass.processElement(ExtensionHandlerJavaClass.java:517)
        at org.apache.xalan.templates.ElemExtensionCall.execute(ElemExtensionCall.java:234)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405)
        at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128)
        at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405)
        at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2275)
        at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1361)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1278)
        at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1256)
        at com.wrycan.xms.publisher.transform.XSLTransformType.transform(XSLTransformType.java:92)

        I'd note that the code path here seems to be going through none of the classes modified by the patch.

        Show
        Eric Schwarzenbach added a comment - I can tell you this patch does not fix all DTM "leaks". My own situation is of a template which makes many call-back to my system using a Java extension function which returns a DOM NodeList as a result. To simplify the scenario, it is more or less like the following: the document being transformed has a large number X elements. There is a template for element X in my XSLT that makes several such extension function calls, generating (as seen by debugging) a DTM for each of these; these are not released when the template is exited. I've applied this patch (manually) to the Xalan-J 2.7.1 release source, and it does not release the DTMs created in this way. FWIW, here is a stack trace from the DTMManagerDefault.addDTM call (I simply created a RuntimeException in the code and logged it with log4j as a convenient way to get this): org.apache.xml.dtm.ref.DTMManagerDefault : StackTrace for addDTM java.lang.RuntimeException: fake exception for stacktrace at org.apache.xml.dtm.ref.DTMManagerDefault.addDTM(DTMManagerDefault.java:167) at org.apache.xml.dtm.ref.DTMManagerDefault.getDTM(DTMManagerDefault.java:276) at org.apache.xml.dtm.ref.DTMManagerDefault.getDTMHandleFromNode(DTMManagerDefault.java:579) at org.apache.xpath.XPathContext.getDTMHandleFromNode(XPathContext.java:189) at org.apache.xpath.NodeSetDTM.<init>(NodeSetDTM.java:171) at org.apache.xpath.objects.XNodeSetForDOM.<init>(XNodeSetForDOM.java:70) at org.apache.xpath.objects.XObjectFactory.create(XObjectFactory.java:148) at org.apache.xpath.objects.XObject.create(XObject.java:180) at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:212) at org.apache.xpath.XPath.execute(XPath.java:337) at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:280) at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:248) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405) at org.apache.xalan.templates.ElemElement.constructNode(ElemElement.java:341) at org.apache.xalan.templates.ElemElement.execute(ElemElement.java:290) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405) at org.apache.xalan.templates.ElemCopy.execute(ElemCopy.java:116) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405) at org.apache.xalan.templates.ElemCopy.execute(ElemCopy.java:116) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405) at org.apache.xalan.templates.ElemCopy.execute(ElemCopy.java:116) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2458) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2328) at org.apache.xalan.lib.Redirect.write(Redirect.java:216) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.xalan.extensions.ExtensionHandlerJavaClass.processElement(ExtensionHandlerJavaClass.java:517) at org.apache.xalan.templates.ElemExtensionCall.execute(ElemExtensionCall.java:234) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2405) at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2275) at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1361) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1278) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1256) at com.wrycan.xms.publisher.transform.XSLTransformType.transform(XSLTransformType.java:92) I'd note that the code path here seems to be going through none of the classes modified by the patch.

          People

          • Assignee:
            Unassigned
            Reporter:
            Helge Schulz
          • Votes:
            3 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:

              Time Tracking

              Estimated:
              Original Estimate - 4h
              4h
              Remaining:
              Remaining Estimate - 4h
              4h
              Logged:
              Time Spent - Not Specified
              Not Specified

                Development