【发布时间】:2014-07-13 06:50:04
【问题描述】:
在我看来这是编译器或 JVM 中的错误,但也许有人有更好的解释。
以下代码按原样运行良好,但如果我取消注释第二个 runnable 初始化,直接使用“this”,它无法反序列化对象(in.readObject() 引发异常)。
public class TestClass implements Serializable {
String msg = "HEY!";
SerializableRunnable runnable;
public TestClass() {
TestClass self = this;
runnable = () -> self.say(); // uses a local copy of 'this'
// runnable = () -> this.say(); // uses 'this' directly
}
public void say() {
System.out.println(msg);
}
public static void main(String[] args) throws Exception {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(buffer)) {
out.writeObject(new TestClass());
}
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()))) {
TestClass s = (TestClass) in.readObject();
s.say();
}
}
}
interface SerializableRunnable extends Runnable, Serializable {
}
这是根本原因的堆栈跟踪:
java.lang.IllegalArgumentException: Invalid lambda deserialization
at j8test.TestClass.$deserializeLambda$(TestClass.java:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at java.lang.invoke.SerializedLambda.readResolve(SerializedLambda.java:230)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1104)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1810)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at j8test.TestClass.main(TestClass.java:30)
这是预期的行为吗?
【问题讨论】:
-
旁注:不需要额外的接口,直接写:
Runnable runnable = (Runnable & Serializable) () -> self.say(); -
我知道。我只是想澄清一下这个东西是可序列化的,而不是另一个“我如何序列化 lambdas”的问题。不够清楚,似乎:)
-
除了最明显的以外,我什么都试过了。问题发生在 Eclipse 中(其中对 java 8 的支持仍处于测试阶段),但不在 javac 中。因此,一个 JDT 错误。
-
为我工作(在 Eclipse 中)。您确定您运行的是最新版本吗?过去有 lambda 序列化的 bug,我自己向 Eclipse 团队提交了一些,但很快就修复了。
标签: java serialization lambda deserialization java-8