Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoSuchMethodError when parsing a JSON stream on Java 8 #2326

Closed
KosmX opened this issue Jun 9, 2023 · 1 comment
Closed

NoSuchMethodError when parsing a JSON stream on Java 8 #2326

KosmX opened this issue Jun 9, 2023 · 1 comment
Assignees

Comments

@KosmX
Copy link

KosmX commented Jun 9, 2023

Describe the bug
Similar issue just with a different method:
#2218

Java changed some function signatures on java 9, when building on java 9+ with targeting java 8, invalid bytecode is produced.
java 9+ function: ByteBuffer position(int newPosition)
java 8 function: Buffer position(int newPosition)

To Reproduce
Attach a code snippet or test data if possible.

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.encodeToStream
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream

@Serializable
data class Data(val name: String, val entry: Int = 0)

@OptIn(ExperimentalSerializationApi::class)
fun main() {
    val out = ByteArrayOutputStream()
    Json.encodeToStream(Data("meow?", entry = 42), out)
    val inputStream = ByteArrayInputStream(out.toByteArray())
    Json.decodeFromStream<Data>(inputStream).let { println(it) } //
}

will produce

Exception in thread "main" java.lang.NoSuchMethodError: java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer;
	at kotlinx.serialization.json.internal.CharsetReader.fillByteBuffer(CharsetReader.kt:106)
	at kotlinx.serialization.json.internal.CharsetReader.doRead(CharsetReader.kt:78)
	at kotlinx.serialization.json.internal.CharsetReader.read(CharsetReader.kt:64)
	at kotlinx.serialization.json.internal.JavaStreamSerialReader.read(JvmJsonStreams.kt:261)
	at kotlinx.serialization.json.internal.ReaderJsonLexer.preload(JsonLexer.kt:87)
	at kotlinx.serialization.json.internal.ReaderJsonLexer.<init>(JsonLexer.kt:47)
	at kotlinx.serialization.json.internal.ReaderJsonLexer.<init>(JsonLexer.kt:38)
	at kotlinx.serialization.json.internal.JsonStreamsKt.decodeByReader(JsonStreams.kt:36)
	at kotlinx.serialization.json.JvmStreamsKt.decodeFromStream(JvmStreams.kt:61)
	at SerialBugDemoKt.main(SerialBugDemo.kt:20)
	at SerialBugDemoKt.main(SerialBugDemo.kt)

Process finished with exit code 1

Expected behavior
Not crashing

Environment

  • Kotlin version: 1.8.21
  • Library version: 1.5.1
  • Kotlin platforms: JVM 1.8 , newer JVM version don't crash
  • Gradle version: 8.1.1
@shanshin shanshin self-assigned this Jun 9, 2023
@KosmX
Copy link
Author

KosmX commented Jun 9, 2023

Workaround:

fun InputStream.asString(): String = String(readBytes())
// and then 
Json.decodeFromString<DatabaseFiles>(it.asString())

shanshin added a commit that referenced this issue Jun 12, 2023
Fixes #2326

An explicit cast is needed here due to an API change in Java 9, see #2218.
In Java 8 and earlier, the `position(I)` method was final in `Buffer`, and returned a `Buffer`.
In Java 9 and later, the method was opened, and `ByteFuffer` overrides it, returning a `ByteBuffer`.
This causes a `NoSuchMethodError` when running a class, compiled with a newer Java version, on Java 8.
shanshin added a commit that referenced this issue Jun 12, 2023
Fixes #2326

In Java 8 and earlier, the `position(I)` method was final in `Buffer`, and returned a `Buffer`.
In Java 9 and later, the method was opened, and `ByteBuffer` overrides it, returning a `ByteBuffer`.
This causes a `NoSuchMethodError` when running a class, compiled with a newer Java version, on Java 8.

Adding `-Xjdk-release=1.8` parameter allows the compiler to generate bytecode compatible with JVM 1.8
shanshin added a commit that referenced this issue Jun 12, 2023
Fixes #2326

In Java 8 and earlier, the `position(I)` method was final in `Buffer`, and returned a `Buffer`.
In Java 9 and later, the method was opened, and `ByteBuffer` overrides it, returning a `ByteBuffer`.
This causes a `NoSuchMethodError` when running a class, compiled with a newer Java version, on Java 8.

Adding `-Xjdk-release=1.8` parameter allows the compiler to generate bytecode compatible with JVM 1.8
woainikk pushed a commit that referenced this issue Jun 20, 2023
Fixes #2326

An explicit cast is needed here due to an API change in Java 9, see #2218.
In Java 8 and earlier, the `position(I)` method was final in `Buffer`, and returned a `Buffer`.
In Java 9 and later, the method was opened, and `ByteBuffer` overrides it, returning a `ByteBuffer`.
This causes a `NoSuchMethodError` when running a class, compiled with a newer Java version, on Java 8.
JesusMcCloud pushed a commit to a-sit-plus/kotlinx.serialization that referenced this issue Jul 5, 2023
…2328)

Fixes Kotlin#2326

An explicit cast is needed here due to an API change in Java 9, see Kotlin#2218.
In Java 8 and earlier, the `position(I)` method was final in `Buffer`, and returned a `Buffer`.
In Java 9 and later, the method was opened, and `ByteBuffer` overrides it, returning a `ByteBuffer`.
This causes a `NoSuchMethodError` when running a class, compiled with a newer Java version, on Java 8.
JellyBrick added a commit to JellyBrick/kotlinx.serialization that referenced this issue Jul 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants