Using flexmark in a native image causes an ArrayIndexOutOfBoundsException
I'm trying to build an app with JavaFX and markdown-javafx-renderer (which uses flexmark) using GraalVM. I can successfully build the image but at runtime the app crashes with the following exception:
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:893)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at java.lang.Thread.run(Thread.java:833)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:704)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:202)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] Caused by: java.lang.ExceptionInInitializerError
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.util.sequence.builder.SequenceBuilder.<init>(SequenceBuilder.java:42)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.util.sequence.builder.SequenceBuilder.<init>(SequenceBuilder.java:35)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.util.sequence.builder.SequenceBuilder.emptyBuilder(SequenceBuilder.java:371)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.util.sequence.BasedSequenceImpl.getBuilder(BasedSequenceImpl.java:52)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.util.sequence.SegmentedSequence.create(SegmentedSequence.java:135)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.parser.LightInlineParserImpl.flushTextNode(LightInlineParserImpl.java:143)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.parser.internal.InlineParserImpl.parse(InlineParserImpl.java:173)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.parser.core.HeadingParser.parseInlines(HeadingParser.java:62)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.parser.internal.DocumentParser.processInlines(DocumentParser.java:750)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.parser.internal.DocumentParser.finalizeAndProcess(DocumentParser.java:1005)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.parser.internal.DocumentParser.parse(DocumentParser.java:312)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.parser.Parser.parse(Parser.java:388)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sandec.mdfx.impl.MDFXNodeHelper.<init>(MDFXNodeHelper.java:84)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sandec.mdfx.MarkdownView.updateContent(MarkdownView.java:33)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sandec.mdfx.MarkdownView.<init>(MarkdownView.java:22)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at io.github.palexdev.reproducer.view.View.buildRoot(View.java:26)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at io.github.palexdev.reproducer.view.View.init(View.java:36)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at io.github.palexdev.reproducer.Reproducer.start(Reproducer.java:13)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at java.security.AccessController.executePrivileged(AccessController.java:169)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at java.security.AccessController.doPrivileged(AccessController.java:399)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST_Runnable_run_16403f8d32adb631126daa893e5e80085c5d6325(JNIJavaCallWrappers.java:0)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.glass.ui.gtk.GtkApplication._runLoop(GtkApplication.java)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:316)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] ... 3 more
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.util.misc.BitFieldSet.intMask(BitFieldSet.java:304)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] at com.vladsch.flexmark.util.sequence.builder.ISegmentBuilder.<clinit>(ISegmentBuilder.java:19)
[Mon Jun 12 12:49:19 CEST 2023][INFO] [SUB] ... 31 more
To Reproduce
Here's the Reproducer project I'm using: Reproducer.zip
Steps to reproduce:
- Execute the
nativeBuildGradle task - Execute the
nativeRunGradle task
Hi there!
Thanks for the flexmark-java library 👍
Are there any plans for compatibility with graalvm (native image)?
I'm hitting a somewhat similar error in a binary built with GraalVM:
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
at com.vladsch.flexmark.util.misc.BitFieldSet.add(BitFieldSet.java:659)
at com.vladsch.flexmark.util.misc.BitFieldSet.of(BitFieldSet.java:1204)
at com.vladsch.flexmark.util.sequence.LineAppendable.<clinit>(LineAppendable.java:48)
I tried #578 and I confirm it fixes my issue. Any chance we can get a release with that fix any time soon?
Would be good to see this fixed. I was able to patch the change from https://github.com/vsch/flexmark-java/pull/578 into my image using GraalVM's substitution feature so I didn't have to use a rebuilt flexmark jar:
@TargetClass(value = BitFieldSet.class, innerClass = "UniverseLoader")
final class com_vladsch_flexmark_util_misc_BitFieldSet_UniverseLoader {
@Alias
static ConcurrentHashMap<Class, Enum[]> enumUniverseMap;
@Substitute
public static <E extends Enum<E>> Enum[] getUniverseSlow(Class<E> elementType) {
assert (elementType.isEnum());
Enum[] cachedUniverse = enumUniverseMap.get(elementType);
if (cachedUniverse != null) return cachedUniverse;
E[] constants = elementType.getEnumConstants();
int enums = constants.length;
if (enums > 0) {
cachedUniverse = new Enum[enums];
enums = 0;
for (E constant : constants) {
cachedUniverse[enums++] = constant;
}
} else {
cachedUniverse = new Enum<?>[0];
}
enumUniverseMap.put(elementType, cachedUniverse);
return cachedUniverse;
}
}