Skip to content

Commit a0be93b

Browse files
committed
Merge pull request #192 from rxin/asJavaIterable
Support serializing asJavaIterable.
2 parents 9c47f4e + 9cd7ba4 commit a0be93b

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.twitter.chill
2+
3+
import _root_.java.lang.{ Iterable => JIterable }
4+
5+
/**
6+
* A Kryo serializer for serializing results returned by asJavaIterable.
7+
*
8+
* The underlying object is scala.collection.convert.Wrappers$IterableWrapper.
9+
* Kryo deserializes this into an AbstractCollection, which unfortunately doesn't work.
10+
*
11+
* Ported from Apache Spark's KryoSerializer.scala.
12+
*/
13+
private class JavaIterableWrapperSerializer extends KSerializer[JIterable[_]] {
14+
15+
import JavaIterableWrapperSerializer._
16+
17+
override def write(kryo: Kryo, out: Output, obj: JIterable[_]): Unit = {
18+
// If the object is the wrapper, simply serialize the underlying Scala Iterable object.
19+
// Otherwise, serialize the object itself.
20+
if (obj.getClass == wrapperClass && underlyingMethodOpt.isDefined) {
21+
kryo.writeClassAndObject(out, underlyingMethodOpt.get.invoke(obj))
22+
} else {
23+
kryo.writeClassAndObject(out, obj)
24+
}
25+
}
26+
27+
override def read(kryo: Kryo, in: Input, clz: Class[JIterable[_]]): JIterable[_] = {
28+
kryo.readClassAndObject(in) match {
29+
case scalaIterable: Iterable[_] =>
30+
scala.collection.JavaConversions.asJavaIterable(scalaIterable)
31+
case javaIterable: JIterable[_] =>
32+
javaIterable
33+
}
34+
}
35+
}
36+
37+
private object JavaIterableWrapperSerializer {
38+
// The class returned by asJavaIterable (scala.collection.convert.Wrappers$IterableWrapper).
39+
val wrapperClass = scala.collection.JavaConversions.asJavaIterable(Seq(1)).getClass
40+
41+
// Get the underlying method so we can use it to get the Scala collection for serialization.
42+
private val underlyingMethodOpt = {
43+
try Some(wrapperClass.getDeclaredMethod("underlying")) catch {
44+
case e: Exception =>
45+
None
46+
}
47+
}
48+
}

chill-scala/src/main/scala/com/twitter/chill/ScalaKryoInstantiator.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,21 @@ class ScalaCollectionsRegistrar extends IKryoRegistrar {
163163
}
164164
}
165165

166+
class JavaWrapperCollectionRegistrar extends IKryoRegistrar {
167+
def apply(newK: Kryo) {
168+
newK.register(JavaIterableWrapperSerializer.wrapperClass, new JavaIterableWrapperSerializer)
169+
}
170+
}
171+
166172
/** Registers all the scala (and java) serializers we have */
167173
class AllScalaRegistrar extends IKryoRegistrar {
168174
def apply(k: Kryo) {
169175
val col = new ScalaCollectionsRegistrar
170176
col(k)
177+
178+
val jcol = new JavaWrapperCollectionRegistrar
179+
jcol(k)
180+
171181
// Register all 22 tuple serializers and specialized serializers
172182
ScalaTupleSerialization.register(k)
173183
k.forClass[Symbol](new KSerializer[Symbol] {

chill-scala/src/test/scala/com/twitter/chill/KryoSpec.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ class KryoSpec extends Specification with BaseProperties {
172172
"handle scala enums" in {
173173
WeekDay.values.foreach { _ must roundtrip }
174174
}
175+
"handle asJavaIterable" in {
176+
val col = scala.collection.JavaConversions.asJavaIterable(Seq(12345))
177+
col must roundtrip
178+
}
175179
"use java serialization" in {
176180
val kinst = { () => getKryo.javaForClass[TestCaseClassForSerialization] }
177181
rtEquiv(kinst, TestCaseClassForSerialization("hey", 42)) must beTrue

0 commit comments

Comments
 (0)