https://bz.apache.org/bugzilla/show_bug.cgi?id=57341

--- Comment #13 from Cristian <m3rcyhea...@icloud.com> ---
While performing a JUnitReport task, our build server started consistently
reporting Stack Overflow errors:

build.xml:773: The following error occurred while executing this line:
build.xml:923: java.lang.StackOverflowError
        at
com.sun.org.apache.xml.internal.serializer.ToStream.processDirty(ToStream.java:1571)
        at
com.sun.org.apache.xml.internal.serializer.ToStream.characters(ToStream.java:1489)
        at
com.sun.org.apache.xml.internal.serializer.ToHTMLStream.characters(ToHTMLStream.java:1529)
        at
com.sun.org.apache.xml.internal.serializer.ToStream.characters(ToStream.java:1614)
        at
com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.characters(AbstractTranslet.java:621)
        at junit_frames.br$dash$replace()
        at junit_frames.br$dash$replace()
        at junit_frames.br$dash$replace()
        ...
        at junit_frames.br$dash$replace()
        x1000

I tested locally and got a slightly different result:

build.xml:923: java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOfRange(Arrays.java:2694)
        at java.lang.String.<init>(String.java:203)
        at java.lang.String.substring(String.java:1877)
        at
com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary.substring_afterF(BasisLibrary.java:329)
        at junit_frames.br$dash$replace()
        at junit_frames.br$dash$replace()
        at junit_frames.br$dash$replace()
        ...
        at junit_frames.br$dash$replace()
        x1000

Monitoring the build on my workstation, Java Mission Control showed the memory
spiking to over 1.47GB before I got the out of memory error.

I had a look at the br-replace template in the $ANT_HOME/etc/junit-frames.xsl
and $ANT_HOME/etc/junit-noframes.xsl files and it is performing a recursive
replace of line returns one by one, so as soon as you perform a br-replace on a
file with more line returns than your stack limit, you're going to get this
error, unless you run out of memory first.

I managed to reimplement the br-replace template to be less stack/heap
intensive. After trying unsuccessfully to use the java
String.replace/replaceAll and StringUtils.replace functions that are used
elsewhere (which seem to have issues, possibly JVM dependent) I went for a
plain XSLT 1.0 implementation using a binary-subdivision approach that splits
the string approximately evenly on the nearest line break on large strings:

<xsl:template name="br-replace">
  <xsl:param name="word"/>
  <xsl:param name="splitlimit">32</xsl:param>
  <xsl:variable name="secondhalflen"
select="(string-length($word)+(string-length($word) mod 2)) div 2"/>
  <xsl:variable name="secondhalfword" select="substring($word,
$secondhalflen)"/>
  <!-- When word is very big, a recursive replace is very heap/stack expensive,
so subdivide on line break after middle of string -->
  <xsl:choose>
    <xsl:when test="(string-length($word) > $splitlimit) and
(contains($secondhalfword, '&#xa;'))">
      <xsl:variable name="secondhalfend"
select="substring-after($secondhalfword, '&#xa;')"/>
      <xsl:variable name="firsthalflen" select="string-length($word) -
$secondhalflen"/>
      <xsl:variable name="firsthalfword" select="substring($word, 1,
$firsthalflen)"/>
      <xsl:variable name="firsthalfend"
select="substring-before($secondhalfword, '&#xa;')"/>
      <xsl:call-template name="br-replace">
        <xsl:with-param name="word"
select="concat($firsthalfword,$firsthalfend)"/>
      </xsl:call-template>
      <br/>
      <xsl:call-template name="br-replace">
        <xsl:with-param name="word" select="$secondhalfend"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="contains($word, '&#xa;')">
      <xsl:value-of select="substring-before($word, '&#xa;')"/>
      <br/>
      <xsl:call-template name="br-replace">
        <xsl:with-param name="word" select="substring-after($word, '&#xa;')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
  <xsl:value-of select="$word"/>
    </xsl:otherwise>New Template name="MercyHearts">

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to