mordant icon indicating copy to clipboard operation
mordant copied to clipboard

R8 issue with JDK <22

Open TWiStErRob opened this issue 1 year ago • 1 comments

I'm using an R8 setup very similar to the test module here.

After updating Clikt to 5.0.0 I started getting an error like this (click to expand)
> Task :ghlint-cli:r8Jar
Error: Missing class java.lang.foreign.AddressLayout (referenced from: java.lang.foreign.AddressLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.POINTER and 6 other contexts)
Missing class java.lang.foreign.Arena (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 7 other contexts)
Missing class java.lang.foreign.FunctionDescriptor (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker$Option (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker (referenced from: java.lang.foreign.Linker com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.linker and 6 other contexts)
Missing class java.lang.foreign.MemoryLayout$PathElement (referenced from: long com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.byteOffset(java.lang.foreign.MemoryLayout, java.lang.String) and 1 other context)
Missing class java.lang.foreign.MemoryLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt$shortField$$inlined$scalarField$default$1.$layout and 46 other contexts)
Missing class java.lang.foreign.MemorySegment (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.LinuxCLibrary$winsize.segment and 61 other contexts)
Missing class java.lang.foreign.StructLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.StructLayout.getLayout())
Missing class java.lang.foreign.SymbolLookup (referenced from: java.lang.foreign.SymbolLookup com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.lookup and 6 other contexts)
Missing class java.lang.foreign.ValueLayout$OfByte (referenced from: java.lang.foreign.ValueLayout$OfByte com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.BYTE and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfChar (referenced from: java.lang.foreign.ValueLayout$OfChar com.github.ajalt.mordant.terminal.terminalinterface.ffm.WinLayouts.WCHAR and 1 other context)
Missing class java.lang.foreign.ValueLayout$OfInt (referenced from: java.lang.foreign.ValueLayout$OfInt com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.INT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout$OfLong (referenced from: java.lang.foreign.ValueLayout$OfLong com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.LONG and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfShort (referenced from: java.lang.foreign.ValueLayout$OfShort com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.SHORT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 2 other contexts)
Compilation failed
Exception in thread "main" java.lang.RuntimeException: com.android.tools.r8.CompilationFailedException: Compilation failed to complete
        at com.android.tools.r8.internal.to.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:131)
        at com.android.tools.r8.R8.main(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:5)
Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete
        at Version.fakeStackEntry(Version_8.5.35.java:0)
        at com.android.tools.r8.T.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:5)
        at com.android.tools.r8.internal.to.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:82)
        at com.android.tools.r8.internal.to.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:32)
        at com.android.tools.r8.internal.to.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:31)
        at com.android.tools.r8.internal.to.c(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1)
        at com.android.tools.r8.R8.b(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:35)
        at com.android.tools.r8.R8.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1548)
        at com.android.tools.r8.internal.to.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:118)
        ... 1 more
Caused by: com.android.tools.r8.internal.g: Missing class java.lang.foreign.AddressLayout (referenced from: java.lang.foreign.AddressLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.POINTER and 6 other contexts)
Missing class java.lang.foreign.Arena (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 7 other contexts)
Missing class java.lang.foreign.FunctionDescriptor (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker$Option (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker (referenced from: java.lang.foreign.Linker com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.linker and 6 other contexts)
Missing class java.lang.foreign.MemoryLayout$PathElement (referenced from: long com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.byteOffset(java.lang.foreign.MemoryLayout, java.lang.String) and 1 other context)
Missing class java.lang.foreign.MemoryLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt$shortField$$inlined$scalarField$default$1.$layout and 46 other contexts)
Missing class java.lang.foreign.MemorySegment (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.LinuxCLibrary$winsize.segment and 61 other contexts)
Missing class java.lang.foreign.StructLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.StructLayout.getLayout())
Missing class java.lang.foreign.SymbolLookup (referenced from: java.lang.foreign.SymbolLookup com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.lookup and 6 other contexts)
Missing class java.lang.foreign.ValueLayout$OfByte (referenced from: java.lang.foreign.ValueLayout$OfByte com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.BYTE and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfChar (referenced from: java.lang.foreign.ValueLayout$OfChar com.github.ajalt.mordant.terminal.terminalinterface.ffm.WinLayouts.WCHAR and 1 other context)
Missing class java.lang.foreign.ValueLayout$OfInt (referenced from: java.lang.foreign.ValueLayout$OfInt com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.INT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout$OfLong (referenced from: java.lang.foreign.ValueLayout$OfLong com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.LONG and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfShort (referenced from: java.lang.foreign.ValueLayout$OfShort com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.SHORT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 2 other contexts)
        at com.android.tools.r8.internal.x50.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:21)
        at com.android.tools.r8.internal.x50.error(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1)
        at com.android.tools.r8.shaking.M.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1962)
        at com.android.tools.r8.shaking.M.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1643)
        at com.android.tools.r8.R8.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1471)
        at com.android.tools.r8.R8.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:233)
        at com.android.tools.r8.R8.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1547)
        at com.android.tools.r8.internal.to.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:28)
        ... 5 more
        Suppressed: java.lang.RuntimeException: com.android.tools.r8.internal.g: Missing class java.lang.foreign.AddressLayout (referenced from: java.lang.foreign.AddressLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.POINTER and 6 other contexts)
Missing class java.lang.foreign.Arena (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 7 other contexts)
Missing class java.lang.foreign.FunctionDescriptor (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker$Option (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker (referenced from: java.lang.foreign.Linker com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.linker and 6 other contexts)
Missing class java.lang.foreign.MemoryLayout$PathElement (referenced from: long com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.byteOffset(java.lang.foreign.MemoryLayout, java.lang.String) and 1 other context)
Missing class java.lang.foreign.MemoryLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt$shortField$$inlined$scalarField$default$1.$layout and 46 other contexts)
Missing class java.lang.foreign.MemorySegment (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.LinuxCLibrary$winsize.segment and 61 other contexts)
Missing class java.lang.foreign.StructLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.StructLayout.getLayout())
Missing class java.lang.foreign.SymbolLookup (referenced from: java.lang.foreign.SymbolLookup com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.lookup and 6 other contexts)
Missing class java.lang.foreign.ValueLayout$OfByte (referenced from: java.lang.foreign.ValueLayout$OfByte com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.BYTE and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfChar (referenced from: java.lang.foreign.ValueLayout$OfChar com.github.ajalt.mordant.terminal.terminalinterface.ffm.WinLayouts.WCHAR and 1 other context)
Missing class java.lang.foreign.ValueLayout$OfInt (referenced from: java.lang.foreign.ValueLayout$OfInt com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.INT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout$OfLong (referenced from: java.lang.foreign.ValueLayout$OfLong com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.LONG and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfShort (referenced from: java.lang.foreign.ValueLayout$OfShort com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.SHORT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 2 other contexts)
                at com.android.tools.r8.internal.x50.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:29)
                at com.android.tools.r8.shaking.M.a(R8_8.5.35_9c55004e7c41a17b1ed47c4e1952cb6778b3dac6afb6afc113a2737c3cde13e0:1964)
                ... 10 more
        Caused by: [CIRCULAR REFERENCE: com.android.tools.r8.internal.g: Missing class java.lang.foreign.AddressLayout (referenced from: java.lang.foreign.AddressLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.POINTER and 6 other contexts)
Missing class java.lang.foreign.Arena (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 7 other contexts)
Missing class java.lang.foreign.FunctionDescriptor (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker$Option (referenced from: java.lang.invoke.MethodHandle com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.handle$lambda$3$lambda$2$lambda$0(com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder, java.lang.foreign.MemoryLayout, java.lang.foreign.MemoryLayout[], java.lang.foreign.MemorySegment))
Missing class java.lang.foreign.Linker (referenced from: java.lang.foreign.Linker com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.linker and 6 other contexts)
Missing class java.lang.foreign.MemoryLayout$PathElement (referenced from: long com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.byteOffset(java.lang.foreign.MemoryLayout, java.lang.String) and 1 other context)
Missing class java.lang.foreign.MemoryLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt$shortField$$inlined$scalarField$default$1.$layout and 46 other contexts)
Missing class java.lang.foreign.MemorySegment (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.LinuxCLibrary$winsize.segment and 61 other contexts)
Missing class java.lang.foreign.StructLayout (referenced from: java.lang.foreign.MemoryLayout com.github.ajalt.mordant.terminal.terminalinterface.ffm.StructLayout.getLayout())
Missing class java.lang.foreign.SymbolLookup (referenced from: java.lang.foreign.SymbolLookup com.github.ajalt.mordant.terminal.terminalinterface.ffm.MethodHandlesHolder.lookup and 6 other contexts)
Missing class java.lang.foreign.ValueLayout$OfByte (referenced from: java.lang.foreign.ValueLayout$OfByte com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.BYTE and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfChar (referenced from: java.lang.foreign.ValueLayout$OfChar com.github.ajalt.mordant.terminal.terminalinterface.ffm.WinLayouts.WCHAR and 1 other context)
Missing class java.lang.foreign.ValueLayout$OfInt (referenced from: java.lang.foreign.ValueLayout$OfInt com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.INT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout$OfLong (referenced from: java.lang.foreign.ValueLayout$OfLong com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.LONG and 2 other contexts)
Missing class java.lang.foreign.ValueLayout$OfShort (referenced from: java.lang.foreign.ValueLayout$OfShort com.github.ajalt.mordant.terminal.terminalinterface.ffm.Layouts.SHORT and 4 other contexts)
Missing class java.lang.foreign.ValueLayout (referenced from: java.lang.foreign.MemorySegment com.github.ajalt.mordant.terminal.terminalinterface.ffm.FfmLayoutsKt.allocateInt(java.lang.foreign.Arena) and 2 other contexts)]

This is because I'm running minification on JDK <22, which is a requirement because I do not want to enforce users of the minified CLI to run on JDK 22+. Mordant is targeting Java 8 bytecode, my project is targeting Java 11 bytecode. R8 reads and emits Java 11 bytecode, but it needs to know about these classes.

The classes are visible if

  • the Gradle build is running JDK 22+ AND the Gradle R8 task has no toolchain defined
  • the Gradle build is running on any supported JDK AND the Gradle R8 task has a toolchain defined for JDK 22+

Defining a toolchain is:

	javaLauncher = javaToolchains.launcherFor {
		languageVersion = JavaLanguageVersion.of(22)
		vendor = JvmVendorSpec.ADOPTIUM // Temurin
	}

Your project's CI and I guess your local env is using JDK 22, so your case falls into the first bullet point. My library/CLI app uses the second approach (I was running on JDK 21 (LTS) and JDK 11 toolchain to represent the lowest-supported user).

I'm opening this issue to share my findings, and maybe trigger you into changing the testing approach or finding a way to make the second bullet point work. A 3rd party dependency of a project shouldn't dictate what JDKs another build is required to be using.

An alternative workaround to "solve" the R8 issue is to keep using lower JDKs, but also

	api(libs.clikt) {
                // See https://github.com/ajalt/mordant/issues/233
		// https://github.com/ajalt/mordant/releases/tag/3.0.0
		// > Added new terminal implementation that uses the Foreign Function and Memory (FFM) API added in JDK 22.
		exclude(group: "com.github.ajalt.mordant", "module": "mordant-jvm-ffm")
		exclude(group: "com.github.ajalt.mordant", "module": "mordant-jvm-ffm-jvm")
	}

which I don't know what effect it has.

TWiStErRob avatar Sep 29 '24 10:09 TWiStErRob

I'm not totally clear on what change you're asking for here. The FFM module uses APIs introduced in JDK 22, so it has to compile with that version.


Your workaround is valid, although you might prefer the simpler method of specifying just the modules you need rather than depending on the whole mordant package and excluding parts of it:

implementation("com.github.ajalt.mordant:mordant-core:$mordantVersion")
implementation("com.github.ajalt.mordant:mordant-jvm-jna:$mordantVersion")

ajalt avatar Sep 29 '24 16:09 ajalt