ArrayIndexOutOfBoundsException regression iterating children (original) (raw)

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:

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

Then execute the Jsoup element iterator benchmark:

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