in chill-scala/src/main/scala/com/twitter/chill/ScalaKryoInstantiator.scala [110:180]
def apply(newK: Kryo): Unit = {
// for binary compat this is here, but could be moved to RichKryo
def useField[T](cls: Class[T]): Unit = {
val fs = new com.esotericsoftware.kryo.serializers.FieldSerializer(newK, cls)
fs.setIgnoreSyntheticFields(false) // scala generates a lot of these attributes
newK.register(cls, fs)
}
// The wrappers are private classes:
useField(List(1, 2, 3).asJava.getClass)
useField(List(1, 2, 3).iterator.asJava.getClass)
useField(Map(1 -> 2, 4 -> 3).asJava.getClass)
useField(new _root_.java.util.ArrayList().asScala.getClass)
useField(new _root_.java.util.HashMap().asScala.getClass)
/*
* Note that subclass-based use: addDefaultSerializers, else: register
* You should go from MOST specific, to least to specific when using
* default serializers. The FIRST one found is the one used
*/
newK
// wrapper array is abstract
.forSubclass[WrappedArray[Any]](new WrappedArraySerializer[Any])
.forSubclass[BitSet](new BitSetSerializer)
.forSubclass[SortedSet[Any]](new SortedSetSerializer)
.forClass[Some[Any]](new SomeSerializer[Any])
.forClass[Left[Any, Any]](new LeftSerializer[Any, Any])
.forClass[Right[Any, Any]](new RightSerializer[Any, Any])
.forTraversableSubclass(Queue.empty[Any])
// List is a sealed class, so there are only two subclasses:
.forTraversableSubclass(List.empty[Any])
// Add ListBuffer subclass before Buffer to prevent the more general case taking precedence
.forTraversableSubclass(ListBuffer.empty[Any], isImmutable = false)
// add mutable Buffer before Vector, otherwise Vector is used
.forTraversableSubclass(Buffer.empty[Any], isImmutable = false)
// Vector is a final class in 2.11 / 2.12
// for 2.13 we have specific implementations
// we should not match subclasses as it conflicts with wrappers
.forTraversableClass(Vector.empty[Any])
.forTraversableSubclass(ListSet.empty[Any])
// specifically register small sets since Scala represents them differently
.forConcreteTraversableClass(Set[Any]('a))
.forConcreteTraversableClass(Set[Any]('a, 'b))
.forConcreteTraversableClass(Set[Any]('a, 'b, 'c))
.forConcreteTraversableClass(Set[Any]('a, 'b, 'c, 'd))
// default set implementation
.forConcreteTraversableClass(HashSet[Any]('a, 'b, 'c, 'd, 'e))
// specifically register small maps since Scala represents them differently
.forConcreteTraversableClass(Map[Any, Any]('a -> 'a))
.forConcreteTraversableClass(Map[Any, Any]('a -> 'a, 'b -> 'b))
.forConcreteTraversableClass(Map[Any, Any]('a -> 'a, 'b -> 'b, 'c -> 'c))
.forConcreteTraversableClass(Map[Any, Any]('a -> 'a, 'b -> 'b, 'c -> 'c, 'd -> 'd))
// default map implementation
.forConcreteTraversableClass(HashMap[Any, Any]('a -> 'a, 'b -> 'b, 'c -> 'c, 'd -> 'd, 'e -> 'e))
// The normal fields serializer works for ranges
.registerClasses(
Seq(classOf[Range.Inclusive], classOf[NumericRange.Inclusive[_]], classOf[NumericRange.Exclusive[_]])
)
// Add some maps
.forSubclass[SortedMap[Any, Any]](new SortedMapSerializer)
.forTraversableSubclass(ListMap.empty[Any, Any])
.forTraversableSubclass(HashMap.empty[Any, Any])
// The above ListMap/HashMap must appear before this:
.forTraversableSubclass(Map.empty[Any, Any])
// here are the mutable ones:
.forTraversableClass(MBitSet.empty, isImmutable = false)
.forTraversableClass(MHashMap.empty[Any, Any], isImmutable = false)
.forTraversableClass(MHashSet.empty[Any], isImmutable = false)
.forTraversableSubclass(MQueue.empty[Any], isImmutable = false)
.forTraversableSubclass(MMap.empty[Any, Any], isImmutable = false)
.forTraversableSubclass(MSet.empty[Any], isImmutable = false)
}