Cordaでシリアル化の問題が発生しました。私の新しいコードパスには、まだシリアル化/逆シリアル化されていない新しいクラスは含まれていませんが、次の例外を除いて爆発します。スタックトレースにCorDapp固有のクラスが含まれていないため、問題が何であるかを理解するのが非常に難しいことに注意してください。
この種の例外の根本的な原因が何であるかを調査し始める方法に関するヒント/ヒントはありますか?
ありがとう:-)
com.esotericsoftware.kryo.KryoException: java.lang.UnsupportedOperationException
Serialization trace:
dataObject (co.paralleluniverse.fibers.Stack)
stack (net.corda.node.services.statemachine.FlowStateMachineImpl)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:144)
at com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer.read(CompatibleFieldSerializer.java:147)
at com.esotericsoftware.kryo.Kryo.readObjectOrNull(Kryo.java:782)
at co.paralleluniverse.io.serialization.kryo.ReplaceableObjectKryo.readObjectOrNull(ReplaceableObjectKryo.java:107)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:132)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:540)
at co.paralleluniverse.fibers.Fiber$FiberSerializer.read(Fiber.java:2137)
at co.paralleluniverse.fibers.Fiber$FiberSerializer.read(Fiber.java:2067)
at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:813)
at co.paralleluniverse.io.serialization.kryo.ReplaceableObjectKryo.readClassAndObject(ReplaceableObjectKryo.java:112)
at net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme$deserialize$$inlined$use$lambda$1$1.invoke(KryoSerializationScheme.kt:97)
at net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme$deserialize$$inlined$use$lambda$1$1.invoke(KryoSerializationScheme.kt:37)
at net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme.withContext(KryoSerializationScheme.kt:80)
at net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme.access$withContext(KryoSerializationScheme.kt:37)
at net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme$deserialize$$inlined$use$lambda$1.execute(KryoSerializationScheme.kt:95)
at com.esotericsoftware.kryo.pool.KryoPoolQueueImpl.run(KryoPoolQueueImpl.java:61)
at net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme.deserialize(KryoSerializationScheme.kt:94)
at net.corda.nodeapi.internal.serialization.SerializationFactoryImpl$deserialize$1$1.invoke(SerializationScheme.kt:111)
at net.corda.core.serialization.SerializationFactory.withCurrentContext(SerializationAPI.kt:66)
at net.corda.nodeapi.internal.serialization.SerializationFactoryImpl$deserialize$1.invoke(SerializationScheme.kt:111)
at net.corda.nodeapi.internal.serialization.SerializationFactoryImpl$deserialize$1.invoke(SerializationScheme.kt:86)
at net.corda.core.serialization.SerializationFactory.asCurrent(SerializationAPI.kt:80)
at net.corda.nodeapi.internal.serialization.SerializationFactoryImpl.deserialize(SerializationScheme.kt:111)
at net.corda.node.services.statemachine.StateMachineManagerImpl.deserializeFiber(StateMachineManagerImpl.kt:715)
at net.corda.node.services.statemachine.StateMachineManagerImpl.access$deserializeFiber(StateMachineManagerImpl.kt:63)
at net.corda.node.services.statemachine.StateMachineManagerImpl$updateCheckpoint$2.run(StateMachineManagerImpl.kt:551)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.UnsupportedOperationException
at java.util.AbstractCollection.add(AbstractCollection.java:262)
at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:134)
at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:40)
at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:813)
at co.paralleluniverse.io.serialization.kryo.ReplaceableObjectKryo.readClassAndObject(ReplaceableObjectKryo.java:112)
at de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer.read(UnmodifiableCollectionsSerializer.java:71)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:731)
at co.paralleluniverse.io.serialization.kryo.ReplaceableObjectKryo.readObject(ReplaceableObjectKryo.java:92)
at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.read(DefaultArraySerializers.java:392)
at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.read(DefaultArraySerializers.java:303)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:731)
at co.paralleluniverse.io.serialization.kryo.ReplaceableObjectKryo.readObject(ReplaceableObjectKryo.java:92)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:125)
... 28 more
[INFO ] 17:02:38,664 [Mock network] (FlowStateMachineImpl.kt:432) flow.[66a8e516-7d9e-4ff3-a922-c80dda86768e].initiateSession - Initiating flow session with party O=Notary Service, L=Zurich, C=CH. Session id for tracing purposes is SessionId(toLong=763122305110574148). {}
[ERROR] 17:02:38,660 [CheckpointChecker-1] (StateMachineManagerImpl.kt:417) flow.[66a8e516-7d9e-4ff3-a922-c80dda86768e].deserializeFiber - Encountered unrestorable checkpoint! {}
com.esotericsoftware.kryo.KryoException: java.lang.UnsupportedOperationException
KatとAndras @ R3からのすばらしいヘルプを投稿して、この問題の最後に到達しました。もう少しグーグルヘルプがあるように、私はこれをここに投稿するように頼まれました!
ソリューション(TL; DR)
オブジェクトのマップがあり、それらのオブジェクトごとに、基本的に2つのサブフロー(handleEventメソッドの下)を開始するメソッドを呼び出したいと思いました。
これは失敗していました:
modelDataMap.values.forEach { it.handleEvent(event, this, flowLogic, notary) }
しかし、これは問題を修正します:
modelDataMap.values.toList().forEach { it.handleEvent(event, this, flowLogic, notary) }
最初のケースでは、Kryoは値を変更不可能なコレクションとして逆シリアル化し、要素を追加できなかったと思います。toListの結果、Kryoは値を追加できるコレクションを作成し、すべてが正常でした。
これを理解する方法
この問題の原因となった変更されたコードパスを認識していました。私の場合、スタックトレースの前にログ行があり、どこから始めればよいかについてのヒントが得られました。
Andrasは、この時点で2つの便利なツールを指摘しました。
@Suspendableアノテーションがありません
テストに次のフラグを追加した場合:
-Dco.paralleluniverse.fibers.verifyInstrumentation=true
@Suspendableアノテーションがないスタック内のメソッドが通知されます。これは実際に本当に役に立ちます。
FlowStackSnapshot
Andrasは、スタックを印刷するために使用できるツールをFlowLogicに追加しました。これに、スタックを反復処理するメソッドを追加し、すべてを再帰的にシリアル化および逆シリアル化して、問題の原因を特定できるようにするというアイデアがありました。
今のところ、爆破する直前にこれを適切なポイントに追加すると、少なくともKryoの観点からスタックを表示できるようになります。
val snapshot = flowLogic.flowStackSnapshot()
Corda 3.2の時点では、flowStackSnapshotのコードパスに@Suspendableがないため、現時点ではflowStackSnapshotでverifyInstrumentationフラグを使用しないでください:-)
もう一度-これの底に到達するのを手伝ってくれたKatとAndrasに大いに感謝します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加