Class AcrossJVMSerializationFeature
- java.lang.Object
-
- org.powermock.api.mockito.repackaged.AcrossJVMSerializationFeature
-
- All Implemented Interfaces:
java.io.Serializable
@Incubating class AcrossJVMSerializationFeature extends java.lang.Object implements java.io.SerializableThis is responsible for serializing a mock, it is enabled if the mock is implementingSerializable.The way it works is to enable serialization via the
enableSerializationAcrossJVM(MockCreationSettings), if the mock settings is set to be serializable it will add theAcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializableinterface. This interface defines a theAcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable.writeReplace()whose signature match the one that is looked by the standard Java serialization.Then in the
MethodInterceptorFilterof mockito, if thewriteReplacemethod is called, it will use the custom implementation of this classwriteReplace(Object). This method has a specific knowledge on how to serialize a mockito mock that is based on CGLIB.Only one instance per mock! See
TODO use a proper way to add the interface TODO offer a way to disable completely this behavior, or maybe enable this behavior only with a specific setting TODO check the class is mockable in the deserialization sideMethodInterceptorFilter- Since:
- 1.10.0
- See Also:
CglibMockMaker,MethodInterceptorFilter
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interfaceAcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializableSimple interface that hold a correctwriteReplacesignature that can be seen by anObjectOutputStream.static classAcrossJVMSerializationFeature.AcrossJVMMockSerializationProxyThis is the serialization proxy that will encapsulate the real mock data as a byte array.static classAcrossJVMSerializationFeature.MockitoMockObjectInputStreamSpecial Mockito awareObjectInputStreamthat will resolve the Mockito proxy class.private static classAcrossJVMSerializationFeature.MockitoMockObjectOutputStreamSpecial Mockito awareObjectOutputStream.
-
Field Summary
Fields Modifier and Type Field Description private booleaninstanceLocalCurrentlySerializingFlagprivate static java.lang.StringMOCKITO_PROXY_MARKERprivate java.util.concurrent.locks.Lockmutexprivate static longserialVersionUID
-
Constructor Summary
Constructors Constructor Description AcrossJVMSerializationFeature()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description <T> voidenableSerializationAcrossJVM(org.mockito.mock.MockCreationSettings<T> settings)Enable serialization serialization that will work across classloaders / and JVM.booleanisWriteReplace(java.lang.reflect.Method method)private booleanmockIsCurrentlyBeingReplaced()private voidmockReplacementCompleted()private voidmockReplacementStarted()java.lang.ObjectwriteReplace(java.lang.Object mockitoMock)Custom implementation of thewriteReplacemethod 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
-
isWriteReplace
public boolean isWriteReplace(java.lang.reflect.Method method)
-
writeReplace
public java.lang.Object writeReplace(java.lang.Object mockitoMock) throws java.io.ObjectStreamExceptionCustom implementation of thewriteReplacemethod 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 :
So,objectOutputStream.writeObject(mock);ObjectOutputStreamwill track thewriteReplacemethod 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 anAcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy. -
Now, in the constructor
AcrossJVMMockSerializationProxy(Object)the mock is being serialized in a custom way (usingAcrossJVMSerializationFeature.MockitoMockObjectOutputStream) to a byte array. So basically it means the code is performing double nested serialization of the passedmockitoMock.However the
ObjectOutputStreamwill still detect the customwriteReplaceand execute it. (For that matter disabling replacement viaObjectOutputStream.enableReplaceObject(boolean)doesn't disable thewriteReplacecall, but just just toggle replacement in the written stream,writeReplaceis 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 (
AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy) to be serialized by the calling ObjectOutputStream. - Throws:
java.io.ObjectStreamException
-
-
mockReplacementCompleted
private void mockReplacementCompleted()
-
mockReplacementStarted
private void mockReplacementStarted()
-
mockIsCurrentlyBeingReplaced
private boolean mockIsCurrentlyBeingReplaced()
-
enableSerializationAcrossJVM
public <T> void enableSerializationAcrossJVM(org.mockito.mock.MockCreationSettings<T> settings)
Enable serialization serialization that will work across classloaders / and JVM.Only enable if settings says the mock should be serializable. In this case add the
AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializableto the extra interface list.- Type Parameters:
T- Type param to not be bothered by the generics- Parameters:
settings- Mock creation settings.
-
-