Class ByteBuddyCrossClassLoaderSerializationSupport
- java.lang.Object
-
- org.mockito.internal.creation.bytebuddy.ByteBuddyCrossClassLoaderSerializationSupport
-
- All Implemented Interfaces:
java.io.Serializable
@Incubating class ByteBuddyCrossClassLoaderSerializationSupport extends java.lang.Object implements java.io.Serializable
This is responsible for serializing a mock, it is enabled if the mock is implementingSerializable
.The way it works is to enable serialization with mode
SerializableMode.ACROSS_CLASSLOADERS
, if the mock settings is set to be serializable the mock engine will implement theByteBuddyCrossClassLoaderSerializationSupport.CrossClassLoaderSerializableMock
marker interface. This interface defines a theByteBuddyCrossClassLoaderSerializationSupport.CrossClassLoaderSerializableMock.writeReplace()
whose signature match the one that is looked by the standard Java serialization.Then in the proxy class there will be a generated
writeReplace
that will delegate toMockMethodInterceptor.ForWriteReplace.doWriteReplace(MockAccess)
of mockito, and in turn will delegate to the custom implementation of this classwriteReplace(Object)
. This method has a specific knowledge on how to serialize a mockito mock that is based on ByteBuddy and will ignore other Mockito MockMakers.Only one instance per mock! See
TODO check the class is mockable in the deserialization sideMockMethodInterceptor
- Since:
- 1.10.0
- See Also:
SubclassByteBuddyMockMaker
,MockMethodInterceptor
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
ByteBuddyCrossClassLoaderSerializationSupport.CrossClassLoaderSerializableMock
Simple interface that hold a correctwriteReplace
signature that can be seen by anObjectOutputStream
.static class
ByteBuddyCrossClassLoaderSerializationSupport.CrossClassLoaderSerializationProxy
This is the serialization proxy that will encapsulate the real mock data as a byte array.static class
ByteBuddyCrossClassLoaderSerializationSupport.MockitoMockObjectInputStream
Special Mockito awareObjectInputStream
that will resolve the Mockito proxy class.private static class
ByteBuddyCrossClassLoaderSerializationSupport.MockitoMockObjectOutputStream
Special Mockito awareObjectOutputStream
.
-
Field Summary
Fields Modifier and Type Field Description private boolean
instanceLocalCurrentlySerializingFlag
private static java.lang.String
MOCKITO_PROXY_MARKER
private java.util.concurrent.locks.Lock
mutex
private static long
serialVersionUID
-
Constructor Summary
Constructors Constructor Description ByteBuddyCrossClassLoaderSerializationSupport()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description private boolean
mockIsCurrentlyBeingReplaced()
private void
mockReplacementCompleted()
private void
mockReplacementStarted()
java.lang.Object
writeReplace(java.lang.Object mockitoMock)
Custom implementation of thewriteReplace
method for serialization.
-
-
-
Field Detail
-
serialVersionUID
private static final long serialVersionUID
- See Also:
- Constant Field Values
-
MOCKITO_PROXY_MARKER
private static final java.lang.String MOCKITO_PROXY_MARKER
- See Also:
- Constant Field Values
-
instanceLocalCurrentlySerializingFlag
private boolean instanceLocalCurrentlySerializingFlag
-
mutex
private final java.util.concurrent.locks.Lock mutex
-
-
Method Detail
-
writeReplace
public java.lang.Object writeReplace(java.lang.Object mockitoMock) throws java.io.ObjectStreamException
Custom implementation of thewriteReplace
method for serialization. Here's how it's working and why :-
When first entering in this method, it's because some is serializing the mock, with some code like :
objectOutputStream.writeObject(mock);
So,
ObjectOutputStream
will track thewriteReplace
method in the instance and execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock. At this point, the code will return anByteBuddyCrossClassLoaderSerializationSupport.CrossClassLoaderSerializableMock
. -
Now, in the constructor
CrossClassLoaderSerializationProxy(java.lang.Object)
the mock is being serialized in a custom way (usingByteBuddyCrossClassLoaderSerializationSupport.MockitoMockObjectOutputStream
) to a byte array. So basically it means the code is performing double nested serialization of the passedmockitoMock
.However the
ObjectOutputStream
will still detect the customwriteReplace
and execute it. (For that matter disabling replacement viaObjectOutputStream.enableReplaceObject(boolean)
doesn't disable thewriteReplace
call, but just just toggle replacement in the written stream,writeReplace
is always called byObjectOutputStream
.)In order to avoid this recursion, obviously leading to a
StackOverflowError
, this method is using a flag that marks the mock as already being replaced, and then shouldn't replace itself again. This flag is local to this class, which means the flag of this class unfortunately needs to be protected against concurrent access, hence the reentrant lock.
- Parameters:
mockitoMock
- The Mockito mock to be serialized.- Returns:
- A wrapper (
ByteBuddyCrossClassLoaderSerializationSupport.CrossClassLoaderSerializationProxy
) to be serialized by the calling ObjectOutputStream. - Throws:
java.io.ObjectStreamException
-
-
mockReplacementCompleted
private void mockReplacementCompleted()
-
mockReplacementStarted
private void mockReplacementStarted()
-
mockIsCurrentlyBeingReplaced
private boolean mockIsCurrentlyBeingReplaced()
-
-