vsch / flexmark-java

CommonMark/Markdown Java parser with source level AST. CommonMark 0.28, emulation of: pegdown, kramdown, markdown.pl, MultiMarkdown. With HTML to MD, MD to PDF, MD to DOCX conversion modules.
BSD 2-Clause "Simplified" License
2.26k stars 269 forks source link

Using flexmark in a native image causes an ArrayIndexOutOfBoundsException #577

Open palexdev opened 1 year ago

palexdev commented 1 year ago

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: 1) Execute the nativeBuild Gradle task 2) Execute the nativeRun Gradle task

just-sultanov commented 1 year ago

Hi there! Thanks for the flexmark-java library 👍

Are there any plans for compatibility with graalvm (native image)?

fbricon commented 10 months ago

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?

felixkrull-neuland commented 2 months ago

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;
    }
}