Skip to content

ArrayIndexOutOfBoundsException regression iterating children #2366

@carlosame

Description

@carlosame

I have a repository of benchmarks where some Java DOM implementations are compared (JDK DOM, DOM4J, CSS4J-DOM4J, CSS4J DOM and finally Jsoup). You can see the results here: https://css4j.github.io/dom-mark.html

Until 1.19.1 I could run the basic Jsoup element iterator benchmark that just counts children, but 1.20.1 and 1.21.1 both produce errors. This one is from 1.21.1:

$ java -Xmx3G -jar buildMaven/benchmarks.jar DOMIteratorSmallMark.markElementIteratorJsoup
# JMH version: 1.37
# VM version: JDK 21.0.7, OpenJDK 64-Bit Server VM, 21.0.7+6-LTS
# VM invoker: [...]\jdk-21.0.7.6-hotspot\bin\java.exe
# VM options: -Xmx3G
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 6 iterations, 10 s each
# Measurement: 16 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 4 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: io.sf.carte.mark.dom.DOMIteratorSmallMark.markElementIteratorJsoup

# Run progress: 0,00% complete, ETA 00:07:20
# Fork: 1 of 2
# Warmup Iteration   1: <failure>

java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
        at org.jsoup.nodes.Attributes.addObject(Attributes.java:147)
        at org.jsoup.nodes.Attributes.userData(Attributes.java:179)
        at org.jsoup.nodes.Element.cachedChildren(Element.java:407)
        at org.jsoup.nodes.Element.childElementsList(Element.java:394)
        at org.jsoup.nodes.Element.children(Element.java:385)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.markElementIteratorJsoup(DOMIteratorSmallMark.java:146)
        at io.sf.carte.mark.dom.jmh_generated.DOMIteratorSmallMark_markElementIteratorJsoup_jmhTest.markElementIteratorJsoup_Throughput(DOMIteratorSmallMark_markElementIteratorJsoup_jmhTest.java:80)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:527)
        at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:504)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)

java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
        at org.jsoup.nodes.Attributes.addObject(Attributes.java:147)
        at org.jsoup.nodes.Attributes.userData(Attributes.java:179)
        at org.jsoup.nodes.Element.cachedChildren(Element.java:407)
        at org.jsoup.nodes.Element.childElementsList(Element.java:394)
        at org.jsoup.nodes.Element.children(Element.java:385)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.iterateJsoupElements(DOMIteratorSmallMark.java:157)
        at io.sf.carte.mark.dom.DOMIteratorSmallMark.markElementIteratorJsoup(DOMIteratorSmallMark.java:146)
        at io.sf.carte.mark.dom.jmh_generated.DOMIteratorSmallMark_markElementIteratorJsoup_jmhTest.markElementIteratorJsoup_thrpt_jmhStub(DOMIteratorSmallMark_markElementIteratorJsoup_jmhTest.java:147)
        at io.sf.carte.mark.dom.jmh_generated.DOMIteratorSmallMark_markElementIteratorJsoup_jmhTest.markElementIteratorJsoup_Throughput(DOMIteratorSmallMark_markElementIteratorJsoup_jmhTest.java:86)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:527)
        at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:504)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)

The code is somewhat simple, just count children: https://github.com/css4j/benchmark/blob/f02fe560c5baba4730379e4a1c203f0d75e9066e/src/io/sf/carte/mark/dom/DOMIteratorSmallMark.java

How to reproduce

Clone the benchmark repository:

git clone https://github.com/css4j/benchmark.git

In the repository copy, produce the jar files in any of the supported ways, for example to build with Maven you would modify the pom.xml file to bump the Jsoup version to 1.21.1:

https://github.com/css4j/benchmark/blob/f02fe560c5baba4730379e4a1c203f0d75e9066e/pom.xml#L86-L90

then run

mvn

Then execute the Jsoup element iterator benchmark:

java -Xmx3G -jar buildMaven/benchmarks.jar DOMIteratorSmallMark.markElementIteratorJsoup

Metadata

Metadata

Assignees

No one assigned

    Labels

    fixedAn {bug|improvement} that has been {fixed|implemented}

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions