2018-03-13 23:45:55 +09:00
/*
* Copyright ( C ) 2018 Lightbend Inc . < https : //www.lightbend.com>
*/
2011-06-07 06:36:21 +05:30
package akka.serialization
/* *
2018-01-04 17:26:29 +00:00
* Copyright ( C ) 2009 - 2018 Lightbend Inc . < https : //www.lightbend.com>
2011-06-07 06:36:21 +05:30
*/
2017-08-08 06:15:18 -05:00
import java.io. { ByteArrayInputStream , ByteArrayOutputStream , NotSerializableException , ObjectOutputStream }
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
2017-02-16 14:09:04 +01:00
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
2017-02-16 14:09:04 +01:00
import akka.annotation.InternalApi
import akka.event. { LogMarker , Logging }
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 scala.util.DynamicVariable
2017-02-16 14:09:04 +01:00
import scala.util.control.NoStackTrace
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 .
2017-02-25 10:17:18 -05:00
* Values from 0 to 40 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
*/
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
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
*/
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
2012-02-10 12:45:22 +01:00
final def fromBinary ( bytes : Array [ Byte ] , clazz : Class [ _ ] ) : AnyRef = fromBinary ( bytes , Option ( clazz ) )
2011-12-30 22:00:49 +01:00
}
2018-04-12 19:58:13 +03:00
object Serializers {
// NOTE!!! If you change this method it is likely that DaemonMsgCreateSerializer.serialize needs the changes too.
def manifestFor ( s : Serializer , message : AnyRef ) : String = s match {
case s2 : SerializerWithStringManifest ⇒ s2 . manifest ( message )
case _ ⇒ if ( s . includeManifest ) message . getClass . getName else ""
}
}
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 .
2017-02-25 10:17:18 -05:00
* Values from 0 to 40 are reserved for Akka internal usage .
2015-05-28 18:42:22 +02:00
*/
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
*/
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
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 ( )
2017-03-13 17:49:45 +01:00
* val bytes = new Array [ Byte ] ( buf . remaining )
2016-05-26 11:58:13 +02:00
* 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 .
*/
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
2016-05-26 11:58:13 +02:00
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 .
*/
2017-02-16 14:09:04 +01:00
final val SerializationIdentifiers = BaseSerializer . SerializationIdentifiers
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
*/
2017-02-16 14:09:04 +01:00
@InternalApi
2015-04-30 09:23:18 +02:00
private [ akka ] def identifierFromConfig : Int =
2017-02-16 14:09:04 +01:00
BaseSerializer . identifierFromConfig ( getClass , system )
}
object BaseSerializer {
/* *
* 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"
/* * INTERNAL API */
@InternalApi
private [ akka ] def identifierFromConfig ( clazz : Class [ _ ] , system : ExtendedActorSystem ) : Int =
system . settings . config . getInt ( s""" ${ SerializationIdentifiers } . " ${ clazz . getName } " """ )
2015-03-05 11:55:05 -06:00
}
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 {
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
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 {
2017-02-16 14:09:04 +01:00
if ( ! system . settings . AllowJavaSerialization )
throw new DisabledJavaSerializer . JavaSerializationException ( "Attempted creation of `JavaSerializer` while `akka.actor.allow-java-serialization = off` was set!" )
2011-07-19 14:20:18 +02:00
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
}
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
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
}
}
2017-02-16 14:09:04 +01:00
/* *
* This Serializer is used when `akka.actor.java-serialization = off`
*/
final case class DisabledJavaSerializer ( system : ExtendedActorSystem ) extends Serializer with ByteBufferSerializer {
import DisabledJavaSerializer._
// use same identifier as JavaSerializer, since it's a replacement
override val identifier : Int = BaseSerializer . identifierFromConfig ( classOf [ JavaSerializer ] , system )
private [ this ] val empty = Array . empty [ Byte ]
private [ this ] val log = Logging . withMarker ( system , getClass )
def includeManifest : Boolean = false
override def toBinary ( o : AnyRef , buf : ByteBuffer ) : Unit = {
log . warning ( LogMarker . Security , "Outgoing message attempted to use Java Serialization even though `akka.actor.allow-java-serialization = off` was set! " +
"Message type was: [{}]" , o . getClass )
throw IllegalSerialization
}
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
2017-02-16 14:09:04 +01:00
override def fromBinary ( bytes : Array [ Byte ] , clazz : Option [ Class [ _ ] ] ) : AnyRef = {
2017-06-14 03:27:33 -04:00
log . warning ( LogMarker . Security , "Incoming message attempted to use Java Serialization even though `akka.actor.allow-java-serialization = off` was set!" )
2017-02-16 14:09:04 +01:00
throw IllegalDeserialization
}
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
2017-02-16 14:09:04 +01:00
override def fromBinary ( buf : ByteBuffer , manifest : String ) : AnyRef = {
2017-06-14 03:27:33 -04:00
// we don't capture the manifest or mention it in the log as the default setting for includeManifest is set to false.
log . warning ( LogMarker . Security , "Incoming message attempted to use Java Serialization even though `akka.actor.allow-java-serialization = off` was set!" )
throw IllegalDeserialization
2017-02-16 14:09:04 +01:00
}
override def toBinary ( o : AnyRef ) : Array [ Byte ] = {
toBinary ( o , null )
empty // won't return, toBinary throws
}
}
object DisabledJavaSerializer {
final class JavaSerializationException ( msg : String ) extends RuntimeException ( msg ) with NoStackTrace
final val IllegalSerialization = new JavaSerializationException ( "Attempted to serialize message using Java serialization while `akka.actor.allow-java-serialization` was disabled. Check WARNING logs for more details." )
final val IllegalDeserialization = new JavaSerializationException ( "Attempted to deserialize message using Java serialization while `akka.actor.allow-java-serialization` was disabled. Check WARNING logs for more details." )
}
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
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
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
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
}
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
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 } ] " )
}
2017-08-08 06:15:18 -05:00
@throws ( classOf [ NotSerializableException ] )
2016-05-26 11:58:13 +02:00
override def fromBinary ( buf : ByteBuffer , manifest : String ) : AnyRef = {
2017-03-13 17:49:45 +01:00
val bytes = new Array [ Byte ] ( buf . remaining ( ) )
2016-05-26 11:58:13 +02:00
buf . get ( bytes )
bytes
}
2012-09-27 00:59:33 +02:00
}