6

非常に単純なデータ構造をシリアル化/逆シリアル化しようとすると発生する次の問題を理解しようとしています。

case class SimpleClass(i: Int)

object SerializationDebug {

  def main(args: Array[String]) {
    val c = SimpleClass(0)
    val l1 = List(c)

    serializationSaveToFile("test", l1)
    val l2 = serializationLoadFromFile("test") // .asInstanceOf ...
  }

  def serializationSaveToFile(fn: String, o: Any) {
    val fos = new FileOutputStream(fn)
    val oos = new ObjectOutputStream(fos)
    oos.writeObject(o)
    oos.close()
  }

  def serializationLoadFromFile(fn: String): Any = {
    val fis = new FileInputStream(fn)
    val ois = new ObjectInputStream(fis)
    return ois.readObject()
  }  
}

このコードを実行しようとするとjava.lang.ClassNotFoundException: SimpleClass、逆シリアル化のステップに入ります。私の調査の現在の結果は次のとおりです。

  • SimpleClassこの例は、組み込み型で交換した場合に機能します。つまり、問題なく逆シリアルList[Int]化できます。List[(Int, Double)]組み込み型と my を混在さSimpleClassせる (つまり、 を持つList[Any]) と、再び例外がスローされます。
  • 他のスコープで定義しようとしSimpleClassました (たとえば、オブジェクトまたはローカル スコープにネストされているなど) が、何も変わりませんでした。また、通常の (大文字と小文字を区別しない) クラスを拡張Serializableしても、同じ結果が得られます。
  • さらに困惑するのは、Array[SimpleClass]代わりにを使用すると機能するListことです! 他のコンテナーを試してみると、この奇妙な矛盾が確認SimpleClassされます。不変マップ内に型パラメーターを指定すると機能しますが、可変マップの場合は例外が発生します。

重要な場合: 私の Scala バージョンは 2.10.0 です。JDK は 1.7.0 です。

ここで何が起こっているのですか?これは失敗するはずですか、それとも何らかのバグですか? 私が直面している実際の問題は、はるかに複雑なデータ構造 (多数のネスト、組み込みクラスと独自クラスの混合) に関係しています。このデータ構造のシリアライズ/デシリアライズを最小限に抑えた簡単な方法 (つまり、コンテナ クラスとその型パラメータの有効な組み合わせを見つける必要なし) への提案も大歓迎です!

4

3 に答える 3

1

@trenobus @bluenote10 あなたの調査結果に関連する:

今日これに出くわしましたが、コンソールで定義したときにクラスの名前が異なる(マングルされている)ためだと思います。たとえば、Onescala からクラスをシリアル化しました

> import java.io._
import java.io._
> case class One(s: String, b: Boolean)
defined class One
> new ObjectOutputStream(new FileOutputStream("data")) writeObject One("abc", true)

次に、トップレベルで名前が付けられた同様のクラスを準備して、同じファイルからJavaでデシリアライズしようとしましたOne(SerialVersionUIDも同じにしましたが、問題ではないためここには含めませんでした)が、これを取得しましたエラー:

Exception in thread "main" java.lang.ClassNotFoundException: $line4.$read$$iw$$iw$One

クラスを定義するたびにscalaが(当然のことながら)新しいJVMクラスを作成し、おそらく内部マッピングを保持して、定義された名前で参照できるようにすることを示唆しています(One)。

同様に、JVM ではそのようなクラスはそれぞれ異なるため、One同じ scala コンソールでクラスを再定義し、dataファイルからデシリアライズしようとすると、(再定義した新しいクラスではなく) 元のクラスのオブジェクトが取得されます。 .

于 2013-09-03T17:12:24.870 に答える
-1

SimpleClass が Serializable を拡張する場合に機能します。

于 2013-05-05T17:13:07.150 に答える