Skip to content

Commit abb8afc

Browse files
authored
Fixed NoSuchMethodError when parsing a JSON stream on Java 8 (#2219)
Fixes #2218
1 parent 24c6028 commit abb8afc

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

formats/json/jvmMain/src/kotlinx/serialization/json/internal/CharsetReader.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,20 @@ internal class CharsetReader(
2020
.onMalformedInput(CodingErrorAction.REPLACE)
2121
.onUnmappableCharacter(CodingErrorAction.REPLACE)
2222
byteBuffer = ByteBuffer.wrap(ByteArrayPool8k.take())
23-
byteBuffer.flip() // Make empty
23+
// An explicit cast is needed here due to an API change in Java 9, see #2218.
24+
//
25+
// In Java 8 and earlier, the `flip` method was final in `Buffer`, and returned a `Buffer`.
26+
// In Java 9 and later, the method was opened, and `ByteFuffer` overrides it, returning a `ByteBuffer`.
27+
//
28+
// You could observe this by decompiling this call with `javap`:
29+
// Compiled with Java 8 it produces `INVOKEVIRTUAL java/nio/ByteBuffer.flip ()Ljava/nio/Buffer;`
30+
// Compiled with Java 9+ it produces `INVOKEVIRTUAL java/nio/ByteBuffer.flip ()Ljava/nio/ByteBuffer;`
31+
//
32+
// This causes a `NoSuchMethodError` when running a class, compiled with a newer Java version, on Java 8.
33+
//
34+
// To mitigate that, `--bootclasspath` / `--release` options were introduced in `javac`, but there are no
35+
// counterparts for these options in `kotlinc`, so an explicit cast is required.
36+
(byteBuffer as Buffer).flip() // Make empty
2437
}
2538

2639
@Suppress("NAME_SHADOWING")
@@ -92,7 +105,7 @@ internal class CharsetReader(
92105
if (bytesRead < 0) return bytesRead
93106
byteBuffer.position(position + bytesRead)
94107
} finally {
95-
byteBuffer.flip()
108+
(byteBuffer as Buffer).flip() // see the `init` block in this class for the reasoning behind the cast
96109
}
97110
return byteBuffer.remaining()
98111
}

0 commit comments

Comments
 (0)