When javac creates the deserializeLambda method, the externalize method is
called on the class names needed. This is returned as a byte array, which is turned into a string by calling the String constructor. However, the bytes are encoded in the JVM's UTF encoding,which can result in the String constructor making a bad string if the platform default encoding has different byte values for characters.
Reproduce:
Create a class containing a lambda using a suitable non-ASCII mappable character.eg."ABCâ"
Create a test class that serializes ABCâ, compile using ASCII encoding
See attached TestSerial.java example.
javac -J-Dfile.encoding=ISO-8859-1 TestSerial.java
Run test:
java TestSerial
Exception in thread "main" java.io.InvalidObjectException: ReflectiveOperationException during deserialization
at java.base/java.lang.invoke.SerializedLambda.readResolve(SerializedLambda.java:241)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1250)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2202)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1700)
at java.base/java.io.ObjectInputStream.readObjectImpl(ObjectInputStream.java:517)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:455)
at TestSerial.reserialize(TestSerial.java:38)
at TestSerial.main(TestSerial.java:52)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/java.lang.invoke.SerializedLambda.readResolve(SerializedLambda.java:239)
... 11 more
Caused by: java.lang.IllegalArgumentException: Invalid lambda deserialization
at TestSerial$ABCâ.$deserializeLambda$(TestSerial.java:15)
... 16 more
called on the class names needed. This is returned as a byte array, which is turned into a string by calling the String constructor. However, the bytes are encoded in the JVM's UTF encoding,which can result in the String constructor making a bad string if the platform default encoding has different byte values for characters.
Reproduce:
Create a class containing a lambda using a suitable non-ASCII mappable character.eg."ABCâ"
Create a test class that serializes ABCâ, compile using ASCII encoding
See attached TestSerial.java example.
javac -J-Dfile.encoding=ISO-8859-1 TestSerial.java
Run test:
java TestSerial
Exception in thread "main" java.io.InvalidObjectException: ReflectiveOperationException during deserialization
at java.base/java.lang.invoke.SerializedLambda.readResolve(SerializedLambda.java:241)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1250)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2202)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1700)
at java.base/java.io.ObjectInputStream.readObjectImpl(ObjectInputStream.java:517)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:455)
at TestSerial.reserialize(TestSerial.java:38)
at TestSerial.main(TestSerial.java:52)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/java.lang.invoke.SerializedLambda.readResolve(SerializedLambda.java:239)
... 11 more
Caused by: java.lang.IllegalArgumentException: Invalid lambda deserialization
at TestSerial$ABCâ.$deserializeLambda$(TestSerial.java:15)
... 16 more
- relates to
-
JDK-8249079 LambdaFileEncodingSerialization.java failed "exitCode = 1 expected [true] but found [false]"
- Open