diff --git a/jvm/CHANGELOG.md b/jvm/CHANGELOG.md index 3ad5f7e8..2486c168 100644 --- a/jvm/CHANGELOG.md +++ b/jvm/CHANGELOG.md @@ -22,6 +22,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). * The `Reify`/`Reflect` instances for `()` is now mapped to a *serializable* small JVM object. This is a more useful instance for sparkle users. +* `Reify`/`Reflect` were given an additional invariant. + The result and argument of `reflect` and `reify` shouldn't share any + direct JVM object references. This fixes memory errors in the + instances of `[J ty]`. + [#102](https://github.com/tweag/inline-java/pull/102) ## [0.3.0] - 2017-08-31 diff --git a/jvm/src/Language/Java.hs b/jvm/src/Language/Java.hs index 5fdcab62..fae8fd30 100644 --- a/jvm/src/Language/Java.hs +++ b/jvm/src/Language/Java.hs @@ -469,19 +469,23 @@ class (SingI (Interp a), IsReferenceType (Interp a)) => Interpretation (a :: k) -- say, unmarshall a Java object to a Haskell value. Unlike coercing, in general -- reifying induces allocations and copies. class Interpretation a => Reify a where + -- | Invariant: The result and the argument share no direct JVM object + -- references. reify :: J (Interp a) -> IO a default reify :: (Coercible a, Interp a ~ Ty a) => J (Interp a) -> IO a - reify x = return (unsafeUncoerce (JObject x)) + reify x = unsafeUncoerce . JObject <$> (newLocalRef x :: IO (J (Ty a))) -- | Inject a concrete Haskell value into the space of Java objects. That is to -- say, marshall a Haskell value to a Java object. Unlike coercing, in general -- reflection induces allocations and copies. class Interpretation a => Reflect a where + -- | Invariant: The result and the argument share no direct JVM object + -- references. reflect :: a -> IO (J (Interp a)) default reflect :: (Coercible a, Interp a ~ Ty a) => a -> IO (J (Interp a)) - reflect x = return (jobject x) + reflect x = newLocalRef (jobject x) #if ! (__GLASGOW_HASKELL__ == 800 && __GLASGOW_HASKELL_PATCHLEVEL1__ == 1) reifyMVector