diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,12 @@
 ### Removed
 ### Changed
 
+## [0.10.0] - 2020-11-30
+
+### Changed
+
+* Support building with jni-0.8
+
 ## [0.9.1] - 2020-07-16
 
 ### Changed
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # inline-java: Call any JVM function from Haskell
 
 [![CircleCI](https://circleci.com/gh/tweag/inline-java.svg?style=svg)](https://circleci.com/gh/tweag/inline-java)
-[![Build status](https://badge.buildkite.com/143d77b1eec06bb865d694dbe685f2ed7712caa12852c8808e.svg)](https://buildkite.com/tweag-1/inline-java)
+[![Build status](https://badge.buildkite.com/143d77b1eec06bb865d694dbe685f2ed7712caa12852c8808e.svg?branch=master)](https://buildkite.com/tweag-1/inline-java)
 
 The Haskell standard includes a native foreign function interface
 (FFI). Using it can be a bit involved and only C support is
@@ -74,7 +74,7 @@
 
 ## Building the safe interface
 
-There is [an experimental interface][safe-interface] which catches
+There is [an experimental interface][safe-inline-java] which catches
 common memory management mistakes at compile time. This interface
 currently needs a [fork][linear-types-ghc] of GHC which supports the
 [LinearTypes][linear-types-proposal] language extension. Both the GHC
@@ -101,8 +101,12 @@
 If you want to know more about how it is implemented, look at
 [our post][inline-java-plugin] on the plugin implementation.
 
+There is also a post which gives an overview of the
+[safe interface][safe-interface-post].
+
 [inline-java-tutorial]: https://www.tweag.io/posts/2017-09-15-inline-java-tutorial.html
 [inline-java-plugin]: https://www.tweag.io/posts/2017-09-22-inline-java-ghc-plugin.html
+[safe-interface-post]: https://www.tweag.io/blog/2020-02-06-safe-inline-java
 
 ## Debugging
 
@@ -114,6 +118,76 @@
 If `-ddump-to-file` is in effect (as when using `stack`), the java code
 is dumped to `<module>.dump-java` instead.
 
+## Troubleshooting
+
+### Build-time error `package or class Blah does not exist`
+
+`inline-java` is going to invoke the `javac` compiler, and any classes
+used in `java` quotations need to be reachable via the `CLASSPATH`
+environment variable. For instance,
+```
+CLASSPATH=/path/to/my.jar:/some/other/path ghc --make program.hs
+```
+
+### Run-time error `ThreadNotAttached`
+
+Haskell threads need to be attached to the JVM before making JNI calls.
+`Foreign.JNI.withJVM` attaches the calling thread, and other threads
+can be attached with `Foreign.JNI.runInAttachedThread`. When the JVM
+calls into Haskell, the thread is already attached.
+
+### Run-time error `ThreadNotBound`
+
+JNI calls need to be done from bound threads. The thread invoking the
+`main` function of a program is bound. Threads created with `forkOS`
+are bound. In other threads, `Control.Concurrent.runInBoundThread`
+can be used to run a computation in a bound thread.
+
+### Run-time error `java.lang.NoClassDefFoundError`
+
+Classes might not be found at runtime if they are not in a folder or
+jar listed in the parameter `-Djava.class.path=<classpath>` passed
+to `withJVM`.
+
+```Haskell
+withJVM ["-Djava.class.path=/path/to/my.jar:/some/other/path"] $ do
+  ...
+```
+
+Additionally, classes might not be found if a thread other than the one
+calling `main` is trying to use them. One solution is to have the thread
+calling `main` load all the classes in advance. Then the classes will
+be available in the JVM for other threads that need them.
+Calling `Language.Java.Inline.loadJavaWrappers` will have the effect of
+loading all classes needed for `java` quotations, which will suffice in
+many cases.
+
+Another option is to set the context class loader of other threads,
+so they earn the ability to load classes on their own. This might
+work when the thread was attached to the JVM via the JNI, and
+the context class loader is just `null`.
+
+```Haskell
+loader <- [java| Thread.currentThread().getContextClassLoader() |]
+...
+forkOS $ runInAttachedThread $ do
+  [java| { Thread.currentThread().setContextClassLoader($loader); } |]
+  ...
+```
+
+### Run-time error `JVMException`
+
+Any java exception that goes from Java to Haskell will be wrapped
+as a value of type `JVMException` with a reference to the Java object
+representing the exception. The message and the stack trace of the
+exception can be retrieved from the exception object with more JNI
+calls, e.g.
+
+```Haskell
+\(JVMException e) -> [java| { $e.printStackTrace(); } |]
+```
+or with `JNI.Foreign.showException`.
+
 ## License
 
 Copyright (c) 2015-2016 EURL Tweag.
@@ -126,7 +200,7 @@
 ## Sponsors
 
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-[<img src="http://i.imgur.com/0HK8X4y.png" height="65">](http://tweag.io)
+[![Tweag I/O](http://i.imgur.com/0HK8X4y.png)](http://tweag.io)
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 [![LeapYear](http://i.imgur.com/t9VxRHn.png)](http://leapyear.io)
 
diff --git a/inline-java.cabal b/inline-java.cabal
--- a/inline-java.cabal
+++ b/inline-java.cabal
@@ -1,5 +1,5 @@
 name:                inline-java
-version:             0.9.1
+version:             0.10.0
 synopsis:            Java interop via inline Java code in Haskell modules.
 description:         Please see README.md.
 homepage:            http://github.com/tweag/inline-java#readme
@@ -56,8 +56,8 @@
     directory >=1.2,
     filepath >=1,
     ghc >=8.10.1 && <=8.11,
-    jni >=0.7 && <0.8,
-    jvm >=0.5 && <0.6,
+    jni >=0.8 && <0.9,
+    jvm >=0.6 && <0.7,
     language-java >=0.2,
     mtl >=2.2.1,
     process >=1.2,
@@ -90,8 +90,12 @@
     jvm,
     hspec,
     inline-java,
-    text
+    QuickCheck,
+    quickcheck-unicode,
+    text,
+    vector
   default-language: Haskell2010
+  ghc-options: -threaded
   cpp-options: -DHSPEC_DISCOVER=hspec-discover
   if flag(linear-types)
     hs-source-dirs: tests/linear-types
diff --git a/tests/common/Language/Java/InlineSpec.hs b/tests/common/Language/Java/InlineSpec.hs
--- a/tests/common/Language/Java/InlineSpec.hs
+++ b/tests/common/Language/Java/InlineSpec.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE ExplicitNamespaces #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TemplateHaskell #-}
@@ -9,11 +10,18 @@
 
 module Language.Java.InlineSpec(spec) where
 
+import Data.Char
 import Data.Int
+import qualified Data.Text as Text
+import qualified Data.Vector.Storable as Vector
+import Data.Vector.Storable.Mutable (IOVector)
 import Foreign.JNI (JVMException)
 import Language.Java
 import Language.Java.Inline
 import Test.Hspec
+import Test.Hspec.QuickCheck
+import Test.QuickCheck
+import Test.QuickCheck.Unicode
 
 type ObjectClass = 'Class "java.lang.Object"
 type ListClass = 'Iface "java.util.List"
@@ -122,3 +130,20 @@
           st :: J ('Class "java.lang.Thread$State") <-
             [java| Thread.State.NEW |]
           [java| $st == Thread.State.NEW |] `shouldReturn` True
+
+      it "Supports modified utf-8 encoding from Haskell to Java" $
+          withLocalRef (reflect ("a\NULb" :: Text.Text)) $ \jString ->
+            [java| "a\0b".equals($jString) |] `shouldReturn` True
+
+      it "Supports modified utf-8 encoding from Java to Haskell" $ do
+          withLocalRef [java| "a\0b" |] reify `shouldReturn` ("a\NULb" :: Text.Text)
+
+      prop "Processes Unicode code points as the JVM does" $ do
+        \u -> ioProperty $ do
+          let chars :: [Char] = fromUnicode u
+          let text = Text.pack chars
+          codePoints :: IOVector Int32 <- Vector.thaw $ Vector.fromList $ map (fromIntegral . ord) chars
+          withLocalRef (reflect codePoints) $ \jPoints -> do
+            jString <- [java| new String($jPoints, 0, $jPoints.length) |]
+            jText <- reify jString
+            return $ jText === text
diff --git a/tests/common/Main.hs b/tests/common/Main.hs
--- a/tests/common/Main.hs
+++ b/tests/common/Main.hs
@@ -1,11 +1,13 @@
 module Main where
 
-import Language.Java (withJVM)
+import Control.Concurrent (runInBoundThread)
+import Foreign.JNI
 import qualified SafeSpec
 import qualified Spec
 import Test.Hspec
 
 main :: IO ()
-main = withJVM [] $ hspec $ do
-    Spec.spec
-    SafeSpec.spec
+main = withJVM [] $ hspec $
+    around_ (runInBoundThread . runInAttachedThread) $ do
+      Spec.spec
+      SafeSpec.spec
