dirk.dittert
12/11/2024, 8:24 AMjava.util.stream.Stream.toList()Ljava/util/List;
java.lang.NoSuchMethodError: java.util.stream.Stream.toList()Ljava/util/List;
at io.kotest.matchers.paths.PathsKt$containFile$1.test(paths.kt:162)
at io.kotest.matchers.paths.PathsKt$containFile$1.test(paths.kt:160)
at io.kotest.matchers.ShouldKt.invokeMatcher(should.kt:38)
at io.kotest.matchers.ShouldKt.should(should.kt:33)
at io.kotest.matchers.paths.PathsKt.shouldContainFile(paths.kt:158)
at tfo.backup.walker.DirectoryWalkerMultipleFittingFilesTest$1$1$2.invokeSuspend(DirectoryWalkerMultipleFittingFilesTest.kt:52)
It is my understanding that this line fails:
val contents = Files.list(value).map { it.fileName.toString() }.toList()
However, Stream.toList()
is properly implemented by Kotlin to use a Collector.toList()
to work with older JDK (I am running a JDK 1.8)
And here comes the weird part: When I copy that line that fails (that I quoted above) to my unit test, it succeeds. This is very unexpected. Am I missing something obvious?Sam
12/11/2024, 8:36 AMStream.toList()
is implemented by Kotlin using a collector, which is true, but that extension function is still a different function from the member function that was added in JDK16. If the code you're calling was compiled against JDK16, it can still be referencing the member version that doesn't exist in your version of Java. It doesn't know the Kotlin extension version exists 😞Sam
12/11/2024, 8:38 AMSam
12/11/2024, 8:40 AMdirk.dittert
12/11/2024, 8:41 AMkotest-assertions-core-jvm-5.9.1.jar
is compiled on a newer version of the JDK that includes a Stream.toList()
method (not sure when that was added exactly) but the compiler was configured to produce class files compatible with JDK 1.8. That is, why I run into that NoSuchMethodError
.Sam
12/11/2024, 8:42 AMdirk.dittert
12/11/2024, 8:44 AMCollector
(if compiled on Java 8 ) or the newer Stream.toList()
if compiled on a newer Java version? This is something that must be addressed when kotest-assertions-core-jvm-5.9.1.jar
is compiled and is out of my hands?dirk.dittert
12/11/2024, 8:45 AMtoList()
call, this is what I see:
public fun <T> Stream<T>.toList(): List<T> = collect(Collectors.toList<T>())
which is in kotlin.streams.jdk8
and I guess the magic is that there essentially is a separate runtime jar for JDK 8.Sam
12/11/2024, 8:46 AMSam
12/11/2024, 8:53 AMkotlin.streams.toList()
function is always present at both compile time and runtime, as part of the Kotlin standard library. The problem occurs when the JDK16 version of the function is also present at compile time. In that case, the class is compiled with a reference to the JDK16 function. When it runs on JDK8, it is still referencing that non-existing JDK16 function, even though the working version is also available. The two functions have different FQNs, and the class will continue to point to the one it was compiled against, regardless of what actually exists at runtime.dirk.dittert
12/11/2024, 8:55 AMSam
12/11/2024, 8:59 AMdirk.dittert
12/11/2024, 9:01 AMSam
12/11/2024, 9:02 AMdirk.dittert
12/11/2024, 10:01 AMdirk.dittert
12/22/2024, 2:59 PM