public Object writeReplace(Object mockitoMock) throws ObjectStreamException {
        // reentrant lock for critical section. could it be improved ?
        mutex.lock();
        try {
            // mark started flag // per thread, not per instance
            // temporary loosy hack to avoid stackoverflow
            if (mockIsCurrentlyBeingReplaced()) {
                return mockitoMock;
            }
            mockReplacementStarted();

            return new CrossClassLoaderSerializationProxy(mockitoMock);
        } catch (IOException ioe) {
            MockName mockName = MockUtil.getMockName(mockitoMock);
            String mockedType = MockUtil.getMockSettings(mockitoMock).getTypeToMock().getCanonicalName();
            throw new MockitoSerializationIssue(join(
                    "The mock '" + mockName + "' of type '" + mockedType + "'",
                    "The Java Standard Serialization reported an '" + ioe.getClass().getSimpleName() + "' saying :",
                    "  " + ioe.getMessage()
            ), ioe);
        } finally {
            // unmark
            mockReplacementCompleted();
            mutex.unlock();
        }
    }
public Object writeReplace ( Object mockitoMock ) throws ObjectStreamException { mutex . lock ( ) ; try { if ( mockIsCurrentlyBeingReplaced ( ) ) { return mockitoMock ; } mockReplacementStarted ( ) ; return new CrossClassLoaderSerializationProxy ( mockitoMock ) ; } catch ( IOException ioe ) { MockName mockName = MockUtil . getMockName ( mockitoMock ) ; String mockedType = MockUtil . getMockSettings ( mockitoMock ) . getTypeToMock ( ) . getCanonicalName ( ) ; throw new MockitoSerializationIssue ( join ( "The mock '" + mockName + "' of type '" + mockedType + "'" , "The Java Standard Serialization reported an '" + ioe . getClass ( ) . getSimpleName ( ) + "' saying :" , "  " + ioe . getMessage ( ) ) , ioe ) ; } finally { mockReplacementCompleted ( ) ; mutex . unlock ( ) ; } }
Custom implementation of the <code>writeReplace</code> method for serialization.
<p/>
Here's how it's working and why :
<ol>

<li>
<p>When first entering in this method, it's because some is serializing the mock, with some code like :</p>

<pre class="code"><code class="java">
objectOutputStream.writeObject(mock);
</code></pre>

<p>So, {@link ObjectOutputStream} will track the <code>writeReplace</code> 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 an
{@link CrossClassLoaderSerializableMock}.</p>
</li>
<li>
<p>Now, in the constructor
{@link CrossClassLoaderSerializationProxy#CrossClassLoaderSerializationProxy(java.lang.Object)}
the mock is being serialized in a custom way (using {@link MockitoMockObjectOutputStream}) to a
byte array. So basically it means the code is performing double nested serialization of the passed
<code>mockitoMock</code>.</p>

<p>However the <code>ObjectOutputStream</code> will still detect the custom
<code>writeReplace</code> and execute it.
<em>(For that matter disabling replacement via {@link ObjectOutputStream#enableReplaceObject(boolean)}
doesn't disable the <code>writeReplace</code> call, but just just toggle replacement in the
written stream, <strong><code>writeReplace</code> is always called by
<code>ObjectOutputStream</code></strong>.)</em></p>

<p>In order to avoid this recursion, obviously leading to a {@link StackOverflowError}, this method is using
a flag that marks the mock as already being replaced, and then shouldn't replace itself again.
<strong>This flag is local to this class</strong>, which means the flag of this class unfortunately needs
to be protected against concurrent access, hence the reentrant lock.</p>
</li>
</ol>

@param mockitoMock The Mockito mock to be serialized.
@return A wrapper ({@link CrossClassLoaderSerializationProxy}) to be serialized by the calling ObjectOutputStream.
@throws java.io.ObjectStreamException