Creating a Terminal fails running with a TTY on Java 21
We're seeing exceptions at runtime initialising a Terminal in interactive mode, but only for JRE 20 and 21:
java.lang.ClassCastException: Cannot cast java.lang.Integer to java.lang.foreign.MemorySegment
at java.base/java.lang.Class.cast(Class.java:4067)
at java.base/java.lang.invoke.VarHandles.insertCoordinates(VarHandles.java:501)
at java.base/java.lang.invoke.MethodHandles.insertCoordinates(MethodHandles.java:8144)
at com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.varHandle(FfmLayouts.kt:133)
at com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt$shortField$$inlined$scalarField$default$1$1.invoke(FfmLayouts.kt:84)
at com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt$shortField$$inlined$scalarField$default$1$1.invoke(FfmLayouts.kt:81)
at com.github.ajalt.mordant.terminal.terminalinterface.ffm.StructAccessor$DefaultImpls.getValue(FfmLayouts.kt:117)
at com.github.ajalt.mordant.terminal.terminalinterface.ffm.MacosCLibrary$winsize.getValue(TerminalInterface.ffm.macos.kt:11)
at com.github.ajalt.mordant.terminal.terminalinterface.ffm.MacosCLibrary$winsize.getWs_col(TerminalInterface.ffm.macos.kt:22)
at com.github.ajalt.mordant.terminal.terminalinterface.ffm.TerminalInterfaceFfmMacos.getTerminalSize(TerminalInterface.ffm.macos.kt:89)
at com.github.ajalt.mordant.terminal.TerminalDetectionKt.detectSize(TerminalDetection.kt:217)
at com.github.ajalt.mordant.terminal.Terminal.<init>(Terminal.kt:81)
All works fine on Java 17-19, and on Java 22-25.
Tested on macOs and Ubuntu using Temurin JREs.
I'm trying to put together something in the GitHub Actions so that a build job emits the jar file(s) and a subsequent matrix build can run the detection sample against 17, 21 & 25 JREs (i.e. all the LTEs), if that would be valuable?
Yes, I'd appreciate that.
The error itself is odd; the ffm module that's causing that exception is only supported on JDK 22+, it should even be loaded on 21. Maybe we need to explicitly check for JDK 21 rather than rely on the NoClassDef error
I've found some more specific info.
We are running java --enable-native-access=ALL-UNNAMED in order to avoid getting this message on Java 24 & 25:
WARNING: A restricted method in java.lang.System has been called WARNING: java.lang.System::load has been called by v.I in an unnamed module (file:/Users/robert/dev/thirdparty/mordant/test/proguard/build/libs/main-r8.jar) WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module WARNING: Restricted methods will be blocked in a future release unless native access is enabled
However, on Java 20 & 21 this causes Terminal.<init>(Terminal.kt:81) to throw the exception.
If we omit this option Mordant works OK against all Java versions 17-25.
(Odd that it works OK with that option on Java 17, 18, & 19; perhaps that option does nothing on those.)
Not sure if that means this is something that needs fixing or not?