Twitter Chill 在 Android 上崩溃
Twitter Chill crashing on Android
我正在尝试 Kryo+Chill(com.twitter:chill_2.11:0.8.0
和 Scala 版本是 2.11.8
)。以下代码在桌面上运行良好,但在 Android 上它崩溃了。
case class TestDogRef(id: Int)
case class TestDog(ref: TestDogRef, name: String, friends: Seq[TestDogRef])
class TestHouse[T](val data: Seq[T])
case class TestDogHouse(override val data: Seq[TestDog]) extends TestHouse[TestDog](data)
def serialize[A](data: A): Array[Byte] = {
val instantiator = new ScalaKryoInstantiator
instantiator.setRegistrationRequired(false)
val kryo = instantiator.newKryo()
val bao = new ByteArrayOutputStream
val output = new Output(bao)
kryo.writeObject(output, data)
output.close()
bao.toByteArray
}
def deserialize[A](ser: Array[Byte], clazz: Class[A]): A = {
val instantiator = new ScalaKryoInstantiator
instantiator.setRegistrationRequired(false)
val kryo = instantiator.newKryo()
val input = new Input(new ByteArrayInputStream(ser))
val deserData = kryo.readObject(input, clazz)
deserData
}
override def run(): String = {
val orig = TestDogHouse(Seq(TestDog(TestDogRef(4), "Doggy", Seq(TestDogRef(1)))))
val serialized = serialize(orig)
val deserialized = deserialize(serialized, classOf[TestDogHouse])
deserialized.toString
}
这是崩溃:
07-14 11:55:42.053 6744-6764/x.y E/AndroidRuntime: FATAL EXCEPTION: GLThread 137
java.lang.ExceptionInInitializerError
at com.twitter.chill.java.PackageRegistrar.all(Unknown Source)
at com.twitter.chill.AllScalaRegistrar.apply(Unknown Source)
at com.twitter.chill.ScalaKryoInstantiator.newKryo(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.serialize(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.run(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at scala.collection.immutable.List.foreach(Unknown Source)
at x.y.LibraryTests$.run(Unknown Source)
at x.y.a.a(Unknown Source)
at com.badlogic.gdx.backends.android.j.onSurfaceChanged(Unknown Source)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1505)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Caused by: com.esotericsoftware.kryo.KryoException: Error while getting field 'words' of bitSet
at com.twitter.chill.java.BitSetSerializer.<clinit>(Unknown Source)
at com.twitter.chill.java.PackageRegistrar.all(Unknown Source)
at com.twitter.chill.AllScalaRegistrar.apply(Unknown Source)
at com.twitter.chill.ScalaKryoInstantiator.newKryo(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.serialize(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.run(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at scala.collection.immutable.List.foreach(Unknown Source)
at x.y.LibraryTests$.run(Unknown Source)
at x.y.a.a(Unknown Source)
at com.badlogic.gdx.backends.android.j.onSurfaceChanged(Unknown Source)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1505)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Caused by: java.lang.NoSuchFieldException: words
at java.lang.Class.getDeclaredField(Class.java:631)
at com.twitter.chill.java.BitSetSerializer.<clinit>(Unknown Source)
at com.twitter.chill.java.PackageRegistrar.all(Unknown Source)
at com.twitter.chill.AllScalaRegistrar.apply(Unknown Source)
at com.twitter.chill.ScalaKryoInstantiator.newKryo(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.serialize(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.run(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at scala.collection.immutable.List.foreach(Unknown Source)
at x.y.LibraryTests$.run(Unknown Source)
at x.y.a.a(Unknown Source)
at com.badlogic.gdx.backends.android.j.onSurfaceChanged(Unknown Source)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1505)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
我怀疑这是因为 ProGuard - 有些东西被破坏或掉落,但我不知道我还能做什么。
相关混淆规则:
-keep class scala.collection.BitSet { *; }
-keepclassmembers class scala.collection.BitSet { *; }
-keep class scala.collection.immutable.BitSet { *; }
-keepclassmembers class scala.collection.immutable.BitSet { *; }
-keep class scala.collection.BitSetLike { *; }
-keepclassmembers class scala.collection.BitSetLike { *; }
-keep class scala.collection.immutable.BitSet.** { *; }
-keepclassmembers class scala.collection.immutable.BitSet.** { *; }
-keepnames class scala.** { *; }
如有任何帮助,我将不胜感激。
此问题与 ProGuard 无关。 chill
java 库有一个 BitSetSerializer
for java.util.BitSet
类 通过反射访问字段(名为 words
)。现在 Android 中包含的 java.util.BitSet
实现(派生自 Apache Harmony 项目高达 Android 6,Android N 将基于 OpenJDK)没有这样的字段你会得到问题中看到的运行时错误。
查看chill-scala库的源代码,使用ScalaKryoInstantiator
也会注册所有Java相关的序列化器。您也许可以通过使用 EmptyScalaKryoInstantiator
并注册所有需要的序列化程序来规避此问题:
val instantiator = new EmptyScalaKryoInstantiator
instantiator.setRegistrationRequired(false)
val kryo = instantiator.newKryo()
val col = new ScalaCollectionsRegistrar
col(kryo)
ScalaTupleSerialization.register(kryo)
....
// others as needed
另请参阅 ScalaKryoInstantiator.scala 以了解要包含哪些序列化程序。
我正在尝试 Kryo+Chill(com.twitter:chill_2.11:0.8.0
和 Scala 版本是 2.11.8
)。以下代码在桌面上运行良好,但在 Android 上它崩溃了。
case class TestDogRef(id: Int)
case class TestDog(ref: TestDogRef, name: String, friends: Seq[TestDogRef])
class TestHouse[T](val data: Seq[T])
case class TestDogHouse(override val data: Seq[TestDog]) extends TestHouse[TestDog](data)
def serialize[A](data: A): Array[Byte] = {
val instantiator = new ScalaKryoInstantiator
instantiator.setRegistrationRequired(false)
val kryo = instantiator.newKryo()
val bao = new ByteArrayOutputStream
val output = new Output(bao)
kryo.writeObject(output, data)
output.close()
bao.toByteArray
}
def deserialize[A](ser: Array[Byte], clazz: Class[A]): A = {
val instantiator = new ScalaKryoInstantiator
instantiator.setRegistrationRequired(false)
val kryo = instantiator.newKryo()
val input = new Input(new ByteArrayInputStream(ser))
val deserData = kryo.readObject(input, clazz)
deserData
}
override def run(): String = {
val orig = TestDogHouse(Seq(TestDog(TestDogRef(4), "Doggy", Seq(TestDogRef(1)))))
val serialized = serialize(orig)
val deserialized = deserialize(serialized, classOf[TestDogHouse])
deserialized.toString
}
这是崩溃:
07-14 11:55:42.053 6744-6764/x.y E/AndroidRuntime: FATAL EXCEPTION: GLThread 137
java.lang.ExceptionInInitializerError
at com.twitter.chill.java.PackageRegistrar.all(Unknown Source)
at com.twitter.chill.AllScalaRegistrar.apply(Unknown Source)
at com.twitter.chill.ScalaKryoInstantiator.newKryo(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.serialize(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.run(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at scala.collection.immutable.List.foreach(Unknown Source)
at x.y.LibraryTests$.run(Unknown Source)
at x.y.a.a(Unknown Source)
at com.badlogic.gdx.backends.android.j.onSurfaceChanged(Unknown Source)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1505)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Caused by: com.esotericsoftware.kryo.KryoException: Error while getting field 'words' of bitSet
at com.twitter.chill.java.BitSetSerializer.<clinit>(Unknown Source)
at com.twitter.chill.java.PackageRegistrar.all(Unknown Source)
at com.twitter.chill.AllScalaRegistrar.apply(Unknown Source)
at com.twitter.chill.ScalaKryoInstantiator.newKryo(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.serialize(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.run(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at scala.collection.immutable.List.foreach(Unknown Source)
at x.y.LibraryTests$.run(Unknown Source)
at x.y.a.a(Unknown Source)
at com.badlogic.gdx.backends.android.j.onSurfaceChanged(Unknown Source)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1505)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Caused by: java.lang.NoSuchFieldException: words
at java.lang.Class.getDeclaredField(Class.java:631)
at com.twitter.chill.java.BitSetSerializer.<clinit>(Unknown Source)
at com.twitter.chill.java.PackageRegistrar.all(Unknown Source)
at com.twitter.chill.AllScalaRegistrar.apply(Unknown Source)
at com.twitter.chill.ScalaKryoInstantiator.newKryo(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.serialize(Unknown Source)
at x.y.LibraryTests$KryoWithChillTest$.run(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at x.y.LibraryTests$$anonfun$run.apply(Unknown Source)
at scala.collection.immutable.List.foreach(Unknown Source)
at x.y.LibraryTests$.run(Unknown Source)
at x.y.a.a(Unknown Source)
at com.badlogic.gdx.backends.android.j.onSurfaceChanged(Unknown Source)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1505)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
我怀疑这是因为 ProGuard - 有些东西被破坏或掉落,但我不知道我还能做什么。
相关混淆规则:
-keep class scala.collection.BitSet { *; }
-keepclassmembers class scala.collection.BitSet { *; }
-keep class scala.collection.immutable.BitSet { *; }
-keepclassmembers class scala.collection.immutable.BitSet { *; }
-keep class scala.collection.BitSetLike { *; }
-keepclassmembers class scala.collection.BitSetLike { *; }
-keep class scala.collection.immutable.BitSet.** { *; }
-keepclassmembers class scala.collection.immutable.BitSet.** { *; }
-keepnames class scala.** { *; }
如有任何帮助,我将不胜感激。
此问题与 ProGuard 无关。 chill
java 库有一个 BitSetSerializer
for java.util.BitSet
类 通过反射访问字段(名为 words
)。现在 Android 中包含的 java.util.BitSet
实现(派生自 Apache Harmony 项目高达 Android 6,Android N 将基于 OpenJDK)没有这样的字段你会得到问题中看到的运行时错误。
查看chill-scala库的源代码,使用ScalaKryoInstantiator
也会注册所有Java相关的序列化器。您也许可以通过使用 EmptyScalaKryoInstantiator
并注册所有需要的序列化程序来规避此问题:
val instantiator = new EmptyScalaKryoInstantiator
instantiator.setRegistrationRequired(false)
val kryo = instantiator.newKryo()
val col = new ScalaCollectionsRegistrar
col(kryo)
ScalaTupleSerialization.register(kryo)
....
// others as needed
另请参阅 ScalaKryoInstantiator.scala 以了解要包含哪些序列化程序。