Repository: mockito/mockito
Issue: Mockito not able to be built with OracleJDK8u181-b13
Labels: bug
java-8
java-10
build

Oracle has released [JDK8u181-b13](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) today. I tried to build Mockito with JDK8u181 but some of the Mockito unit tests failed at the build.

```
org.mockitousage.basicapi.MocksSerializationForAnnotationTest > should_serialize_object_mock FAILED
    java.io.InvalidClassException: org.mockito.internal.matchers.Any$MockitoMock$1346699744; no valid constructor
        at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169)
        at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:874)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2043)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:27)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:23)
        at org.mockitousage.basicapi.MocksSerializationForAnnotationTest.should_serialize_object_mock(MocksSerializationForAnnotationTest.java:277)

org.mockitousage.basicapi.MocksSerializationForAnnotationTest > should_serialize_real_partial_mock FAILED
    java.io.InvalidClassException: org.mockito.internal.matchers.Any$MockitoMock$122170722; no valid constructor
        at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169)
        at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:874)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2043)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:27)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:23)
        at org.mockitousage.basicapi.MocksSerializationForAnnotationTest.should_serialize_real_partial_mock(MocksSerializationForAnnotationTest.java:289)

org.mockitousage.basicapi.MocksSerializationForAnnotationTest > should_serialization_work FAILED
    java.io.InvalidClassException: org.mockito.internal.matchers.Any$MockitoMock$1346699744; no valid constructor
        at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169)
        at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:874)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2043)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:27)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:23)
        at org.mockitoutil.SimpleSerializationUtil.serializeAndBack(SimpleSerializationUtil.java:17)
        at org.mockitousage.basicapi.MocksSerializationForAnnotationTest.should_serialization_work(MocksSerializationForAnnotationTest.java:176)

org.mockitousage.basicapi.MocksSerializationTest > should_serialize_object_mock FAILED
    java.io.InvalidClassException: org.mockito.internal.matchers.Any$MockitoMock$1346699744; no valid constructor
        at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169)
        at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:874)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2043)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:27)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:23)
        at org.mockitousage.basicapi.MocksSerializationTest.should_serialize_object_mock(MocksSerializationTest.java:302)

org.mockitousage.basicapi.MocksSerializationTest > should_serialize_real_partial_mock FAILED
    java.io.InvalidClassException: org.mockito.internal.matchers.Any$MockitoMock$122170722; no valid constructor
        at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:169)
        at java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:874)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2043)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:27)
        at org.mockitoutil.SimpleSerializationUtil.deserializeMock(SimpleSerializationUtil.java:23)
        at org.mockitousage.basicapi.MocksSerializationTest.should_serialize_real_partial_mock(MocksSerializationTest.java:315)

1888 tests completed, 5 failed, 47 skipped

```

I roughly looked at the cause of the failure and found that `org.mockito.internal.matchers.Any` class has a private constructor. In [Oracle doc for Serializable interface](https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html), it states:

> During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.

This could be the cause of the issue when `Any.class` is mocked by `deserializeMock`.


Java version:

```
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
```

The problem is reproducible by setting OracleJDK8u181 as JAVA_HOME and run `./gradlew build` in Mockito root.



Issue comments:
Interesting. Thanks for the bug report.

I noticed a change  in serialization in the release notes (http://www.oracle.com/technetwork/java/javase/8u181-relnotes-4479407.html) yesterday.

> core-libs/java.io:serialization
> ➜ Better stack walking
> New access checks have been added during the object creation phase of deserialization. This should not affect ordinary uses of deserialization. However, reflective frameworks that make use of JDK-internal APIs may be impacted. The new checks can be disabled if necessary by setting the system property jdk.disableSerialConstructorChecks to the value "true". This must be done by adding the argument -Djdk.disableSerialConstructorChecks=true to the Java command line.
>
> JDK-8197925 (not public)

I'll verify that asap.


-- Brice
Misplet on my phone



I'm looking into it right now. Thank you for reporting!

Our JDK10 build has been exposed: https://travis-ci.org/mockito/mockito/jobs/405198762
I confirm that disabling the constructor checks works. Running the tests with the following properties make them pass. 

```diff
diff --git i/build.gradle w/build.gradle
index b47d86bbf..da61d692e 100644
--- i/build.gradle
+++ w/build.gradle
@@ -91,6 +91,10 @@ task wrapper(type: Wrapper) {
     gradleVersion = '4.7'
 }

+test {
+    systemProperty "jdk.disableSerialConstructorChecks", "true"
+}
+
 //Posting Build scans to https://scans.gradle.com
 buildScan {
     licenseAgreementUrl = 'https://gradle.com/terms-of-service'
```

It seems that remove the `Any` constructor did the trick. 

```diff
diff --git i/src/main/java/org/mockito/internal/matchers/Any.java w/src/main/java/org/mockito/internal/matchers/Any.java
index f9f0069bd..ad4cca35a 100644
--- i/src/main/java/org/mockito/internal/matchers/Any.java
+++ w/src/main/java/org/mockito/internal/matchers/Any.java
@@ -13,8 +13,8 @@ public class Any implements ArgumentMatcher<Object>, VarargMatcher ,Serializable

     public static final Any ANY = new Any();

-    private Any() {
-    }
+    // private Any() {
+    // }

     public boolean matches(Object actual) {
         return true;
```

However I suspect that user tests relying on mocks of an object with private no-arg constructor that is serialized using `ObjectInputStream` maybe have to declare this system property. Although it seems like an edgy case.
Created PR to fix this problem: #1433
Fixed on master :tada:
@mockitoguy can you make a patch release to maven central for this?
@TimvdLippe the fix in #1433 only affects mockito's build

Mockito users will see the same errors in their build if they are in the same conditions.
@mockitoguy 
if you take a look at other classes in matchers directory, eg. Contains.java.
they have similar problem. there's no accessible non-arg constructor

mockito UT doesn't try to serialize them. 


Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/internal/matchers/Any.java b/src/main/java/org/mockito/internal/matchers/Any.java
index f9f0069bd9..58b6404355 100644
--- a/src/main/java/org/mockito/internal/matchers/Any.java
+++ b/src/main/java/org/mockito/internal/matchers/Any.java
@@ -9,13 +9,10 @@
 
 import org.mockito.ArgumentMatcher;
 
-public class Any implements ArgumentMatcher<Object>, VarargMatcher ,Serializable {
+public class Any implements ArgumentMatcher<Object>, VarargMatcher, Serializable {
 
     public static final Any ANY = new Any();
 
-    private Any() {
-    }
-
     public boolean matches(Object actual) {
         return true;
     }


Test patch: