mandrean opened a new issue, #3843: URL: https://github.com/apache/fory/issues/3843
### Search before asking - [x] I searched the [Apache Fory issues](https://github.com/apache/fory/issues) and found no report for this cross-version failure. ### Version - Writer: Fory Java `1.2.0` - Reader: Fory Java `1.3.0` - Java: Temurin JDK `21.0.5` - OS: macOS The same sequence succeeds when both writer and reader use Fory `1.2.0`. ### Component(s) Java ### Minimal reproduce step This repro uses one POJO with a field whose concrete type is a `HashMap` subclass. It depends only on `fory-core`. Use this `pom.xml`: ```xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>repro</groupId> <artifactId>fory-binary-compatibility-repro</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.release>17</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <fory.version>1.2.0</fory.version> </properties> <dependencies> <dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-core</artifactId> <version>${fory.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.6.1</version> <configuration> <mainClass>repro.ForyBinaryCompatibilityRepro</mainClass> </configuration> </plugin> </plugins> </build> </project> ``` #### 1. Define the model and runner Save as `src/main/java/repro/ForyBinaryCompatibilityRepro.java`: ```java package repro; import java.util.HashMap; import java.util.HexFormat; import org.apache.fory.Fory; import org.apache.fory.config.CompatibleMode; import org.apache.fory.config.Language; public final class ForyBinaryCompatibilityRepro { public static final class Document { public StringMap values; } public static final class StringMap extends HashMap<String, String> {} public static void main(String[] args) { Fory fory = Fory.builder() .requireClassRegistration(false) .withCompatibleMode(CompatibleMode.COMPATIBLE) .withLanguage(Language.JAVA) .build(); if ("write".equals(args[0])) { System.out.println(HexFormat.of().formatHex(fory.serialize(sample()))); return; } byte[] oldBytes = HexFormat.of().parseHex(args[1]); Document oldDocument = fory.deserialize(oldBytes, Document.class); System.out.println("read 1.2.0 payload: " + oldDocument.values.get("key")); byte[] currentBytes = fory.serialize(oldDocument); Document currentDocument = fory.deserialize(currentBytes, Document.class); System.out.println("next round trip: " + currentDocument.values.get("key")); } private static Document sample() { Document document = new Document(); document.values = new StringMap(); document.values.put("key", "value"); return document; } } ``` #### 2. Serialize with Fory 1.2.0 and dump the hex ```shell HEX=$(mvn -q \ -Dfory.version=1.2.0 \ -Dexec.args=write \ compile exec:java | tail -n 1) echo "$HEX" ``` The generated 163-byte payload is: ```text 00ff1e002d805bea79e05d1e300211c48f8b806df4ae8e3a143411c744e63c134050b44f1d891f1773a370a8c2366036540ba1240416151615ff20022460ad22af570245700011c48f8b807174ae8e3a143411c744e63c134050b44f1d891f1773b29c50d37580780101042460ad22af570245700011c48f8b807174ae8e3a143411c744e63c134050b44f1d891f1773b29c50d375807824010c6b65791476616c7565 ``` #### 3. Read the 1.2.0 payload with Fory 1.3.0 Use the same class and the hex from step 2: ```shell mvn -q \ -Dfory.version=1.3.0 \ -Dexec.args="read $HEX" \ compile exec:java ``` The old payload itself is read successfully. The immediately following round-trip on the same `Fory` instance then fails. #### 4. Observe the regression Fory `1.3.0` prints the successful old-payload read and then throws: ```text read 1.2.0 payload: value [ERROR] ... Failed to deserialize input: class repro.ForyBinaryCompatibilityRepro_StringMapForyCodecCompatible1_0 cannot be cast to class org.apache.fory.serializer.collection.MapLikeSerializer ``` As a control, run the same read sequence with Fory `1.2.0`: ```shell mvn -q \ -Dfory.version=1.2.0 \ -Dexec.args="read $HEX" \ compile exec:java ``` It succeeds: ```text read 1.2.0 payload: value next round trip: value ``` ### What did you expect to see? Fory `1.3.0` should continue to read compatible payloads written by Fory `1.2.0` without corrupting serializer metadata used by later operations on the same `Fory` instance. Expected output: ```text read 1.2.0 payload: value next round trip: value ``` ### What did you see instead? After Fory `1.3.0` reads the Fory `1.2.0` payload, the next valid round-trip fails with a `ClassCastException` from a generated reader: ```text org.apache.fory.exception.DeserializationException: Failed to deserialize input Caused by: java.lang.ClassCastException: class repro.ForyBinaryCompatibilityRepro_StringMapForyCodecCompatible1_0 cannot be cast to class org.apache.fory.serializer.collection.MapLikeSerializer ``` This is a binary-compatibility regression: the sequence passes entirely on Fory `1.2.0` but fails when the reader is upgraded to Fory `1.3.0`. ### Anything Else? The failure requires reusing the same `Fory` instance: 1. Fory `1.3.0` reads the compatible payload produced by Fory `1.2.0`. 2. The same instance serializes another instance of the same model. 3. Deserializing that new payload resolves `StringMap` with a bean-compatible serializer where the generated reader requires a `MapLikeSerializer`. ### Are you willing to submit a PR? - [ ] I'm willing to submit a PR! ### Independent verification I reran this exact reproduction locally: - Temurin JDK 21.0.5: Fory 1.2.0 succeeds; Fory 1.3.0 reads the old payload and then fails with the documented generated-codec-to- cast. - The Fory 1.2.0 writer produced the documented 163-byte payload exactly (SHA-256 ). - Temurin JDK 25.0.2 with : the same cast failure remains. This is distinct from #3788. Without , #3788 fails during Fory construction on JDK 25, before the payload is read. Enabling the required open removes that initialization failure but does not remove this map-like serializer failure. Original report and reproduction: https://github.com/mandrean/fory/issues/12 -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
