2011-06-07 06:36:21 +05:30
|
|
|
package akka.serialization
|
|
|
|
|
|
|
|
|
|
/**
|
2016-02-23 12:58:39 +01:00
|
|
|
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
|
2011-06-07 06:36:21 +05:30
|
|
|
*/
|
|
|
|
|
|
2016-02-22 20:18:15 +01:00
|
|
|
import java.io.{ ObjectOutputStream, ByteArrayOutputStream, ByteArrayInputStream }
|
2016-05-26 11:58:13 +02:00
|
|
|
import java.nio.ByteBuffer
|
2012-12-18 01:25:21 +01:00
|
|
|
import java.util.concurrent.Callable
|
2011-06-07 06:36:21 +05:30
|
|
|
import akka.util.ClassLoaderObjectInputStream
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
import akka.actor.ExtendedActorSystem
|
|
|
|
|
import scala.util.DynamicVariable
|
2011-07-19 14:20:18 +02:00
|
|
|
|
2011-07-19 19:28:17 +02:00
|
|
|
/**
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
* A Serializer represents a bimap between an object and an array of bytes representing that object.
|
|
|
|
|
*
|
|
|
|
|
* Serializers are loaded using reflection during [[akka.actor.ActorSystem]]
|
|
|
|
|
* start-up, where two constructors are tried in order:
|
|
|
|
|
*
|
|
|
|
|
* <ul>
|
|
|
|
|
* <li>taking exactly one argument of type [[akka.actor.ExtendedActorSystem]];
|
|
|
|
|
* this should be the preferred one because all reflective loading of classes
|
2012-02-10 11:36:23 +01:00
|
|
|
* during deserialization should use ExtendedActorSystem.dynamicAccess (see
|
|
|
|
|
* [[akka.actor.DynamicAccess]]), and</li>
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
* <li>without arguments, which is only an option if the serializer does not
|
|
|
|
|
* load classes using reflection.</li>
|
|
|
|
|
* </ul>
|
|
|
|
|
*
|
2016-03-10 10:10:44 +01:00
|
|
|
* <b>Be sure to always use the </b>[[akka.actor.DynamicAccess]]<b> for loading classes!</b> This is necessary to
|
2012-02-09 19:26:02 +01:00
|
|
|
* avoid strange match errors and inequalities which arise from different class loaders loading
|
|
|
|
|
* the same class.
|
2011-07-19 19:28:17 +02:00
|
|
|
*/
|
2012-02-06 14:19:59 +01:00
|
|
|
trait Serializer {
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
|
2011-07-19 14:20:18 +02:00
|
|
|
/**
|
2015-03-05 11:55:05 -06:00
|
|
|
* Completely unique value to identify this implementation of Serializer, used to optimize network traffic.
|
|
|
|
|
* Values from 0 to 16 are reserved for Akka internal usage.
|
2011-07-19 14:20:18 +02:00
|
|
|
*/
|
2011-12-30 22:00:49 +01:00
|
|
|
def identifier: Int
|
2011-07-19 19:28:17 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Serializes the given object into an Array of Byte
|
|
|
|
|
*/
|
2011-06-07 06:36:21 +05:30
|
|
|
def toBinary(o: AnyRef): Array[Byte]
|
2011-07-19 19:28:17 +02:00
|
|
|
|
2011-12-29 16:11:56 +01:00
|
|
|
/**
|
|
|
|
|
* Returns whether this serializer needs a manifest in the fromBinary method
|
|
|
|
|
*/
|
|
|
|
|
def includeManifest: Boolean
|
|
|
|
|
|
2011-12-30 22:00:49 +01:00
|
|
|
/**
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
* Produces an object from an array of bytes, with an optional type-hint;
|
2012-02-10 11:36:23 +01:00
|
|
|
* the class should be loaded using ActorSystem.dynamicAccess.
|
2011-07-19 19:28:17 +02:00
|
|
|
*/
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef
|
2012-02-10 12:45:22 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Java API: deserialize without type hint
|
|
|
|
|
*/
|
|
|
|
|
final def fromBinary(bytes: Array[Byte]): AnyRef = fromBinary(bytes, None)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Java API: deserialize with type hint
|
|
|
|
|
*/
|
|
|
|
|
final def fromBinary(bytes: Array[Byte], clazz: Class[_]): AnyRef = fromBinary(bytes, Option(clazz))
|
2011-12-30 22:00:49 +01:00
|
|
|
}
|
|
|
|
|
|
2015-05-28 18:42:22 +02:00
|
|
|
/**
|
|
|
|
|
* A Serializer represents a bimap between an object and an array of bytes representing that object.
|
|
|
|
|
*
|
|
|
|
|
* For serialization of data that need to evolve over time the `SerializerWithStringManifest` is recommended instead
|
|
|
|
|
* of [[Serializer]] because the manifest (type hint) is a `String` instead of a `Class`. That means
|
|
|
|
|
* that the class can be moved/removed and the serializer can still deserialize old data by matching
|
|
|
|
|
* on the `String`. This is especially useful for Akka Persistence.
|
|
|
|
|
*
|
2016-03-10 10:10:44 +01:00
|
|
|
* The manifest string can also encode a version number that can be used in `fromBinary` to
|
2015-05-28 18:42:22 +02:00
|
|
|
* deserialize in different ways to migrate old data to new domain objects.
|
|
|
|
|
*
|
|
|
|
|
* If the data was originally serialized with [[Serializer]] and in a later version of the
|
|
|
|
|
* system you change to `SerializerWithStringManifest` the manifest string will be the full class name if
|
|
|
|
|
* you used `includeManifest=true`, otherwise it will be the empty string.
|
|
|
|
|
*
|
|
|
|
|
* Serializers are loaded using reflection during [[akka.actor.ActorSystem]]
|
|
|
|
|
* start-up, where two constructors are tried in order:
|
|
|
|
|
*
|
|
|
|
|
* <ul>
|
|
|
|
|
* <li>taking exactly one argument of type [[akka.actor.ExtendedActorSystem]];
|
|
|
|
|
* this should be the preferred one because all reflective loading of classes
|
|
|
|
|
* during deserialization should use ExtendedActorSystem.dynamicAccess (see
|
|
|
|
|
* [[akka.actor.DynamicAccess]]), and</li>
|
|
|
|
|
* <li>without arguments, which is only an option if the serializer does not
|
|
|
|
|
* load classes using reflection.</li>
|
|
|
|
|
* </ul>
|
|
|
|
|
*
|
2016-03-10 10:10:44 +01:00
|
|
|
* <b>Be sure to always use the </b>[[akka.actor.DynamicAccess]]<b> for loading classes!</b> This is necessary to
|
2015-05-28 18:42:22 +02:00
|
|
|
* avoid strange match errors and inequalities which arise from different class loaders loading
|
|
|
|
|
* the same class.
|
|
|
|
|
*/
|
|
|
|
|
abstract class SerializerWithStringManifest extends Serializer {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Completely unique value to identify this implementation of Serializer, used to optimize network traffic.
|
|
|
|
|
* Values from 0 to 16 are reserved for Akka internal usage.
|
|
|
|
|
*/
|
|
|
|
|
def identifier: Int
|
|
|
|
|
|
|
|
|
|
final override def includeManifest: Boolean = true
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the manifest (type hint) that will be provided in the fromBinary method.
|
|
|
|
|
* Use `""` if manifest is not needed.
|
|
|
|
|
*/
|
|
|
|
|
def manifest(o: AnyRef): String
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Serializes the given object into an Array of Byte
|
|
|
|
|
*/
|
|
|
|
|
def toBinary(o: AnyRef): Array[Byte]
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Produces an object from an array of bytes, with an optional type-hint;
|
|
|
|
|
* the class should be loaded using ActorSystem.dynamicAccess.
|
2016-12-16 11:36:04 +01:00
|
|
|
*
|
|
|
|
|
* It's recommended to throw `java.io.NotSerializableException` in `fromBinary`
|
|
|
|
|
* if the manifest is unknown. This makes it possible to introduce new message
|
|
|
|
|
* types and send them to nodes that don't know about them. This is typically
|
|
|
|
|
* needed when performing rolling upgrades, i.e. running a cluster with mixed
|
|
|
|
|
* versions for while. `NotSerializableException` is treated as a transient
|
|
|
|
|
* problem in the TCP based remoting layer. The problem will be logged
|
|
|
|
|
* and message is dropped. Other exceptions will tear down the TCP connection
|
|
|
|
|
* because it can be an indication of corrupt bytes from the underlying transport.
|
2015-05-28 18:42:22 +02:00
|
|
|
*/
|
|
|
|
|
def fromBinary(bytes: Array[Byte], manifest: String): AnyRef
|
|
|
|
|
|
|
|
|
|
final def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef = {
|
|
|
|
|
val manifestString = manifest match {
|
|
|
|
|
case Some(c) ⇒ c.getName
|
|
|
|
|
case None ⇒ ""
|
|
|
|
|
}
|
|
|
|
|
fromBinary(bytes, manifestString)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-26 11:58:13 +02:00
|
|
|
/**
|
|
|
|
|
* Serializer between an object and a `ByteBuffer` representing that object.
|
|
|
|
|
*
|
|
|
|
|
* Implementations should typically extend [[SerializerWithStringManifest]] and
|
|
|
|
|
* in addition to the `ByteBuffer` based `toBinary` and `fromBinary` methods also
|
|
|
|
|
* implement the array based `toBinary` and `fromBinary` methods. The array based
|
|
|
|
|
* methods will be used when `ByteBuffer` is not used, e.g. in Akka Persistence.
|
|
|
|
|
*
|
|
|
|
|
* Note that the array based methods can for example be implemented by delegation
|
|
|
|
|
* like this:
|
|
|
|
|
* {{{
|
|
|
|
|
* // you need to know the maximum size in bytes of the serialized messages
|
|
|
|
|
* val pool = new akka.io.DirectByteBufferPool(defaultBufferSize = 1024 * 1024, maxPoolEntries = 10)
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* // Implement this method for compatibility with `SerializerWithStringManifest`.
|
|
|
|
|
* override def toBinary(o: AnyRef): Array[Byte] = {
|
|
|
|
|
* val buf = pool.acquire()
|
|
|
|
|
* try {
|
|
|
|
|
* toBinary(o, buf)
|
|
|
|
|
* buf.flip()
|
|
|
|
|
* val bytes = Array.ofDim[Byte](buf.remaining)
|
|
|
|
|
* buf.get(bytes)
|
|
|
|
|
* bytes
|
|
|
|
|
* } finally {
|
|
|
|
|
* pool.release(buf)
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* // Implement this method for compatibility with `SerializerWithStringManifest`.
|
|
|
|
|
* override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef =
|
|
|
|
|
* fromBinary(ByteBuffer.wrap(bytes), manifest)
|
|
|
|
|
*
|
|
|
|
|
* }}}
|
|
|
|
|
*/
|
2016-09-30 15:29:05 +02:00
|
|
|
//#ByteBufferSerializer
|
2016-05-26 11:58:13 +02:00
|
|
|
trait ByteBufferSerializer {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Serializes the given object into the `ByteBuffer`.
|
|
|
|
|
*/
|
|
|
|
|
def toBinary(o: AnyRef, buf: ByteBuffer): Unit
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Produces an object from a `ByteBuffer`, with an optional type-hint;
|
|
|
|
|
* the class should be loaded using ActorSystem.dynamicAccess.
|
|
|
|
|
*/
|
|
|
|
|
def fromBinary(buf: ByteBuffer, manifest: String): AnyRef
|
|
|
|
|
|
|
|
|
|
}
|
2016-09-30 15:29:05 +02:00
|
|
|
//#ByteBufferSerializer
|
2016-05-26 11:58:13 +02:00
|
|
|
|
2015-03-05 11:55:05 -06:00
|
|
|
/**
|
|
|
|
|
* Base serializer trait with serialization identifiers configuration contract,
|
|
|
|
|
* when globally unique serialization identifier is configured in the `reference.conf`.
|
|
|
|
|
*/
|
|
|
|
|
trait BaseSerializer extends Serializer {
|
|
|
|
|
/**
|
|
|
|
|
* Actor system which is required by most serializer implementations.
|
|
|
|
|
*/
|
2015-04-30 09:23:18 +02:00
|
|
|
def system: ExtendedActorSystem
|
2016-03-10 10:10:44 +01:00
|
|
|
|
2015-03-05 11:55:05 -06:00
|
|
|
/**
|
|
|
|
|
* Configuration namespace of serialization identifiers in the `reference.conf`.
|
|
|
|
|
*
|
|
|
|
|
* Each serializer implementation must have an entry in the following format:
|
|
|
|
|
* `akka.actor.serialization-identifiers."FQCN" = ID`
|
|
|
|
|
* where `FQCN` is fully qualified class name of the serializer implementation
|
|
|
|
|
* and `ID` is globally unique serializer identifier number.
|
|
|
|
|
*/
|
|
|
|
|
final val SerializationIdentifiers = "akka.actor.serialization-identifiers"
|
2016-03-10 10:10:44 +01:00
|
|
|
|
2015-03-05 11:55:05 -06:00
|
|
|
/**
|
|
|
|
|
* Globally unique serialization identifier configured in the `reference.conf`.
|
|
|
|
|
*
|
2016-03-10 10:10:44 +01:00
|
|
|
* See [[Serializer#identifier]].
|
2015-03-05 11:55:05 -06:00
|
|
|
*/
|
2015-04-30 09:23:18 +02:00
|
|
|
override val identifier: Int = identifierFromConfig
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* INTERNAL API
|
|
|
|
|
*/
|
|
|
|
|
private[akka] def identifierFromConfig: Int =
|
2015-03-05 11:55:05 -06:00
|
|
|
system.settings.config.getInt(s"""${SerializationIdentifiers}."${getClass.getName}"""")
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-30 22:00:49 +01:00
|
|
|
/**
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
* Java API for creating a Serializer: make sure to include a constructor which
|
|
|
|
|
* takes exactly one argument of type [[akka.actor.ExtendedActorSystem]], because
|
|
|
|
|
* that is the preferred constructor which will be invoked when reflectively instantiating
|
|
|
|
|
* the JSerializer (also possible with empty constructor).
|
2011-12-30 22:00:49 +01:00
|
|
|
*/
|
|
|
|
|
abstract class JSerializer extends Serializer {
|
2012-02-10 12:45:22 +01:00
|
|
|
final def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef =
|
|
|
|
|
fromBinaryJava(bytes, manifest.orNull)
|
2011-12-30 22:00:49 +01:00
|
|
|
|
|
|
|
|
/**
|
2012-02-10 12:45:22 +01:00
|
|
|
* This method must be implemented, manifest may be null.
|
2011-12-30 22:00:49 +01:00
|
|
|
*/
|
2012-02-10 12:45:22 +01:00
|
|
|
protected def fromBinaryJava(bytes: Array[Byte], manifest: Class[_]): AnyRef
|
2011-06-07 06:36:21 +05:30
|
|
|
}
|
|
|
|
|
|
2011-07-19 14:20:18 +02:00
|
|
|
object NullSerializer extends NullSerializer
|
|
|
|
|
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
object JavaSerializer {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This holds a reference to the current ActorSystem (the surrounding context)
|
|
|
|
|
* during serialization and deserialization.
|
|
|
|
|
*
|
|
|
|
|
* If you are using Serializers yourself, outside of SerializationExtension,
|
|
|
|
|
* you'll need to surround the serialization/deserialization with:
|
|
|
|
|
*
|
|
|
|
|
* currentSystem.withValue(system) {
|
|
|
|
|
* ...code...
|
|
|
|
|
* }
|
2012-12-18 01:25:21 +01:00
|
|
|
*
|
|
|
|
|
* or
|
|
|
|
|
*
|
|
|
|
|
* currentSystem.withValue(system, callable)
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
*/
|
2012-12-18 01:25:21 +01:00
|
|
|
val currentSystem = new CurrentSystem
|
|
|
|
|
final class CurrentSystem extends DynamicVariable[ExtendedActorSystem](null) {
|
|
|
|
|
/**
|
2013-03-07 09:05:55 +01:00
|
|
|
* Java API: invoke the callable with the current system being set to the given value for this thread.
|
|
|
|
|
*
|
2012-12-18 01:25:21 +01:00
|
|
|
* @param value - the current value under the call to callable.call()
|
|
|
|
|
* @param callable - the operation to be performed
|
|
|
|
|
* @return the result of callable.call()
|
|
|
|
|
*/
|
|
|
|
|
def withValue[S](value: ExtendedActorSystem, callable: Callable[S]): S = super.withValue[S](value)(callable.call)
|
|
|
|
|
}
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
}
|
|
|
|
|
|
2011-12-29 16:17:19 +01:00
|
|
|
/**
|
|
|
|
|
* This Serializer uses standard Java Serialization
|
|
|
|
|
*/
|
2015-03-05 11:55:05 -06:00
|
|
|
class JavaSerializer(val system: ExtendedActorSystem) extends BaseSerializer {
|
2011-07-19 14:20:18 +02:00
|
|
|
|
2015-04-30 09:23:18 +02:00
|
|
|
@deprecated("Use constructor with ExtendedActorSystem", "2.4")
|
|
|
|
|
def this() = this(null)
|
|
|
|
|
|
|
|
|
|
// TODO remove this when deprecated this() is removed
|
|
|
|
|
override val identifier: Int =
|
|
|
|
|
if (system eq null) 1
|
|
|
|
|
else identifierFromConfig
|
|
|
|
|
|
2011-12-29 16:11:56 +01:00
|
|
|
def includeManifest: Boolean = false
|
|
|
|
|
|
2011-06-07 06:36:21 +05:30
|
|
|
def toBinary(o: AnyRef): Array[Byte] = {
|
|
|
|
|
val bos = new ByteArrayOutputStream
|
|
|
|
|
val out = new ObjectOutputStream(bos)
|
2012-02-20 11:06:12 +01:00
|
|
|
JavaSerializer.currentSystem.withValue(system) { out.writeObject(o) }
|
2011-06-07 06:36:21 +05:30
|
|
|
out.close()
|
|
|
|
|
bos.toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = {
|
2012-02-10 11:36:23 +01:00
|
|
|
val in = new ClassLoaderObjectInputStream(system.dynamicAccess.classLoader, new ByteArrayInputStream(bytes))
|
2012-02-20 11:06:12 +01:00
|
|
|
val obj = JavaSerializer.currentSystem.withValue(system) { in.readObject }
|
2011-06-07 06:36:21 +05:30
|
|
|
in.close()
|
|
|
|
|
obj
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-29 16:17:19 +01:00
|
|
|
/**
|
|
|
|
|
* This is a special Serializer that Serializes and deserializes nulls only
|
|
|
|
|
*/
|
2011-07-19 14:20:18 +02:00
|
|
|
class NullSerializer extends Serializer {
|
|
|
|
|
val nullAsBytes = Array[Byte]()
|
2011-12-29 16:11:56 +01:00
|
|
|
def includeManifest: Boolean = false
|
2011-12-30 22:00:49 +01:00
|
|
|
def identifier = 0
|
2016-09-26 15:04:53 +02:00
|
|
|
def toBinary(o: AnyRef): Array[Byte] = nullAsBytes
|
Bye-bye ReflectiveAccess, introducing PropertyMaster, see #1750
- PropertyMaster is the only place in Akka which calls
ClassLoader.getClass (apart from kernel, which might be special)
- all PropertyMaster methods (there are only three) take a ClassManifest
of what is to be constructed, and they verify that the obtained object
is actually compatible with the required type
Other stuff:
- noticed that I had forgotten to change to ExtendedActorSystem when
constructing Extensions by ExtensionKey (damn you, reflection!)
- moved Serializer.currentSystem into JavaSerializer, because that’s the
only one needing it (it’s only used in readResolve() methods)
- Serializers are constructed now with one-arg constructor taking
ExtendedActorSystem (if that exists, otherwise no-arg as before), to
allow JavaSerializer to do its magic; possibly necessary for others as
well
- Removed all Option[ClassLoader] signatures
- made it so that the ActorSystem will try context class loader, then
the class loader which loaded the class actually calling into
ActorSystem.apply, then the loader which loaded ActorSystemImpl
- for the second of the above I added a (reflectively accessed hopefully
safe) facility for getting caller Class[_] objects by using
sun.reflect.Reflection; this is optional an defaults to None, e.g. on
Android, which means that getting the caller’s classloader is done on
a best effort basis (there’s nothing we can do because a StackTrace
does not contain actual Class[_] objects).
- refactored DurableMailbox to contain the owner val and use that
instead of declaring that in all subclasses
2012-02-09 11:56:43 +01:00
|
|
|
def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = null
|
2011-06-07 06:36:21 +05:30
|
|
|
}
|
2012-09-27 00:59:33 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is a special Serializer that Serializes and deserializes byte arrays only,
|
|
|
|
|
* (just returns the byte array unchanged/uncopied)
|
|
|
|
|
*/
|
2016-05-26 11:58:13 +02:00
|
|
|
class ByteArraySerializer(val system: ExtendedActorSystem) extends BaseSerializer with ByteBufferSerializer {
|
2015-04-30 09:23:18 +02:00
|
|
|
|
|
|
|
|
@deprecated("Use constructor with ExtendedActorSystem", "2.4")
|
|
|
|
|
def this() = this(null)
|
|
|
|
|
|
|
|
|
|
// TODO remove this when deprecated this() is removed
|
|
|
|
|
override val identifier: Int =
|
|
|
|
|
if (system eq null) 4
|
|
|
|
|
else identifierFromConfig
|
|
|
|
|
|
2012-09-27 00:59:33 +02:00
|
|
|
def includeManifest: Boolean = false
|
2016-09-26 15:04:53 +02:00
|
|
|
def toBinary(o: AnyRef): Array[Byte] = o match {
|
2012-09-27 00:59:33 +02:00
|
|
|
case null ⇒ null
|
|
|
|
|
case o: Array[Byte] ⇒ o
|
2016-05-26 11:58:13 +02:00
|
|
|
case other ⇒ throw new IllegalArgumentException(
|
|
|
|
|
s"${getClass.getName} only serializes byte arrays, not [${other.getClass.getName}]")
|
2012-09-27 00:59:33 +02:00
|
|
|
}
|
|
|
|
|
def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef = bytes
|
2016-05-26 11:58:13 +02:00
|
|
|
|
|
|
|
|
override def toBinary(o: AnyRef, buf: ByteBuffer): Unit =
|
|
|
|
|
o match {
|
|
|
|
|
case null ⇒
|
|
|
|
|
case bytes: Array[Byte] ⇒ buf.put(bytes)
|
|
|
|
|
case other ⇒ throw new IllegalArgumentException(
|
|
|
|
|
s"${getClass.getName} only serializes byte arrays, not [${other.getClass.getName}]")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def fromBinary(buf: ByteBuffer, manifest: String): AnyRef = {
|
|
|
|
|
val bytes = Array.ofDim[Byte](buf.remaining())
|
|
|
|
|
buf.get(bytes)
|
|
|
|
|
bytes
|
|
|
|
|
}
|
2012-09-27 00:59:33 +02:00
|
|
|
}
|