首页 > 解决方案 > 序列化 TypeTag 时导致 ClassCastException 的原因是什么?

问题描述

情况

我正在序列化这个类的一个实现:

abstract class FnDescriptor[T <: FnRequest: TypeTag, R <: FnResponse: TypeTag] with Serializable {

  override type Input  = T
  override type Output = R
  override type State  = S

  val inputTag: TypeTag[Input]   = implicitly[TypeTag[T]]
  val outputTag: TypeTag[Output] = implicitly[TypeTag[R]]

}

并通过 REST 将其发送到网关,网关读取它以查找输入和输出状态的类型。(是的,我知道这不是一个很棒的设计)

结果

现在,如果我运行测试,同时启动网关和序列化 FnNamespace 的请求者,一切正常。

但是,如果我单独启动可执行文件,即可执行文件中的网关和另一个中的请求者,则会收到以下错误:

java.lang.ClassCastException:无法将 scala.reflect.api.SerializedTypeTag 的实例分配给 com.package.structure.FnDescriptor$ 实例中 scala.reflect.api.TypeTags$TypeTag 类型的字段 com.package.structure.FnDescriptor.inputTag $匿名$1

线索

我所做的研究表明,Serializer 使用 writeReplace 方法将 TypeTag 转换为 SerializedTypeTag。反序列化器应发生相应的 readResolve 以将 SerializedTypeTag 转换回 TypeTag,但它不会发生。相反,它会尝试将 SerializedTypeTag 分配给导致异常的 TypeTag。

它不会发生在单个 JVM 中的事实是我拥有的最好的线索,尽管我不知道如何解释它。

完整的堆栈跟踪

java.lang.ClassCastException: cannot assign instance of scala.reflect.api.SerializedTypeTag to field com.package.structure.FnDescriptor.inputTag of type scala.reflect.api.TypeTags$TypeTag in instance of com.package.structure.FnDescriptor$$anon$1
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2287)
    at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1417)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2293)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1975)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1567)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
    at com.package.structure.gateway.GatewayService$$anonfun$1$$anonfun$apply$2$$anonfun$apply$3$$anonfun$apply$4.apply(GatewayService.scala:76)

标签: javascalaserializationjvm

解决方案


推荐阅读