quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.68k stars 2.65k forks source link

Windows native: JLINE(JANSI), ForeignAPISupport, JDK 23+ #43777

Open Karm opened 2 days ago

Karm commented 2 days ago

Describe the bug

The library used to highlight and color terminal output on Windows, jline needs FFM. Hopefully, it doesn't do any upcalls...no idea why it should though.

Specifically, downcalls are supported on x64 Linux, Windows and MacOS, while upcalls are supported only on x64 Linux.

We need to take a look at how we handle the library in Quarkus and to make it work on Windows. This issue slipped CI, because the logic detects it is not running in a proper terminal and does not execute. You need a real terminal, like the vanilla cmd or https://cmder.app/ like I use to trigger it. Actually any terminal the JANSI (JLINE) can work with triggers the issue on Windows.

Expected behavior

It works.

Actual behavior

It crashes during build.

Workaround

Remove quarkus-junit5 from the project.

How to Reproduce?

C:\tmp
λ curl -O -J -L https://github.com/graalvm/mandrel/releases/download/mandrel-24.1.0.0-Final/mandrel-java23-windows-amd64-24.1.0.0-Final.zip
λ powershell -c "Expand-Archive -Path mandrel-java23-windows-amd64-24.1.0.0-Final.zip -DestinationPath . -Force
λ SET JAVA_HOME=C:\tmp\mandrel-java23-24.1.0.0-Final\
λ SET GRAALVM_HOME=%JAVA_HOME%
λ SET PATH=%JAVA_HOME%\bin;%PATH%

λ curl -O -J -L "https://code.quarkus.io/d?e=rest&cn=code.quarkus.io"
λ powershell -c "Expand-Archive -Path code-with-quarkus.zip -DestinationPath . -Force
λ cd code-with-quarkus\
C:\tmp\code-with-quarkus
λ vcvars64
λ mvnw package -Dnative

Log

Note that just simply adding the option doesn't help:

C:\tmp\code-with-quarkus
λ mvnw package -Dnative -Dquarkus.native.additional-build-args=-H:+ForeignAPISupport
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] C:\tmp\mandrel-java23-24.1.0.1-devadbc8bdf69d\bin\native-image.cmd -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dlogging.initial-configurator.min-level=500 -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=3 -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Duser.language=en -J-Duser.country=US -J-Dfile.encoding=UTF-8 --features=io.quarkus.runner.Feature,io.quarkus.runtime.graal.DisableLoggingFeature -J--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED -J--add-exports=java.security.jgss/sun.security.jgss=ALL-UNNAMED -J--add-opens=java.base/java.text=ALL-UNNAMED -J--add-opens=java.base/java.io=ALL-UNNAMED -J--add-opens=java.base/java.lang.invoke=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -H:+UnlockExperimentalVMOptions -H:BuildOutputJSONFile=code-with-quarkus-1.0.0-SNAPSHOT-runner-build-output-stats.json -H:-UnlockExperimentalVMOptions -H:+UnlockExperimentalVMOptions -H:+GenerateBuildArtifactsFile -H:-UnlockExperimentalVMOptions -H:+ForeignAPISupport -H:+UnlockExperimentalVMOptions -H:+AllowFoldMethods -H:-UnlockExperimentalVMOptions -J-Djava.awt.headless=true --no-fallback --link-at-build-time -H:+UnlockExperimentalVMOptions -H:+ReportExceptionStackTraces -H:-UnlockExperimentalVMOptions -H:-AddAllCharsets --enable-url-protocols=http --enable-monitoring=heapdump -H:+UnlockExperimentalVMOptions -H:-UseServiceLoaderFeature -H:-UnlockExperimentalVMOptions -J--add-exports=org.graalvm.nativeimage/org.graalvm.nativeimage.impl=ALL-UNNAMED --exclude-config io\.netty\.netty-codec /META-INF/native-image/io\.netty/netty-codec/generated/handlers/reflect-config\.json --exclude-config io\.netty\.netty-handler /META-INF/native-image/io\.netty/netty-handler/generated/handlers/reflect-config\.json code-with-quarkus-1.0.0-SNAPSHOT-runner -jar code-with-quarkus-1.0.0-SNAPSHOT-runner.jar
Warning: The option '-H:+ForeignAPISupport' is experimental and must be enabled via '-H:+UnlockExperimentalVMOptions' in the future.
Warning: Please re-evaluate whether any experimental option is required, and either remove or unlock it. The build output lists all active experimental options, including where they come from and possible alternatives. If you think an experimental option should be considered as stable, please file an issue.
Warning: Option 'DynamicProxyConfigurationResources' is deprecated and might be removed in a future release: This can be caused by a proxy-config.json file in your META-INF directory. Consider including proxy configuration in the reflection section of reachability-metadata.md instead.. Please refer to the GraalVM release notes.
========================================================================================================================
GraalVM Native Image: Generating 'code-with-quarkus-1.0.0-SNAPSHOT-runner' (executable)...
========================================================================================================================
For detailed information and explanations on the build output, visit:
https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/BuildOutput.md
------------------------------------------------------------------------------------------------------------------------
[1/8] Initializing...                                                                                   (21.2s @ 0.13GB)
 Java version: 23+37, vendor version: Mandrel-24.1.0.1-devadbc8bdf69d
 Graal compiler: optimization level: 2, target machine: x86-64-v3
 C compiler: cl.exe (microsoft, x64, 19.36.32535)
 Garbage collector: Serial GC (max heap size: 80% of RAM)
 3 user-specific feature(s):
 - com.oracle.svm.thirdparty.gson.GsonFeature
 - io.quarkus.runner.Feature: Auto-generated class by Quarkus from the existing extensions
 - io.quarkus.runtime.graal.DisableLoggingFeature: Disables INFO logging during the analysis phase
------------------------------------------------------------------------------------------------------------------------
 5 experimental option(s) unlocked:
 - '-H:+AllowFoldMethods' (origin(s): command line)
 - '-H:+ForeignAPISupport' (origin(s): command line)
 - '-H:BuildOutputJSONFile' (origin(s): command line)
 - '-H:-UseServiceLoaderFeature' (origin(s): command line)
 - '-H:+GenerateBuildArtifactsFile' (origin(s): command line)
------------------------------------------------------------------------------------------------------------------------
Build resources:
 - 11.05GB of memory (69.1% of 16.00GB system memory, determined at start)
 - 8 thread(s) (100.0% of 8 available processor(s), determined at start)
[2/8] Performing analysis...  []                                                                        (12.7s @ 0.60GB)
    5,445 reachable types   (72.0% of    7,567 total)
    6,345 reachable fields  (38.7% of   16,386 total)
   23,148 reachable methods (41.6% of   55,682 total)
    1,824 types,    18 fields, and   402 methods registered for reflection
        0 downcalls and 0 upcalls registered for foreign access
        4 native libraries: crypt32, ncrypt, psapi, winhttp

Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing jdk.internal.foreign.abi.DowncallStub/0x00000000ae02ac00.invoke(Unknown Source)
Parsing context:
   at jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetConsoleScreenBufferInfo(Kernel32.java:224)
   at jdk.internal.org.jline.terminal.impl.ffm.WindowsAnsiWriter.getConsoleInfo(WindowsAnsiWriter.java:95)
   at jdk.internal.org.jline.terminal.impl.ffm.WindowsAnsiWriter.processCursorDown(WindowsAnsiWriter.java:239)
   at jdk.internal.org.jline.utils.AnsiWriter.processEscapeCommand(AnsiWriter.java:269)
   at jdk.internal.org.jline.utils.AnsiWriter.write(AnsiWriter.java:134)
   at jdk.internal.org.jline.utils.AnsiWriter.write(AnsiWriter.java:781)
   at java.io.PrintWriter.implWrite(PrintWriter.java:621)
   at java.io.PrintWriter.write(PrintWriter.java:613)
   at java.io.PrintWriter.write(PrintWriter.java:635)
   at java.io.PrintWriter.print(PrintWriter.java:782)
   at java.io.PrintWriter.println(PrintWriter.java:1033)
   at java.lang.Throwable$WrappedPrintWriter.println(Throwable.java:829)
   at java.lang.Throwable.lockedPrintStackTrace(Throwable.java:712)
   at java.lang.Throwable.printStackTrace(Throwable.java:701)
   at java.lang.Throwable.printStackTrace(Throwable.java:688)
   at java.lang.Throwable.printStackTrace(Throwable.java:679)
   at org.slf4j.helpers.Util.report(Util.java:123)
   at org.slf4j.helpers.MessageFormatter.safeObjectAppend(MessageFormatter.java:294)
   at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:263)
   at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:225)
   at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:160)
   at io.netty.util.internal.logging.LocationAwareSlf4JLogger.warn(LocationAwareSlf4JLogger.java:195)
   at io.netty.util.internal.SystemPropertyUtil.getInt(SystemPropertyUtil.java:144)
   at io.netty.buffer.ByteBufUtil.<clinit>(ByteBufUtil.java:103)
   at static root method.(Unknown Source)

        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisError.parsingError(AnalysisError.java:165)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:184)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureFlowsGraphCreated(MethodTypeFlow.java:152)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.getOrCreateMethodFlowsGraphInfo(MethodTypeFlow.java:110)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultStaticInvokeTypeFlow.lambda$update$0(DefaultStaticInvokeTypeFlow.java:75)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.LightImmutableCollection.forEach(LightImmutableCollection.java:90)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultStaticInvokeTypeFlow.update(DefaultStaticInvokeTypeFlow.java:74)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis$1.run(PointsToAnalysis.java:575)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:166)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:152)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1726)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1717)
        at java.base/java.util.concurrent.ForkJoinTask$InterruptibleTask.exec(ForkJoinTask.java:1641)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:507)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1458)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2034)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:189)
Caused by: com.oracle.svm.core.util.VMError$HostedError: should not reach here: unexpected input could not be handled: linkToNative
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.shouldNotReachHereUnexpectedInput(VMError.java:97)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.substitute.PolymorphicSignatureWrapperMethod.buildGraph(PolymorphicSignatureWrapperMethod.java:170)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.substitute.SubstitutionMethod.buildGraph(SubstitutionMethod.java:122)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.buildGraph(AnalysisMethod.java:657)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.AnalysisParsedGraph.parseBytecode(AnalysisParsedGraph.java:108)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.parseGraph(AnalysisMethod.java:916)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsedHelper(AnalysisMethod.java:881)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsed(AnalysisMethod.java:864)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.lookupEncodedGraph(InlineBeforeAnalysisGraphDecoder.java:181)
        at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.doInline(PEGraphDecoder.java:1215)
        at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.tryInline(PEGraphDecoder.java:1198)
        at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.trySimplifyInvoke(PEGraphDecoder.java:1053)
        at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.handleInvokeWithCallTarget(PEGraphDecoder.java:1005)
        at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.handleInvoke(PEGraphDecoder.java:991)
        at jdk.graal.compiler/jdk.graal.compiler.nodes.GraphDecoder.processNextNode(GraphDecoder.java:926)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.processNextNode(InlineBeforeAnalysisGraphDecoder.java:269)
        at jdk.graal.compiler/jdk.graal.compiler.nodes.GraphDecoder.decode(GraphDecoder.java:654)
        at jdk.graal.compiler/jdk.graal.compiler.replacements.PEGraphDecoder.decode(PEGraphDecoder.java:895)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysis.decodeGraph(InlineBeforeAnalysis.java:73)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:200)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:652)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:167)
        ... 15 more

Output of uname -a or ver

Windows 2019

Output of java -version

23.0.0 23+37

Mandrel or GraalVM version (if different from Java)

OpenJDK 64-Bit Server VM Mandrel-24.1.0.0-Final (build 23+37, mixed mode)

Quarkus version or git rev

3.14.4, 3.15.0, 3.15.1

Build tool (ie. output of mvnw --version or gradlew --version)

mvnw

Additional information

No response

quarkus-bot[bot] commented 2 days ago

/cc @galderz (mandrel), @zakkak (mandrel,native-image)

Karm commented 1 day ago

Workaround is to remove dependency on quarkus-junit5 and tests as that brings in the readline/jansi...

Merely disabling tests like so is not enough:

C:\tmp\code-with-quarkus
λ mvnw clean package -Dnative -DskipTests -Dquarkus.profile=prod

and that is concerning on its own :(