codeconsole opened a new pull request, #3198:
URL: https://github.com/apache/groovy/pull/3198
A `memoize()` closure stores a null result in its cache as the private
place-holder `Memoize.MemoizeNullValue`. That class is not `Serializable`, so
the memoized closure cannot be serialized once it has cached a null:
```groovy
def m = { x -> null }.dehydrate().memoize()
m(1)
new ByteArrayOutputStream().withObjectOutputStream { it.writeObject(m) }
// java.io.NotSerializableException:
org.codehaus.groovy.runtime.memoize.Memoize$MemoizeNullValue
```
Seen in 4.0.33, 5.0.8 and 6.0.0 too.
`MemoizeNullValue` now implements `Serializable`. That alone is not enough:
`MemoizeFunction.call` compares a cached value with the `MEMOIZE_NULL`
singleton by identity, so a deserialized copy would come back from the cache as
the place-holder object rather than null. `MemoizeNullValue.readResolve`
therefore returns the singleton.
With #3195 (GROOVY-12674), which makes `memoizeAtMost` closures serializable
with their entries, this also keeps a cached null there; the soft-reference
variants drop their cache on serialization under #3195 and are not affected.
Merges cleanly with #3190, #3194 and #3195.
## Tests
`MemoizeTest.testCachedNullResultSurvivesSerialization` round-trips a
memoized closure that has cached a null and checks that the copy returns null
for the cached argument without calling the wrapped closure again. It fails
without the change with the `NotSerializableException`, and fails with the
place-holder returned instead of null when only `readResolve` is left out.
`org.codehaus.groovy.runtime.memoize.*`, `groovy.lang.*Closure*`,
`groovy.*Memoize*` and `org.codehaus.groovy.transform.Memoized*` pass. The
Checkstyle and CodeNarc gates pass.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]