Upgrade jacoco to v0.8.4 am: 9b5f0cebfe am: 12dee3496f
am: 0f0b5ebf86

Change-Id: Ice1512bc21409270a58b7542bce06745db99af6c
diff --git a/.appveyor.yml b/.appveyor.yml
index 7ab0b10..d8efac6 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -11,7 +11,7 @@
 
 build_script:
   # Maven 3.3.9 requires Java >= 7, but generation of Javadocs requires Java <= 6 (https://github.com/jacoco/jacoco/issues/110)
-  - mvn -V -B -e verify -Djdk.version=1.6 --toolchains=.travis\appveyor-toolchains.xml
+  - mvn -V -B -e verify -Djdk.version=6 --toolchains=.travis\appveyor-toolchains.xml
 
 artifacts:
   - path: jacoco\target\*.zip
diff --git a/.travis.sh b/.travis.sh
index abf4f8d..5889236 100755
--- a/.travis.sh
+++ b/.travis.sh
@@ -43,26 +43,31 @@
   fi
 }
 
+# Preinstalled JDKs:
+ls -lA /usr/lib/jvm/
+
+
 case "$JDK" in
 5)
   install_jdk $JDK5_URL false
   ;;
-6)
-  ;;
-7)
-  jdk_switcher /usr/lib/jvm/java-7-openjdk-amd64
-  ;;
-8)
+6 | 7 | 8)
   jdk_switcher /usr/lib/jvm/java-8-oracle
   ;;
-8-ea)
-  install_jdk $JDK8_EA_URL
-  ;;
 9)
-  install_jdk $JDK9_URL
+  jdk_switcher /usr/lib/jvm/java-9-oracle
   ;;
-10-ea)
-  install_jdk $JDK10_EA_URL
+10)
+  install_jdk $JDK10_URL
+  ;;
+11)
+  install_jdk $JDK11_URL
+  ;;
+12)
+  install_jdk $JDK12_URL
+  ;;
+13-ea)
+  install_jdk $JDK13_EA_URL
   ;;
 esac
 
@@ -72,34 +77,33 @@
 export MAVEN_SKIP_RC=true
 
 # Build:
-# TODO(Godin): see https://github.com/jacoco/jacoco/issues/300 about "bytecode.version"
 case "$JDK" in
 5)
   if [[ ${TRAVIS_PULL_REQUEST} == 'false' && ${TRAVIS_BRANCH} == 'master' ]]
   then
+    # Travis does shallow clone, but SonarQube performs "git blame" and so requires full history
+    git fetch --unshallow
+
     # goal "deploy:deploy" used directly instead of "deploy" phase to avoid pollution of Maven repository by "install" phase
-    mvn -V -B -e -f org.jacoco.build verify deploy:deploy -DdeployAtEnd -Djdk.version=1.5 --toolchains=./.travis/toolchains.xml --settings=./.travis/settings.xml -Dsonar.host.url=${SONARQUBE_URL} -Dsonar.login=${SONARQUBE_TOKEN}
+    mvn -V -B -e -f org.jacoco.build verify sonar:sonar deploy:deploy -DdeployAtEnd -Djdk.version=5 --toolchains=./.travis/toolchains.xml --settings=./.travis/settings.xml -Dsonar.host.url=${SONARQUBE_URL} -Dsonar.login=${SONARQUBE_TOKEN}
     python ./.travis/trigger-site-deployment.py
   else
-    mvn -V -B -e verify -Djdk.version=1.5 --toolchains=./.travis/toolchains.xml
+    mvn -V -B -e verify -Djdk.version=5 --toolchains=./.travis/toolchains.xml \
+      --settings=./.travis/settings.xml
   fi
   ;;
-6)
-  mvn -V -B -e verify -Djdk.version=1.6 -Dbytecode.version=1.6 --toolchains=./.travis/travis-toolchains.xml
+6 | 7 | 8 | 9)
+  mvn -V -B -e verify -Djdk.version=${JDK} -Dbytecode.version=${JDK} -Decj=${ECJ:-} --toolchains=./.travis/travis-toolchains.xml \
+    --settings=./.travis/settings.xml
   ;;
-7)
-  mvn -V -B -e verify -Dbytecode.version=1.7
+10 | 11 | 12)
+  mvn -V -B -e verify -Dbytecode.version=${JDK} \
+    --settings=./.travis/settings.xml
   ;;
-8 | 8-ea)
-  mvn -V -B -e verify -Dbytecode.version=1.8 -Decj=${ECJ:-}
-  ;;
-9)
-  export MAVEN_OPTS="-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts"
-  mvn -V -B -e verify -Dbytecode.version=1.9 \
-    -Dinvoker.mavenOpts="-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts"
-  ;;
-10-ea)
-  mvn -V -B -e verify -Dbytecode.version=1.9
+13-ea)
+  mvn -V -B -e verify -Dbytecode.version=13 \
+    --projects \!org.jacoco.core.test.validation.groovy \
+    --settings=./.travis/settings.xml
   ;;
 *)
   echo "Incorrect JDK [$JDK]"
diff --git a/.travis.yml b/.travis.yml
index f62f80e..239d3b2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,13 +23,10 @@
   - JDK=8
   - JDK=8
     ECJ=true
-  - JDK=8-ea
   - JDK=9
-  - JDK=10-ea
-
-matrix:
-  allow_failures:
-    - env: JDK=8-ea
-    - env: JDK=10-ea
+  - JDK=10
+  - JDK=11
+  - JDK=12
+  - JDK=13-ea
 
 script: ./.travis.sh
diff --git a/.travis/appveyor-toolchains.xml b/.travis/appveyor-toolchains.xml
index 6e91e4b..79fae7d 100644
--- a/.travis/appveyor-toolchains.xml
+++ b/.travis/appveyor-toolchains.xml
@@ -1,15 +1,17 @@
 <?xml version="1.0" encoding="UTF8"?>
 <toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/TOOLCHAINS/1.1.0 http://maven.apache.org/xsd/toolchains-1.1.0.xsd">
+
   <toolchain>
     <type>jdk</type>
     <provides>
       <id>java16</id>
-      <version>1.6</version>
+      <version>6</version>
       <vendor>oracle</vendor>
     </provides>
     <configuration>
       <jdkHome>C:\Program Files\Java\jdk1.6.0</jdkHome>
     </configuration>
   </toolchain>
+
 </toolchains>
diff --git a/.travis/toolchains.xml b/.travis/toolchains.xml
index 59383f3..dcf1b8c 100644
--- a/.travis/toolchains.xml
+++ b/.travis/toolchains.xml
@@ -1,15 +1,17 @@
 <?xml version="1.0" encoding="UTF8"?>
 <toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/TOOLCHAINS/1.1.0 http://maven.apache.org/xsd/toolchains-1.1.0.xsd">
+
   <toolchain>
     <type>jdk</type>
     <provides>
       <id>java15</id>
-      <version>1.5</version>
+      <version>5</version>
       <vendor>sun</vendor>
     </provides>
     <configuration>
       <jdkHome>/tmp/jdk/5</jdkHome>
     </configuration>
   </toolchain>
+
 </toolchains>
diff --git a/.travis/travis-toolchains.xml b/.travis/travis-toolchains.xml
index 9eb8100..8079e74 100644
--- a/.travis/travis-toolchains.xml
+++ b/.travis/travis-toolchains.xml
@@ -1,13 +1,45 @@
 <?xml version="1.0" encoding="UTF8"?>
 <toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/TOOLCHAINS/1.1.0 http://maven.apache.org/xsd/toolchains-1.1.0.xsd">
+
   <toolchain>
     <type>jdk</type>
     <provides>
-      <version>1.6</version>
+      <version>6</version>
     </provides>
     <configuration>
       <jdkHome>/usr/lib/jvm/java-6-openjdk-amd64</jdkHome>
     </configuration>
   </toolchain>
+
+  <toolchain>
+    <type>jdk</type>
+    <provides>
+      <version>7</version>
+    </provides>
+    <configuration>
+      <jdkHome>/usr/lib/jvm/java-7-openjdk-amd64</jdkHome>
+    </configuration>
+  </toolchain>
+
+  <toolchain>
+    <type>jdk</type>
+    <provides>
+      <version>8</version>
+    </provides>
+    <configuration>
+      <jdkHome>/usr/lib/jvm/java-8-oracle</jdkHome>
+    </configuration>
+  </toolchain>
+
+  <toolchain>
+    <type>jdk</type>
+    <provides>
+      <version>9</version>
+    </provides>
+    <configuration>
+      <jdkHome>/usr/lib/jvm/java-9-oracle</jdkHome>
+    </configuration>
+  </toolchain>
+
 </toolchains>
diff --git a/Android.bp b/Android.bp
index 396f2db..0689525 100644
--- a/Android.bp
+++ b/Android.bp
@@ -52,9 +52,9 @@
     // TODO(b/69671801): there's no bytecode on the device, so these shouldn't
     // be necessary.
     static_libs: [
-        "asm-6.0",
-        "asm-commons-6.0",
-        "asm-tree-6.0",
+        "asm-7.0",
+        "asm-commons-7.0",
+        "asm-tree-7.0",
     ],
 }
 
@@ -92,9 +92,9 @@
     ],
 
     static_libs: [
-        "asm-6.0",
-        "asm-commons-6.0",
-        "asm-tree-6.0",
+        "asm-7.0",
+        "asm-commons-7.0",
+        "asm-tree-7.0",
         "args4j-2.0.28",
     ],
 
diff --git a/FETCH_HEAD b/FETCH_HEAD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/FETCH_HEAD
diff --git a/LICENSE.md b/LICENSE.md
index a53f7c9..2bb435e 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,7 +1,7 @@
 License
 =======
 
-Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
 
 The JaCoCo Java Code Coverage Library and all included documentation is made
 available by Mountainminds GmbH & Co. KG, Munich. Except indicated below, the
diff --git a/METADATA b/METADATA
index d3e592f..43947c9 100644
--- a/METADATA
+++ b/METADATA
@@ -9,10 +9,10 @@
     type: GIT
     value: "https://github.com/jacoco/jacoco.git"
   }
-  version: "v0.8.0"
+  version: "v0.8.4"
   last_upgrade_date {
-    year: 2018
-    month: 1
-    day: 5
+    year: 2019
+    month: 5
+    day: 13
   }
 }
diff --git a/README.md b/README.md
index c068593..dc7b572 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 
 [![Build Status](https://travis-ci.org/jacoco/jacoco.svg?branch=master)](https://travis-ci.org/jacoco/jacoco)
 [![Build status](https://ci.appveyor.com/api/projects/status/g28egytv4tb898d7/branch/master?svg=true)](https://ci.appveyor.com/project/JaCoCo/jacoco/branch/master)
-[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.jacoco/org.jacoco.core/badge.svg?style=flat)](http://search.maven.org/#search|ga|1|g%3Aorg.jacoco)
+[![Maven Central](https://img.shields.io/maven-central/v/org.jacoco/jacoco.svg)](http://search.maven.org/#search|ga|1|g%3Aorg.jacoco)
 
 JaCoCo is a free Java code coverage library distributed under the Eclipse Public
 License. Check the [project homepage](http://www.jacoco.org/jacoco)
diff --git a/README.version b/README.version
deleted file mode 100644
index 0ef82ce..0000000
--- a/README.version
+++ /dev/null
@@ -1,4 +0,0 @@
-URL: https://github.com/jacoco/jacoco/tree/v0.7.5
-Version: v0.7.5
-BugComponent: 108682
-Owners: shertz
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml b/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml
index 176e5ff..ad27b9a 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-check-fails-halt/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -40,15 +40,13 @@
             </goals>
             <configuration>
               <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <element>CLASS</element>
                   <includes>
                     <include>Example</include>
                   </includes>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>METHOD</counter>
                       <value>MISSEDCOUNT</value>
                       <maximum>0</maximum>
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-halt/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-check-fails-halt/src/main/java/Example.java
index 66496fe..937070a 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-halt/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-check-fails-halt/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-halt/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-check-fails-halt/src/test/java/ExampleTest.java
index b1596f2..2632110 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-halt/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-check-fails-halt/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-halt/verify.bsh b/jacoco-maven-plugin.test/it/it-check-fails-halt/verify.bsh
index eea9e67..987843a 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-halt/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-check-fails-halt/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/pom.xml b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/pom.xml
index 3cafa0f..4979976 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -41,12 +41,10 @@
             <configuration>
               <haltOnFailure>false</haltOnFailure>
              <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <element>BUNDLE</element>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>METHOD</counter>
                       <value>MISSEDCOUNT</value>
                       <maximum>0</maximum>
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/main/java/Example.java
index 66496fe..937070a 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/test/java/ExampleTest.java
index b1596f2..2632110 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/verify.bsh b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/verify.bsh
index bb4a1b4..cad473c 100644
--- a/jacoco-maven-plugin.test/it/it-check-fails-no-halt/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-check-fails-no-halt/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-passes/pom.xml b/jacoco-maven-plugin.test/it/it-check-passes/pom.xml
index 80195ce..233974f 100644
--- a/jacoco-maven-plugin.test/it/it-check-passes/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-check-passes/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -40,18 +40,15 @@
             </goals>
             <configuration>
               <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <element>BUNDLE</element>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>INSTRUCTION</counter>
                       <value>COVEREDRATIO</value>
                       <minimum>0.90</minimum>
                     </limit>
-                    <!-- implmentation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>CLASS</counter>
                       <value>MISSEDCOUNT</value>
                       <maximum>0</maximum>
diff --git a/jacoco-maven-plugin.test/it/it-check-passes/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-check-passes/src/main/java/Example.java
index 66496fe..937070a 100644
--- a/jacoco-maven-plugin.test/it/it-check-passes/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-check-passes/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-passes/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-check-passes/src/test/java/ExampleTest.java
index 80b51cb..598c121 100644
--- a/jacoco-maven-plugin.test/it/it-check-passes/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-check-passes/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-check-passes/verify.bsh b/jacoco-maven-plugin.test/it/it-check-passes/verify.bsh
index 39d6c66..e9bae9b 100644
--- a/jacoco-maven-plugin.test/it/it-check-passes/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-check-passes/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml b/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml
index 579a32c..239ff3d 100644
--- a/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-customize-agent/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-customize-agent/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-customize-agent/src/main/java/Example.java
index a95b591..d264823 100644
--- a/jacoco-maven-plugin.test/it/it-customize-agent/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-customize-agent/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-customize-agent/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-customize-agent/src/test/java/ExampleTest.java
index 5df8f7b..db0af65 100644
--- a/jacoco-maven-plugin.test/it/it-customize-agent/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-customize-agent/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh b/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh
index ec6780a..2962f35 100644
--- a/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-customize-agent/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-dump/pom.xml b/jacoco-maven-plugin.test/it/it-dump/pom.xml
index 8e20991..a954f88 100644
--- a/jacoco-maven-plugin.test/it/it-dump/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-dump/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -50,12 +50,10 @@
             </goals>
             <configuration>
               <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <element>BUNDLE</element>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>CLASS</counter>
                       <value>COVEREDCOUNT</value>
                       <minimum>1</minimum>
diff --git a/jacoco-maven-plugin.test/it/it-dump/src/main/java/Server.java b/jacoco-maven-plugin.test/it/it-dump/src/main/java/Server.java
index fc65ad0..2a22ea0 100644
--- a/jacoco-maven-plugin.test/it/it-dump/src/main/java/Server.java
+++ b/jacoco-maven-plugin.test/it/it-dump/src/main/java/Server.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-dump/verify.bsh b/jacoco-maven-plugin.test/it/it-dump/verify.bsh
index 39d6c66..e9bae9b 100644
--- a/jacoco-maven-plugin.test/it/it-dump/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-dump/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-includes-excludes/pom.xml b/jacoco-maven-plugin.test/it/it-includes-excludes/pom.xml
index 23a7a85..3e5739b 100644
--- a/jacoco-maven-plugin.test/it/it-includes-excludes/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-includes-excludes/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/DatabaseUtil.java b/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/DatabaseUtil.java
index 50d822e..90c30a1 100644
--- a/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/DatabaseUtil.java
+++ b/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/DatabaseUtil.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/FileUtil.java b/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/FileUtil.java
index 5e6da36..b956f16 100644
--- a/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/FileUtil.java
+++ b/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/FileUtil.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/TestUtil.java b/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/TestUtil.java
index 7c1baa2..ace8ec7 100644
--- a/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/TestUtil.java
+++ b/jacoco-maven-plugin.test/it/it-includes-excludes/src/main/java/org/project/TestUtil.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-includes-excludes/src/test/java/org/project/TestDatabaseUtil.java b/jacoco-maven-plugin.test/it/it-includes-excludes/src/test/java/org/project/TestDatabaseUtil.java
index ca6b040..f9a0597 100644
--- a/jacoco-maven-plugin.test/it/it-includes-excludes/src/test/java/org/project/TestDatabaseUtil.java
+++ b/jacoco-maven-plugin.test/it/it-includes-excludes/src/test/java/org/project/TestDatabaseUtil.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-includes-excludes/verify.bsh b/jacoco-maven-plugin.test/it/it-includes-excludes/verify.bsh
index 9117d2c..0dbe84a 100644
--- a/jacoco-maven-plugin.test/it/it-includes-excludes/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-includes-excludes/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/pom.xml b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/pom.xml
index 7e5f878..edcec3d 100644
--- a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/module-info.java b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/module-info.java
index 2b610da..e7f9686 100644
--- a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/module-info.java
+++ b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/module-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/org/example/Example.java b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/org/example/Example.java
index 9c79562..0873a9f 100644
--- a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/org/example/Example.java
+++ b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/main/java/org/example/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/test/java/org/example/ExampleTest.java b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/test/java/org/example/ExampleTest.java
index 9128b4f..d68f5ee 100644
--- a/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/test/java/org/example/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-java9-offline-instrumentation/src/test/java/org/example/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-java9/pom.xml b/jacoco-maven-plugin.test/it/it-java9/pom.xml
index a0511f8..b44bafd 100644
--- a/jacoco-maven-plugin.test/it/it-java9/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-java9/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -28,7 +28,8 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
-          <target>1.9</target>
+          <source>9</source>
+          <target>9</target>
         </configuration>
       </plugin>
       <plugin>
@@ -48,11 +49,9 @@
             </goals>
             <configuration>
               <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>INSTRUCTION</counter>
                       <value>COVEREDCOUNT</value>
                       <minimum>8</minimum>
diff --git a/jacoco-maven-plugin.test/it/it-java9/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-java9/src/main/java/Example.java
index d707a61..2666e56 100644
--- a/jacoco-maven-plugin.test/it/it-java9/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-java9/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-java9/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-java9/src/test/java/ExampleTest.java
index e9a49b4..e49e78d 100644
--- a/jacoco-maven-plugin.test/it/it-java9/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-java9/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-merge/pom.xml b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-merge/pom.xml
index 442d507..74d181d 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-merge/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-merge/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -47,4 +47,4 @@
       </plugin>
     </plugins>
   </build>
-</project>
\ No newline at end of file
+</project>
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/pom.xml b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/pom.xml
index 5a0dc1d..d38548b 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/main/java/Example.java
index 024c02b..beaa588 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/test/java/ExampleTest.java
index eb4f46a..3c86bee 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project1/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/pom.xml b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/pom.xml
index 60cbfe7..fe6b03a 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/main/java/Example.java
index 024c02b..beaa588 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/test/java/ExampleTest.java
index eb4f46a..3c86bee 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/it-merge-passes-project2/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/pom.xml b/jacoco-maven-plugin.test/it/it-merge-passes/pom.xml
index 988e462..1cb4206 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-merge-passes/verify.bsh b/jacoco-maven-plugin.test/it/it-merge-passes/verify.bsh
index dc8f9e2..e237161 100644
--- a/jacoco-maven-plugin.test/it/it-merge-passes/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-merge-passes/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -18,4 +18,4 @@
  }
  if ( buildLog.indexOf( "Writing merged execution data to" ) < 0 ) {
      throw new RuntimeException( "Could not write merged execution data" );
- }
\ No newline at end of file
+ }
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/child-jar-without-sources/pom.xml b/jacoco-maven-plugin.test/it/it-multi-module/child-jar-without-sources/pom.xml
index fafcd8b..fdd3e25 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/child-jar-without-sources/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-multi-module/child-jar-without-sources/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/child/pom.xml b/jacoco-maven-plugin.test/it/it-multi-module/child/pom.xml
index 775ad53..e3c316e 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/child/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-multi-module/child/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/Example.java
index a95b591..d264823 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/somepackage/Example.java b/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/somepackage/Example.java
index 19659af..056c63e 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/somepackage/Example.java
+++ b/jacoco-maven-plugin.test/it/it-multi-module/child/src/main/java/somepackage/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/child/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-multi-module/child/src/test/java/ExampleTest.java
index 5df8f7b..db0af65 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/child/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-multi-module/child/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/pom.xml b/jacoco-maven-plugin.test/it/it-multi-module/pom.xml
index f09ca34..673b046 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-multi-module/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/skip-child/pom.xml b/jacoco-maven-plugin.test/it/it-multi-module/skip-child/pom.xml
index 5ced5b4..b956b2a 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/skip-child/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-multi-module/skip-child/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/skip-child/src/test/ExampleTest.java b/jacoco-maven-plugin.test/it/it-multi-module/skip-child/src/test/ExampleTest.java
index 68f956a..2cfb7c7 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/skip-child/src/test/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-multi-module/skip-child/src/test/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multi-module/verify.bsh b/jacoco-maven-plugin.test/it/it-multi-module/verify.bsh
index b0286a5..1505316 100644
--- a/jacoco-maven-plugin.test/it/it-multi-module/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-multi-module/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multiple-executions/pom.xml b/jacoco-maven-plugin.test/it/it-multiple-executions/pom.xml
index 5455c12..b8b2fd5 100644
--- a/jacoco-maven-plugin.test/it/it-multiple-executions/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-multiple-executions/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multiple-executions/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-multiple-executions/src/main/java/Example.java
index a95b591..d264823 100644
--- a/jacoco-maven-plugin.test/it/it-multiple-executions/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-multiple-executions/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multiple-executions/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-multiple-executions/src/test/java/ExampleTest.java
index 5df8f7b..db0af65 100644
--- a/jacoco-maven-plugin.test/it/it-multiple-executions/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-multiple-executions/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-multiple-executions/verify.bsh b/jacoco-maven-plugin.test/it/it-multiple-executions/verify.bsh
index 1d0efc3..122b0bd 100644
--- a/jacoco-maven-plugin.test/it/it-multiple-executions/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-multiple-executions/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/pom.xml b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/pom.xml
index 6909b6c..34deae5 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/src/test/java/ExampleTest.java
index 68f956a..2cfb7c7 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child-without-main-classes/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/pom.xml b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/pom.xml
index 26b87e5..86c05f1 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/DoNotInstrument.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/DoNotInstrument.java
index da2a53e..5d0a189 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/DoNotInstrument.java
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/DoNotInstrument.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/Example.java
index a95b591..d264823 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/test/java/ExampleTest.java
index 5df8f7b..db0af65 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/child/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/pom.xml b/jacoco-maven-plugin.test/it/it-offline-instrumentation/pom.xml
index 21e283a..54a8d1f 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-offline-instrumentation/verify.bsh b/jacoco-maven-plugin.test/it/it-offline-instrumentation/verify.bsh
index e3ceb84..3cf3787 100644
--- a/jacoco-maven-plugin.test/it/it-offline-instrumentation/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-offline-instrumentation/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-prepend-property-skip/pom.xml b/jacoco-maven-plugin.test/it/it-prepend-property-skip/pom.xml
index 259e630..e3ec74d 100644
--- a/jacoco-maven-plugin.test/it/it-prepend-property-skip/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-prepend-property-skip/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-prepend-property-skip/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-prepend-property-skip/src/test/java/ExampleTest.java
index 079ac52..0349a90 100644
--- a/jacoco-maven-plugin.test/it/it-prepend-property-skip/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-prepend-property-skip/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-prepend-property/pom.xml b/jacoco-maven-plugin.test/it/it-prepend-property/pom.xml
index 70f8018..3c2ee5a 100644
--- a/jacoco-maven-plugin.test/it/it-prepend-property/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-prepend-property/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-prepend-property/verify.bsh b/jacoco-maven-plugin.test/it/it-prepend-property/verify.bsh
index ded48df..1fac651 100644
--- a/jacoco-maven-plugin.test/it/it-prepend-property/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-prepend-property/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/pom.xml
index 2412369..ae63a04 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/main/java/package1/Example1.java b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/main/java/package1/Example1.java
index 29be319..73ace31 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/main/java/package1/Example1.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/main/java/package1/Example1.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/test/java/package1/Example1Test.java b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/test/java/package1/Example1Test.java
index 832d49d..413fe7d 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/test/java/package1/Example1Test.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child1/src/test/java/package1/Example1Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/pom.xml
index 5493fe4..163116c 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/main/java/package2/Example2.java b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/main/java/package2/Example2.java
index 2e2d040..25e2f9c 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/main/java/package2/Example2.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/main/java/package2/Example2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/test/java/package2/Example2Test.java b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/test/java/package2/Example2Test.java
index 21149e2..ef0df80 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/test/java/package2/Example2Test.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/child2/src/test/java/package2/Example2Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/pom.xml
index 64f5d89..96392d1 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/report/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/report/pom.xml
index 05832ce..6e2fa30 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/report/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/report/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/verify.bsh b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/verify.bsh
index 629f0aa..b2835db 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate-customization/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate-customization/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/pom.xml
index 8c07622..d2e70c3 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/src/test/java/package1/Example1bTest.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/src/test/java/package1/Example1bTest.java
index 7cb03d1..12049fe 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/src/test/java/package1/Example1bTest.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child1-test/src/test/java/package1/Example1bTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/pom.xml
index cffe791..9f23871 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1a.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1a.java
index 31fe0de..45f0859 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1a.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1a.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1b.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1b.java
index c55250b..f4633bb 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1b.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/main/java/package1/Example1b.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/test/java/package1/Example1aTest.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/test/java/package1/Example1aTest.java
index b37a27e..15895a3 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/test/java/package1/Example1aTest.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child1/src/test/java/package1/Example1aTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child2/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate/child2/pom.xml
index fbfa655..a486857 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child2/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child2/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/main/java/package2/Example2.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/main/java/package2/Example2.java
index 2e2d040..25e2f9c 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/main/java/package2/Example2.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/main/java/package2/Example2.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/test/java/package2/Example2Test.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/test/java/package2/Example2Test.java
index 21149e2..ef0df80 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/test/java/package2/Example2Test.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child2/src/test/java/package2/Example2Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/pom.xml
new file mode 100644
index 0000000..50c70bb
--- /dev/null
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+   All rights reserved. This program and the accompanying materials
+   are made available under the terms of the Eclipse Public License v1.0
+   which accompanies this distribution, and is available at
+   http://www.eclipse.org/legal/epl-v10.html
+
+   Contributors:
+      Marc R. Hoffmann, Jan Wloka - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>jacoco</groupId>
+    <artifactId>it-report-aggregate</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>child2</artifactId>
+  <version>2.0-SNAPSHOT</version>
+
+</project>
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/src/main/java/package2/Example2.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/src/main/java/package2/Example2.java
new file mode 100644
index 0000000..25e2f9c
--- /dev/null
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/src/main/java/package2/Example2.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann, Jan Wloka - initial API and implementation
+ *
+ *******************************************************************************/
+package package2;
+
+public class Example2 {
+
+  public void a() {
+  }
+
+}
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/src/test/java/package2/Example2Test.java b/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/src/test/java/package2/Example2Test.java
new file mode 100644
index 0000000..ef0df80
--- /dev/null
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/child2v2/src/test/java/package2/Example2Test.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann, Jan Wloka - initial API and implementation
+ *
+ *******************************************************************************/
+package package2;
+
+import org.junit.Test;
+
+public class Example2Test {
+
+  @Test
+  public void test() {
+    new Example2().a();
+  }
+
+}
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate/pom.xml
index 4575ee2..ab67c92 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -26,6 +26,7 @@
     <module>child1</module>
     <module>child1-test</module>
     <module>child2</module>
+    <module>child2v2</module>
     <module>report</module>
   </modules>
 
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/report/pom.xml b/jacoco-maven-plugin.test/it/it-report-aggregate/report/pom.xml
index cbf3e97..6d217a8 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/report/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/report/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -38,7 +38,7 @@
     <dependency>
       <groupId>jacoco</groupId>
       <artifactId>child2</artifactId>
-      <version>${project.version}</version>
+      <version>[2-SNAPSHOT,)</version>
       <scope>runtime</scope>
     </dependency>
   </dependencies>
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/report/src/test/java/packagereport/ReportTest.java b/jacoco-maven-plugin.test/it/it-report-aggregate/report/src/test/java/packagereport/ReportTest.java
index cefc6d1..065f71d 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/report/src/test/java/packagereport/ReportTest.java
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/report/src/test/java/packagereport/ReportTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-aggregate/verify.bsh b/jacoco-maven-plugin.test/it/it-report-aggregate/verify.bsh
index 80f6bc2..72fed73 100644
--- a/jacoco-maven-plugin.test/it/it-report-aggregate/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-report-aggregate/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,8 +22,14 @@
     throw new RuntimeException( "Execution data from child1-test was not loaded." );
 }
 
-if ( !Pattern.compile( "Loading execution data file \\S*child2.target.jacoco.exec").matcher( buildLog ).find() ) {
-    throw new RuntimeException( "Execution data from child2 was not loaded." );
+if ( !new File( basedir, "child2/target/jacoco.exec" ).isFile()) {
+    throw new RuntimeException( "No execution data in child2." );
+}
+if ( Pattern.compile( "Loading execution data file \\S*child2.target.jacoco.exec").matcher( buildLog ).find() ) {
+    throw new RuntimeException( "Execution data from child2 was loaded, whereas range should exclude it." );
+}
+if ( !Pattern.compile( "Loading execution data file \\S*child2v2.target.jacoco.exec").matcher( buildLog ).find() ) {
+    throw new RuntimeException( "Execution data from child2v2 was not loaded." );
 }
 
 if ( !Pattern.compile( "Loading execution data file \\S*report.target.jacoco.exec").matcher( buildLog ).find() ) {
diff --git a/jacoco-maven-plugin.test/it/it-report-nomatch/pom.xml b/jacoco-maven-plugin.test/it/it-report-nomatch/pom.xml
index a09b9d0..995c510 100644
--- a/jacoco-maven-plugin.test/it/it-report-nomatch/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-nomatch/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-nomatch/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-report-nomatch/src/main/java/Example.java
index 68a7d30..0deaeaf 100644
--- a/jacoco-maven-plugin.test/it/it-report-nomatch/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-report-nomatch/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-nomatch/verify.bsh b/jacoco-maven-plugin.test/it/it-report-nomatch/verify.bsh
index 3962491..f5419b0 100644
--- a/jacoco-maven-plugin.test/it/it-report-nomatch/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-report-nomatch/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-unreadable-dump/pom.xml b/jacoco-maven-plugin.test/it/it-report-unreadable-dump/pom.xml
index 1204ff5..a99c88c 100644
--- a/jacoco-maven-plugin.test/it/it-report-unreadable-dump/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-unreadable-dump/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-unreadable-dump/verify.bsh b/jacoco-maven-plugin.test/it/it-report-unreadable-dump/verify.bsh
index 7f11002..bac7401 100644
--- a/jacoco-maven-plugin.test/it/it-report-unreadable-dump/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-report-unreadable-dump/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-without-debug/pom.xml b/jacoco-maven-plugin.test/it/it-report-without-debug/pom.xml
index 3434ed0..d4ba677 100644
--- a/jacoco-maven-plugin.test/it/it-report-without-debug/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-without-debug/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-without-debug/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-report-without-debug/src/main/java/Example.java
index a95b591..d264823 100644
--- a/jacoco-maven-plugin.test/it/it-report-without-debug/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-report-without-debug/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-without-debug/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-report-without-debug/src/test/java/ExampleTest.java
index 5df8f7b..db0af65 100644
--- a/jacoco-maven-plugin.test/it/it-report-without-debug/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-report-without-debug/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-without-debug/verify.bsh b/jacoco-maven-plugin.test/it/it-report-without-debug/verify.bsh
index 2597a4c..8cb055f 100644
--- a/jacoco-maven-plugin.test/it/it-report-without-debug/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-report-without-debug/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-without-dump/pom.xml b/jacoco-maven-plugin.test/it/it-report-without-dump/pom.xml
index b35c357..24bfc6d 100644
--- a/jacoco-maven-plugin.test/it/it-report-without-dump/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-report-without-dump/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-report-without-dump/verify.bsh b/jacoco-maven-plugin.test/it/it-report-without-dump/verify.bsh
index 48c12b8..b7cc15e 100644
--- a/jacoco-maven-plugin.test/it/it-report-without-dump/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-report-without-dump/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site-failsafe/pom.xml b/jacoco-maven-plugin.test/it/it-site-failsafe/pom.xml
index 2496d4a..9e4d18c 100644
--- a/jacoco-maven-plugin.test/it/it-site-failsafe/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-site-failsafe/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site-failsafe/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-site-failsafe/src/main/java/Example.java
index 251cd23..d3b6728 100644
--- a/jacoco-maven-plugin.test/it/it-site-failsafe/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-site-failsafe/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleIT.java b/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleIT.java
index e324f74..a42093e 100644
--- a/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleIT.java
+++ b/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleIT.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleTest.java
index 5df8f7b..db0af65 100644
--- a/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-site-failsafe/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site-failsafe/verify.bsh b/jacoco-maven-plugin.test/it/it-site-failsafe/verify.bsh
index c963fe4..c933313 100644
--- a/jacoco-maven-plugin.test/it/it-site-failsafe/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-site-failsafe/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site/pom.xml b/jacoco-maven-plugin.test/it/it-site/pom.xml
index df167b2..3f4035a 100644
--- a/jacoco-maven-plugin.test/it/it-site/pom.xml
+++ b/jacoco-maven-plugin.test/it/it-site/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site/src/main/java/Example.java b/jacoco-maven-plugin.test/it/it-site/src/main/java/Example.java
index a95b591..d264823 100644
--- a/jacoco-maven-plugin.test/it/it-site/src/main/java/Example.java
+++ b/jacoco-maven-plugin.test/it/it-site/src/main/java/Example.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site/src/test/java/ExampleTest.java b/jacoco-maven-plugin.test/it/it-site/src/test/java/ExampleTest.java
index 5df8f7b..db0af65 100644
--- a/jacoco-maven-plugin.test/it/it-site/src/test/java/ExampleTest.java
+++ b/jacoco-maven-plugin.test/it/it-site/src/test/java/ExampleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/it-site/verify.bsh b/jacoco-maven-plugin.test/it/it-site/verify.bsh
index 2883930..c3d96ce 100644
--- a/jacoco-maven-plugin.test/it/it-site/verify.bsh
+++ b/jacoco-maven-plugin.test/it/it-site/verify.bsh
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/settings.xml b/jacoco-maven-plugin.test/it/settings.xml
index 220f191..31132fe 100644
--- a/jacoco-maven-plugin.test/it/settings.xml
+++ b/jacoco-maven-plugin.test/it/settings.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/it/setup-parent/pom.xml b/jacoco-maven-plugin.test/it/setup-parent/pom.xml
index 40510a7..1e736ff 100644
--- a/jacoco-maven-plugin.test/it/setup-parent/pom.xml
+++ b/jacoco-maven-plugin.test/it/setup-parent/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin.test/pom.xml b/jacoco-maven-plugin.test/pom.xml
index e114caa..9325c37 100644
--- a/jacoco-maven-plugin.test/pom.xml
+++ b/jacoco-maven-plugin.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -16,7 +16,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
diff --git a/jacoco-maven-plugin/META-INF/m2e/lifecycle-mapping-metadata.xml b/jacoco-maven-plugin/META-INF/m2e/lifecycle-mapping-metadata.xml
index e5089d4..e895c90 100644
--- a/jacoco-maven-plugin/META-INF/m2e/lifecycle-mapping-metadata.xml
+++ b/jacoco-maven-plugin/META-INF/m2e/lifecycle-mapping-metadata.xml
@@ -1,5 +1,5 @@
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/pom.xml b/jacoco-maven-plugin/pom.xml
index 52aedbd..c19312c 100644
--- a/jacoco-maven-plugin/pom.xml
+++ b/jacoco-maven-plugin/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -16,7 +16,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
@@ -27,9 +27,25 @@
   <description>The JaCoCo Maven Plugin provides the JaCoCo runtime agent to your tests and allows basic report creation.</description>
 
   <prerequisites>
-    <maven>2.2.1</maven>
+    <maven>3.0</maven>
   </prerequisites>
 
+  <dependencyManagement>
+    <dependencies>
+      <!-- maven-reporting-impl and slight update of version of its transitive dependency on commons-collections -->
+      <dependency>
+        <groupId>org.apache.maven.reporting</groupId>
+        <artifactId>maven-reporting-impl</artifactId>
+        <version>2.1</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-collections</groupId>
+        <artifactId>commons-collections</artifactId>
+        <version>3.2.2</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
   <dependencies>
     <dependency>
       <groupId>org.apache.maven</groupId>
@@ -38,7 +54,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-project</artifactId>
+      <artifactId>maven-core</artifactId>
       <version>${project.prerequisites.maven}</version>
     </dependency>
     <dependency>
@@ -60,7 +76,6 @@
     <dependency>
       <groupId>org.apache.maven.reporting</groupId>
       <artifactId>maven-reporting-impl</artifactId>
-      <version>2.1</version>
     </dependency>
 
     <dependency>
@@ -98,19 +113,6 @@
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-javadoc-plugin</artifactId>
-        <configuration>
-          <tagletArtifacts>
-            <tagletArtifact>
-              <groupId>org.apache.maven.plugin-tools</groupId>
-              <artifactId>maven-plugin-tools-javadoc</artifactId>
-              <version>2.8</version>
-            </tagletArtifact>
-          </tagletArtifacts>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-plugin-plugin</artifactId>
         <executions>
           <execution>
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java
index 1d3f34e..d097c53 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractAgentMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
 package org.jacoco.maven;
 
 import java.io.File;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -57,6 +58,21 @@
 	 */
 	@Parameter(property = "jacoco.append")
 	Boolean append;
+
+	/**
+	 * A list of class names to include in instrumentation. May use wildcard
+	 * characters (* and ?). When not specified everything will be included.
+	 */
+	@Parameter
+	private List<String> includes;
+
+	/**
+	 * A list of class names to exclude from instrumentation. May use wildcard
+	 * characters (* and ?). When not specified nothing will be excluded.
+	 */
+	@Parameter
+	private List<String> excludes;
+
 	/**
 	 * A list of class loader names, that should be excluded from execution
 	 * analysis. The list entries are separated by a colon (:) and may use
@@ -168,15 +184,13 @@
 		if (append != null) {
 			agentOptions.setAppend(append.booleanValue());
 		}
-		if (getIncludes() != null && !getIncludes().isEmpty()) {
-			final String agentIncludes = StringUtils.join(getIncludes()
-					.iterator(), ":");
-			agentOptions.setIncludes(agentIncludes);
+		if (includes != null && !includes.isEmpty()) {
+			agentOptions
+					.setIncludes(StringUtils.join(includes.iterator(), ":"));
 		}
-		if (getExcludes() != null && !getExcludes().isEmpty()) {
-			final String agentExcludes = StringUtils.join(getExcludes()
-					.iterator(), ":");
-			agentOptions.setExcludes(agentExcludes);
+		if (excludes != null && !excludes.isEmpty()) {
+			agentOptions
+					.setExcludes(StringUtils.join(excludes.iterator(), ":"));
 		}
 		if (exclClassLoaders != null) {
 			agentOptions.setExclClassloader(exclClassLoaders);
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractJacocoMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractJacocoMojo.java
index d1612ab..8eb55ca 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractJacocoMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractJacocoMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,8 +11,6 @@
  *******************************************************************************/
 package org.jacoco.maven;
 
-import java.util.List;
-
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -31,22 +29,6 @@
 	private MavenProject project;
 
 	/**
-	 * A list of class files to include in instrumentation/analysis/reports. May
-	 * use wildcard characters (* and ?). When not specified everything will be
-	 * included.
-	 */
-	@Parameter
-	private List<String> includes;
-
-	/**
-	 * A list of class files to exclude from instrumentation/analysis/reports.
-	 * May use wildcard characters (* and ?). When not specified nothing will be
-	 * excluded.
-	 */
-	@Parameter
-	private List<String> excludes;
-
-	/**
 	 * Flag used to suppress execution.
 	 */
 	@Parameter(property = "jacoco.skip", defaultValue = "false")
@@ -90,22 +72,4 @@
 		return project;
 	}
 
-	/**
-	 * Returns the list of class files to include.
-	 * 
-	 * @return class files to include, may contain wildcard characters
-	 */
-	protected List<String> getIncludes() {
-		return includes;
-	}
-
-	/**
-	 * Returns the list of class files to exclude.
-	 * 
-	 * @return class files to exclude, may contain wildcard characters
-	 */
-	protected List<String> getExcludes() {
-		return excludes;
-	}
-
 }
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractReportMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractReportMojo.java
index 71a53e9..ecd48ab 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/AbstractReportMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/AbstractReportMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/AgentITMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/AgentITMojo.java
index d26a078..03422d6 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/AgentITMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/AgentITMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java
index 8af3996..f434c98 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/CheckMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/CheckMojo.java
index 6b37a6b..68d6aa8 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/CheckMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/CheckMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -64,12 +64,6 @@
 	 * </ul>
 	 * 
 	 * <p>
-	 * Note that you <b>must</b> use <tt>implementation</tt> hints for
-	 * <tt>rule</tt> and <tt>limit</tt> when using Maven 2, with Maven 3 you do
-	 * not need to specify the attributes.
-	 * </p>
-	 * 
-	 * <p>
 	 * This example requires an overall instruction coverage of 80% and no class
 	 * must be missed:
 	 * </p>
@@ -77,15 +71,15 @@
 	 * <pre>
 	 * {@code
 	 * <rules>
-	 *   <rule implementation="org.jacoco.maven.RuleConfiguration">
+	 *   <rule>
 	 *     <element>BUNDLE</element>
 	 *     <limits>
-	 *       <limit implementation="org.jacoco.report.check.Limit">
+	 *       <limit>
 	 *         <counter>INSTRUCTION</counter>
 	 *         <value>COVEREDRATIO</value>
 	 *         <minimum>0.80</minimum>
 	 *       </limit>
-	 *       <limit implementation="org.jacoco.report.check.Limit">
+	 *       <limit>
 	 *         <counter>CLASS</counter>
 	 *         <value>MISSEDCOUNT</value>
 	 *         <maximum>0</maximum>
@@ -134,6 +128,20 @@
 	@Parameter(defaultValue = "${project.build.directory}/jacoco.exec")
 	private File dataFile;
 
+	/**
+	 * A list of class files to include into analysis. May use wildcard
+	 * characters (* and ?). When not specified everything will be included.
+	 */
+	@Parameter
+	private List<String> includes;
+
+	/**
+	 * A list of class files to exclude from analysis. May use wildcard
+	 * characters (* and ?). When not specified nothing will be excluded.
+	 */
+	@Parameter
+	private List<String> excludes;
+
 	private boolean violations;
 
 	private boolean canCheckCoverage() {
@@ -175,8 +183,7 @@
 		try {
 			final IReportVisitor visitor = support.initRootVisitor();
 			support.loadExecutionData(dataFile);
-			support.processProject(visitor, getProject(), this.getIncludes(),
-					this.getExcludes());
+			support.processProject(visitor, getProject(), includes, excludes);
 			visitor.visitEnd();
 		} catch (final IOException e) {
 			throw new MojoExecutionException(
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/DumpMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/DumpMojo.java
index 97633a4..64836ee 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/DumpMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/DumpMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java b/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java
index 8d35f6f..09029c8 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/FileFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java
index c74cf6b..d99ada7 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/InstrumentMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -23,6 +23,7 @@
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
 import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.IOUtil;
 import org.jacoco.core.instr.Instrumenter;
@@ -44,6 +45,20 @@
 @Mojo(name = "instrument", defaultPhase = LifecyclePhase.PROCESS_CLASSES, threadSafe = true)
 public class InstrumentMojo extends AbstractJacocoMojo {
 
+	/**
+	 * A list of class files to include in instrumentation. May use wildcard
+	 * characters (* and ?). When not specified everything will be included.
+	 */
+	@Parameter
+	private List<String> includes;
+
+	/**
+	 * A list of class files to exclude from instrumentation. May use wildcard
+	 * characters (* and ?). When not specified nothing will be excluded.
+	 */
+	@Parameter
+	private List<String> excludes;
+
 	@Override
 	public void executeMojo() throws MojoExecutionException,
 			MojoFailureException {
@@ -61,7 +76,7 @@
 
 		final List<String> fileNames;
 		try {
-			fileNames = new FileFilter(this.getIncludes(), this.getExcludes())
+			fileNames = new FileFilter(includes, excludes)
 					.getFileNames(classesDir);
 		} catch (final IOException e1) {
 			throw new MojoExecutionException(
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/MergeMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/MergeMojo.java
index bcddf2a..11f9577 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/MergeMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/MergeMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -43,13 +43,10 @@
 	/**
 	 * This mojo accepts any number of execution data file sets.
 	 * 
-	 * Note that you need an <tt>implementation</tt> hint on <tt>fileset</tt>
-	 * with Maven 2 (not needed with Maven 3):
-	 * 
 	 * <pre>
 	 * <code>
 	 * &lt;fileSets&gt;
-	 *   &lt;fileSet implementation="org.apache.maven.shared.model.fileset.FileSet"&gt;
+	 *   &lt;fileSet&gt;
 	 *     &lt;directory&gt;${project.build.directory}&lt;/directory&gt;
 	 *     &lt;includes&gt;
 	 *       &lt;include&gt;*.exec&lt;/include&gt;
@@ -59,7 +56,7 @@
 	 * </code>
 	 * </pre>
 	 */
-	@Parameter(property = "jacoco.fileSets", required = true)
+	@Parameter(required = true)
 	private List<FileSet> fileSets;
 
 	@Override
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/ReportAggregateMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/ReportAggregateMojo.java
index 5597ddf..5b1f12f 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/ReportAggregateMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/ReportAggregateMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -19,6 +19,9 @@
 import java.util.Locale;
 
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
@@ -177,11 +180,28 @@
 		return result;
 	}
 
+	/**
+	 * Note that if dependency specified using version range and reactor
+	 * contains multiple modules with same artifactId and groupId but of
+	 * different versions, then first dependency which matches range will be
+	 * selected. For example in case of range <code>[0,2]</code> if version 1 is
+	 * before version 2 in reactor, then version 1 will be selected.
+	 */
 	private MavenProject findProjectFromReactor(final Dependency d) {
+		final VersionRange depVersionAsRange;
+		try {
+			depVersionAsRange = VersionRange
+					.createFromVersionSpec(d.getVersion());
+		} catch (InvalidVersionSpecificationException e) {
+			throw new AssertionError(e);
+		}
+
 		for (final MavenProject p : reactorProjects) {
+			final DefaultArtifactVersion pv = new DefaultArtifactVersion(
+					p.getVersion());
 			if (p.getGroupId().equals(d.getGroupId())
 					&& p.getArtifactId().equals(d.getArtifactId())
-					&& p.getVersion().equals(d.getVersion())) {
+					&& depVersionAsRange.containsVersion(pv)) {
 				return p;
 			}
 		}
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/ReportITMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/ReportITMojo.java
index b92a4aa..ba4dde2 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/ReportITMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/ReportITMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/ReportMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/ReportMojo.java
index 641d995..002e540 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/ReportMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/ReportMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java b/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java
index b66d688..1cdf847 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -222,9 +222,10 @@
 						c.getName()));
 			}
 		}
-		if (bundle.getClassCounter().getTotalCount() > 0
+		if (bundle.containsCode()
 				&& bundle.getLineCounter().getTotalCount() == 0) {
-			log.warn("To enable source code annotation class files have to be compiled with debug information.");
+			log.warn(
+					"To enable source code annotation class files have to be compiled with debug information.");
 		}
 	}
 
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java
index b376db9..0e238d6 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/RestoreMojo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/RuleConfiguration.java b/jacoco-maven-plugin/src/org/jacoco/maven/RuleConfiguration.java
index 51cf184..be4e5a1 100644
--- a/jacoco-maven-plugin/src/org/jacoco/maven/RuleConfiguration.java
+++ b/jacoco-maven-plugin/src/org/jacoco/maven/RuleConfiguration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/jacoco/assembly.xml b/jacoco/assembly.xml
index c9690f6..056ede4 100644
--- a/jacoco/assembly.xml
+++ b/jacoco/assembly.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/jacoco/pom.xml b/jacoco/pom.xml
index e01371c..9afefc0 100644
--- a/jacoco/pom.xml
+++ b/jacoco/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
@@ -110,7 +110,7 @@
             <configuration>
               <rules>
                 <requireFilesSize>
-                  <maxsize>4100000</maxsize>
+                  <maxsize>4400000</maxsize>
                   <minsize>3400000</minsize>
                   <files>
                     <file>${project.build.directory}/jacoco-${qualified.bundle.version}.zip</file>
diff --git a/org.jacoco.agent.rt.test/pom.xml b/org.jacoco.agent.rt.test/pom.xml
index a14609d..5394ee7 100644
--- a/org.jacoco.agent.rt.test/pom.xml
+++ b/org.jacoco.agent.rt.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java
index 9f9fc78..f21968c 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java
index 5c39f5e..4d63684 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ClassFileDumperTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ConfigLoaderTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ConfigLoaderTest.java
index 2977088..f99c185 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ConfigLoaderTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ConfigLoaderTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
index d9c9cfd..5429570 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/CoverageTransformerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ExceptionRecorder.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ExceptionRecorder.java
index 099d2ed..7e8f5d2 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ExceptionRecorder.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/ExceptionRecorder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/ExecutorTestBase.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/ExecutorTestBase.java
index 2a4c2bd..b276eef 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/ExecutorTestBase.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/ExecutorTestBase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java
index 8d2d963..7e29dde 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/FileOutputTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocket.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocket.java
index 0cdfa78..18e58cb 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocket.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocket.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocketTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocketTest.java
index 3421285..942ce1a 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocketTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockServerSocketTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnection.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnection.java
index 3e077fc..a06d07f 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnection.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnection.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnectionTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnectionTest.java
index b77f9ee..3f78178 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnectionTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/MockSocketConnectionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpClientOutputTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpClientOutputTest.java
index 8059128..849e7a8 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpClientOutputTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpClientOutputTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpConnectionTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpConnectionTest.java
index c652840..514675e 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpConnectionTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpConnectionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpServerOutputTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpServerOutputTest.java
index 361bddd..6efeb67 100644
--- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpServerOutputTest.java
+++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/output/TcpServerOutputTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/pom.xml b/org.jacoco.agent.rt/pom.xml
index 7ef658d..605f449 100644
--- a/org.jacoco.agent.rt/pom.xml
+++ b/org.jacoco.agent.rt/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
@@ -68,6 +68,14 @@
                   <shadedPattern>${jacoco.runtime.package.name}.asm</shadedPattern>
                 </relocation>
               </relocations>
+              <filters>
+                <filter>
+                  <artifact>org.ow2.asm:*</artifact>
+                  <excludes>
+                    <exclude>module-info.class</exclude>
+                  </excludes>
+                </filter>
+              </filters>
               <transformers>
                 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                   <manifestEntries>
diff --git a/org.jacoco.agent.rt/src/com/vladium/emma/rt/RT.java b/org.jacoco.agent.rt/src/com/vladium/emma/rt/RT.java
index bf7787f..f2f86a1 100644
--- a/org.jacoco.agent.rt/src/com/vladium/emma/rt/RT.java
+++ b/org.jacoco.agent.rt/src/com/vladium/emma/rt/RT.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/com/vladium/emma/rt/package-info.java b/org.jacoco.agent.rt/src/com/vladium/emma/rt/package-info.java
index 9981587..0da2e7c 100644
--- a/org.jacoco.agent.rt/src/com/vladium/emma/rt/package-info.java
+++ b/org.jacoco.agent.rt/src/com/vladium/emma/rt/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Compatibility API for EMMA runtime.
  */
-package com.vladium.emma.rt;
\ No newline at end of file
+package com.vladium.emma.rt;
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/IAgent.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/IAgent.java
index 32233c6..4320ae3 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/IAgent.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/IAgent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/RT.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/RT.java
index d5f0b74..c99b807 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/RT.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/RT.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
index b4dd0c1..b6debe1 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ClassFileDumper.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ClassFileDumper.java
index 18aad17..56f74c2 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ClassFileDumper.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ClassFileDumper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ConfigLoader.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ConfigLoader.java
index dcedd52..9020c2f 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ConfigLoader.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/ConfigLoader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java
index 29395b1..ef3300c 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/CoverageTransformer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/IExceptionLogger.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/IExceptionLogger.java
index 6e5c129..82cd19b 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/IExceptionLogger.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/IExceptionLogger.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -32,6 +32,6 @@
 	 * @param ex
 	 *            exception to log
 	 */
-	public void logExeption(Exception ex);
+	void logExeption(Exception ex);
 
 }
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/JmxRegistration.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/JmxRegistration.java
index 418af53..6c49c0c 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/JmxRegistration.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/JmxRegistration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
index 7eac19f..69a9909 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/PreMain.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/PreMain.java
index 538f7a4..205fa5b 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/PreMain.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/PreMain.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,9 +12,13 @@
 package org.jacoco.agent.rt.internal;
 
 import java.lang.instrument.Instrumentation;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
 
 import org.jacoco.core.runtime.AgentOptions;
 import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.InjectedClassRuntime;
 import org.jacoco.core.runtime.ModifiedSystemClassRuntime;
 
 /**
@@ -52,7 +56,58 @@
 
 	private static IRuntime createRuntime(final Instrumentation inst)
 			throws Exception {
+
+		if (redefineJavaBaseModule(inst)) {
+			return new InjectedClassRuntime(Object.class, "$JaCoCo");
+		}
+
 		return ModifiedSystemClassRuntime.createFor(inst, "java/lang/UnknownError");
 	}
 
+	/**
+	 * Opens {@code java.base} module for {@link InjectedClassRuntime} when
+	 * executed on Java 9 JREs or higher.
+	 *
+	 * @return <code>true</code> when running on Java 9 or higher,
+	 *         <code>false</code> otherwise
+	 * @throws Exception
+	 *             if unable to open
+	 */
+	private static boolean redefineJavaBaseModule(
+			final Instrumentation instrumentation) throws Exception {
+		try {
+			Class.forName("java.lang.Module");
+		} catch (final ClassNotFoundException e) {
+			return false;
+		}
+
+		Instrumentation.class.getMethod("redefineModule", //
+				Class.forName("java.lang.Module"), //
+				Set.class, //
+				Map.class, //
+				Map.class, //
+				Set.class, //
+				Map.class //
+		).invoke(instrumentation, // instance
+				getModule(Object.class), // module
+				Collections.emptySet(), // extraReads
+				Collections.emptyMap(), // extraExports
+				Collections.singletonMap("java.lang",
+						Collections.singleton(
+								getModule(InjectedClassRuntime.class))), // extraOpens
+				Collections.emptySet(), // extraUses
+				Collections.emptyMap() // extraProvides
+		);
+		return true;
+	}
+
+	/**
+	 * @return {@code cls.getModule()}
+	 */
+	private static Object getModule(final Class<?> cls) throws Exception {
+		return Class.class //
+				.getMethod("getModule") //
+				.invoke(cls);
+	}
+
 }
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/FileOutput.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/FileOutput.java
index 64ae607..dde7860 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/FileOutput.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/FileOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/IAgentOutput.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/IAgentOutput.java
index ce8e5dd..b3d0e17 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/IAgentOutput.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/IAgentOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -33,8 +33,7 @@
 	 * @throws Exception
 	 *             in case startup fails
 	 */
-	public void startup(final AgentOptions options, final RuntimeData data)
-			throws Exception;
+	void startup(AgentOptions options, RuntimeData data) throws Exception;
 
 	/**
 	 * Shutdown the agent controller and clean up any resources it has created.
@@ -42,7 +41,7 @@
 	 * @throws Exception
 	 *             in case shutdown fails
 	 */
-	public void shutdown() throws Exception;
+	void shutdown() throws Exception;
 
 	/**
 	 * Write all execution data in the runtime to a location determined by the
@@ -53,6 +52,6 @@
 	 * @throws IOException
 	 *             in case writing fails
 	 */
-	public void writeExecutionData(boolean reset) throws IOException;
+	void writeExecutionData(boolean reset) throws IOException;
 
 }
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/NoneOutput.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/NoneOutput.java
index 83a5fdc..85a0055 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/NoneOutput.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/NoneOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpClientOutput.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpClientOutput.java
index 4f69eed..a3b027f 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpClientOutput.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpClientOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpConnection.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpConnection.java
index 06590aa..ccba1f2 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpConnection.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpConnection.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpServerOutput.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpServerOutput.java
index 038d81a..eeaf4a3 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpServerOutput.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/output/TcpServerOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/package-info.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/package-info.java
index 04ca70e..08a182c 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/package-info.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * API to access the JaCoCo agent from within the JVM under test.
  */
-package org.jacoco.agent.rt;
\ No newline at end of file
+package org.jacoco.agent.rt;
diff --git a/org.jacoco.agent.test/pom.xml b/org.jacoco.agent.test/pom.xml
index ab6291e..da758be 100644
--- a/org.jacoco.agent.test/pom.xml
+++ b/org.jacoco.agent.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
diff --git a/org.jacoco.agent.test/src/org/jacoco/agent/AgentJarTest.java b/org.jacoco.agent.test/src/org/jacoco/agent/AgentJarTest.java
index d229f13..c127489 100644
--- a/org.jacoco.agent.test/src/org/jacoco/agent/AgentJarTest.java
+++ b/org.jacoco.agent.test/src/org/jacoco/agent/AgentJarTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent/pom.xml b/org.jacoco.agent/pom.xml
index 07c70d8..ac18eca 100644
--- a/org.jacoco.agent/pom.xml
+++ b/org.jacoco.agent/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
diff --git a/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java b/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java
index f93784f..9e34dd9 100644
--- a/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java
+++ b/org.jacoco.agent/src/org/jacoco/agent/AgentJar.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.agent/src/org/jacoco/agent/package-info.java b/org.jacoco.agent/src/org/jacoco/agent/package-info.java
index effe411..15254a2 100644
--- a/org.jacoco.agent/src/org/jacoco/agent/package-info.java
+++ b/org.jacoco.agent/src/org/jacoco/agent/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Provides the runtime Java agent (JAR file) as a resource.
  */
-package org.jacoco.agent;
\ No newline at end of file
+package org.jacoco.agent;
diff --git a/org.jacoco.ant.test/pom.xml b/org.jacoco.ant.test/pom.xml
index 2284a2f..6686ae2 100644
--- a/org.jacoco.ant.test/pom.xml
+++ b/org.jacoco.ant.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
diff --git a/org.jacoco.ant.test/src/TestTargetInDefault.java b/org.jacoco.ant.test/src/TestTargetInDefault.java
index 8f000ef..a3ef958 100644
--- a/org.jacoco.ant.test/src/TestTargetInDefault.java
+++ b/org.jacoco.ant.test/src/TestTargetInDefault.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.java
index bebff1f..820be37 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml
index f51f611..4049b76 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/AgentTaskTest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -63,4 +63,4 @@
 		<au:assertEquals expected="${agent1}" actual="${agent2}"/>
 	</target>
 	
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/AntFilesLocatorTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/AntFilesLocatorTest.java
index d8021d3..cba5f1a 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/AntFilesLocatorTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/AntFilesLocatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/AntResourcesLocatorTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/AntResourcesLocatorTest.java
index e845fc7..50e3118 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/AntResourcesLocatorTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/AntResourcesLocatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.java
index 2a6ded2..3ee4454 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml
index 6b5bf29..4e34e89 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/CoverageTaskTest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -157,4 +157,4 @@
 		<au:assertLogContains text="java/sql/Timestamp"/>
 	</target>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/CreateExecFiles.java b/org.jacoco.ant.test/src/org/jacoco/ant/CreateExecFiles.java
index 4f5a547..d7787eb 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/CreateExecFiles.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/CreateExecFiles.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/DumpExecClassNames.java b/org.jacoco.ant.test/src/org/jacoco/ant/DumpExecClassNames.java
index 84f713f..de45b2b 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/DumpExecClassNames.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/DumpExecClassNames.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.java
index d8208c6..a145f88 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.xml
index 8eea591..419ba23 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskTest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -57,4 +57,4 @@
 		<au:assertFileDoesntExist file="${exec.file}"/>
 	</target>
 	
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.java
index 51e9733..1e4277d 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.xml
index 864bed8..6a3b9dd 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/DumpTaskWithServerTest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -69,4 +69,4 @@
 		<au:assertFileDoesntExist file="${exec.file}"/>
 	</target>
 	
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.java
index e1c6a3b..14ca20b 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml
index d4740bf..dbe2306 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/InstrumentTaskTest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -124,4 +124,4 @@
 		<au:assertFileExists file="${temp.dir}/test.exec" />
 	</target>
 	
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.java
index 1a6479e..43615bb 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.xml
index 578d844..d61f922 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/MergeTaskTest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -70,4 +70,4 @@
 
 		<au:assertFileExists file="${exec.file}"/>
 	</target>
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/RemoveDebugInfos.java b/org.jacoco.ant.test/src/org/jacoco/ant/RemoveDebugInfos.java
index ba4cf2a..7f9eb8d 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/RemoveDebugInfos.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/RemoveDebugInfos.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -16,6 +16,8 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import org.jacoco.core.internal.InputStreams;
+import org.jacoco.core.internal.instr.InstrSupport;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassWriter;
 
@@ -26,7 +28,8 @@
 
 	public static void main(String[] args) throws Exception {
 		final InputStream in = new FileInputStream(args[0]);
-		final ClassReader reader = new ClassReader(in);
+		final ClassReader reader = InstrSupport
+				.classReaderFor(InputStreams.readFully(in));
 		in.close();
 
 		final ClassWriter writer = new ClassWriter(0);
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskLocaleTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskLocaleTest.java
index 37b49b2..782675e 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskLocaleTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskLocaleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.java b/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.java
index 7b0116d..6f16442 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.xml b/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.xml
index 5415756..055fa0d 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.xml
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -497,4 +497,4 @@
 	</target>
 
 	
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java b/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java
index 6314d1c..a78218f 100644
--- a/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java
+++ b/org.jacoco.ant.test/src/org/jacoco/ant/TestTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/pom.xml b/org.jacoco.ant/pom.xml
index efec69b..cba37bd 100644
--- a/org.jacoco.ant/pom.xml
+++ b/org.jacoco.ant/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
@@ -67,6 +67,14 @@
                   <shadedPattern>org.jacoco.asm</shadedPattern>
                 </relocation>
               </relocations>
+              <filters>
+                <filter>
+                  <artifact>org.ow2.asm:*</artifact>
+                  <excludes>
+                    <exclude>module-info.class</exclude>
+                  </excludes>
+                </filter>
+              </filters>
               <transformers>
                 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                   <manifestEntries>
diff --git a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
index eb96b2e..709358f 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java b/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java
index c8af8af..a02b809 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/AgentTask.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/src/org/jacoco/ant/AntFilesLocator.java b/org.jacoco.ant/src/org/jacoco/ant/AntFilesLocator.java
index d1dc745..6e771f6 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/AntFilesLocator.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/AntFilesLocator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/src/org/jacoco/ant/AntResourcesLocator.java b/org.jacoco.ant/src/org/jacoco/ant/AntResourcesLocator.java
index cccedf5..41c8352 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/AntResourcesLocator.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/AntResourcesLocator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java b/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java
index 9cc9f2b..c5b1092 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/CoverageTask.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -179,7 +179,7 @@
 		 * @return <code>true</code> if this enhancer is capable of enhancing
 		 *         the requested task type
 		 */
-		public boolean supportsTask(String taskname);
+		boolean supportsTask(String taskname);
 
 		/**
 		 * Attempt to enhance the supplied task with coverage information. This
@@ -192,6 +192,6 @@
 		 *             Thrown if this enhancer can handle this type of task, but
 		 *             this instance can not be enhanced for some reason.
 		 */
-		public void enhanceTask(Task task) throws BuildException;
+		void enhanceTask(Task task) throws BuildException;
 	}
 }
diff --git a/org.jacoco.ant/src/org/jacoco/ant/DumpTask.java b/org.jacoco.ant/src/org/jacoco/ant/DumpTask.java
index 509931e..5aa20fd 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/DumpTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/DumpTask.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/src/org/jacoco/ant/InstrumentTask.java b/org.jacoco.ant/src/org/jacoco/ant/InstrumentTask.java
index eb4537b..6ba16ec 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/InstrumentTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/InstrumentTask.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/src/org/jacoco/ant/MergeTask.java b/org.jacoco.ant/src/org/jacoco/ant/MergeTask.java
index ccd4bce..de6897e 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/MergeTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/MergeTask.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java b/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java
index 8ed7b8c..bbcb348 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java
+++ b/org.jacoco.ant/src/org/jacoco/ant/ReportTask.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -593,8 +593,7 @@
 	}
 
 	private void checkForMissingDebugInformation(final ICoverageNode node) {
-		if (node.getClassCounter().getTotalCount() > 0
-				&& node.getLineCounter().getTotalCount() == 0) {
+		if (node.containsCode() && node.getLineCounter().getTotalCount() == 0) {
 			log(format(
 					"To enable source code annotation class files for bundle '%s' have to be compiled with debug information.",
 					node.getName()), Project.MSG_WARN);
diff --git a/org.jacoco.ant/src/org/jacoco/ant/antlib.xml b/org.jacoco.ant/src/org/jacoco/ant/antlib.xml
index c45a2e3..bcedf36 100644
--- a/org.jacoco.ant/src/org/jacoco/ant/antlib.xml
+++ b/org.jacoco.ant/src/org/jacoco/ant/antlib.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -18,4 +18,4 @@
    <taskdef name="merge" classname="org.jacoco.ant.MergeTask"/>
    <taskdef name="dump" classname="org.jacoco.ant.DumpTask"/>
    <taskdef name="instrument" classname="org.jacoco.ant.InstrumentTask"/>
-</antlib>
\ No newline at end of file
+</antlib>
diff --git a/org.jacoco.build/pom.xml b/org.jacoco.build/pom.xml
index b4d3e00..18ac6a5 100644
--- a/org.jacoco.build/pom.xml
+++ b/org.jacoco.build/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -14,7 +14,7 @@
 
   <groupId>org.jacoco</groupId>
   <artifactId>org.jacoco.build</artifactId>
-  <version>0.8.0</version>
+  <version>0.8.4</version>
   <packaging>pom</packaging>
 
   <name>JaCoCo</name>
@@ -83,10 +83,6 @@
     </contributor>
   </contributors>
 
-  <prerequisites>
-    <maven>3.0</maven>
-  </prerequisites>
-
   <modules>
     <!-- Order is important: org.jacoco.agent.rt embeds into org.jacoco.agent and JaCoCo Agent used during tests -->
     <module>../org.jacoco.core</module>
@@ -132,16 +128,17 @@
 
     <maven.build.timestamp.format>yyyyMMddhhmm</maven.build.timestamp.format>
     <jacoco.home.url>http://www.jacoco.org/jacoco</jacoco.home.url>
-    <copyright.years>${project.inceptionYear}, 2018</copyright.years>
+    <copyright.years>${project.inceptionYear}, 2019</copyright.years>
 
-    <maven.compiler.source>1.5</maven.compiler.source>
-    <maven.compiler.target>1.5</maven.compiler.target>
+    <bytecode.version>1.5</bytecode.version>
+    <maven.compiler.source>${bytecode.version}</maven.compiler.source>
+    <maven.compiler.target>${bytecode.version}</maven.compiler.target>
 
     <jvm.args></jvm.args>
     <argLine>${jvm.args}</argLine>
 
     <!-- Dependencies versions -->
-    <asm.version>6.0</asm.version>
+    <asm.version>7.1</asm.version>
     <ant.version>1.7.1</ant.version>
     <args4j.version>2.0.28</args4j.version>
     <junit.version>4.8.2</junit.version>
@@ -268,6 +265,8 @@
         <filtering>false</filtering>
         <excludes>
           <exclude>**/*.java</exclude>
+          <exclude>**/*.kt</exclude>
+          <exclude>**/*.groovy</exclude>
           <exclude>**/*.properties</exclude>
         </excludes>
       </resource>
@@ -308,7 +307,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
-          <version>2.3.2</version>
+          <version>3.7.0</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -323,7 +322,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-enforcer-plugin</artifactId>
-          <version>1.0.1</version>
+          <version>3.0.0-M2</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -348,24 +347,28 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-javadoc-plugin</artifactId>
-          <version>2.10.4</version>
+          <!--
+          Do not upgrade to 3.1.0 because it has troubles with "Automatic-Module-Name"
+          See https://issues.apache.org/jira/browse/MJAVADOC-588
+          -->
+          <version>3.0.1</version>
           <configuration>
             <quiet>true</quiet>
             <detectOfflineLinks>false</detectOfflineLinks>
           </configuration>
-          <dependencies>
-            <dependency>
-              <!-- Workaround to be able to use JDK 9 >= b175 -->
-              <groupId>commons-lang</groupId>
-              <artifactId>commons-lang</artifactId>
-              <version>2.6</version>
-            </dependency>
-          </dependencies>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-plugin-plugin</artifactId>
-          <version>3.5</version>
+          <version>3.6.0</version>
+          <dependencies>
+            <dependency>
+              <!-- Workaround to be able to compile into Java 13 bytecode -->
+              <groupId>org.ow2.asm</groupId>
+              <artifactId>asm</artifactId>
+              <version>7.1</version>
+            </dependency>
+          </dependencies>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -390,7 +393,15 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-shade-plugin</artifactId>
-          <version>3.1.0</version>
+          <version>3.2.1</version>
+          <dependencies>
+            <dependency>
+              <!-- Workaround to be able to compile into Java 13 bytecode -->
+              <groupId>org.ow2.asm</groupId>
+              <artifactId>asm</artifactId>
+              <version>7.1</version>
+            </dependency>
+          </dependencies>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -448,8 +459,7 @@
         <plugin>
           <groupId>org.apache.felix</groupId>
           <artifactId>maven-bundle-plugin</artifactId>
-          <!-- newer versions require Java 7 -->
-          <version>2.5.4</version>
+          <version>3.5.1</version>
         </plugin>
       </plugins>
     </pluginManagement>
@@ -524,6 +534,12 @@
             </goals>
             <configuration>
               <rules>
+                <requireJavaVersion>
+                  <version>1.8</version>
+                </requireJavaVersion>
+                <requireMavenVersion>
+                  <version>3.3.9</version>
+                </requireMavenVersion>
                 <requireNoRepositories>
                   <message>The rules for repo1.maven.org are that pom.xml files should not include repository definitions.</message>
                   <banRepositories>true</banRepositories>
@@ -533,10 +549,6 @@
                   <message>No SNAPSHOT versions allowed for dependencies</message>
                   <onlyWhenRelease>true</onlyWhenRelease>
                 </requireReleaseDeps>
-                <requireMavenVersion>
-                  <!-- Maven 3.0.3 contains bug - see http://jira.codehaus.org/browse/MINVOKER-107 -->
-                  <version>[3.0.0,3.0.3),[3.0.4,)</version>
-                </requireMavenVersion>
               </rules>
             </configuration>
           </execution>
@@ -556,9 +568,11 @@
             <configuration>
               <target>
                 <fileset dir="${basedir}" includes="**/*.java,**/*.xml,**/*.bsh" excludes="target/**,.idea/**,nb-configuration.xml" id="missinglicense.fileset">
+                  <include name="**/*.kt"/>
+                  <include name="**/*.groovy"/>
                   <not>
                     <and>
-                      <contains text="Copyright (c) 2009, 2018 Mountainminds GmbH &amp; Co. KG and Contributors"/>
+                      <contains text="Copyright (c) 2009, 2019 Mountainminds GmbH &amp; Co. KG and Contributors"/>
                       <contains text="All rights reserved. This program and the accompanying materials"/>
                       <contains text="are made available under the terms of the Eclipse Public License v1.0"/>
                       <contains text="which accompanies this distribution, and is available at"/>
@@ -677,7 +691,28 @@
   </build>
 
   <profiles>
-    <!-- This profile is used to launch tests with different JDK versions. -->
+    <!-- http://openjdk.java.net/jeps/182 -->
+    <profile>
+      <id>maven-jdk9</id>
+      <activation>
+        <jdk>[9,12)</jdk>
+      </activation>
+      <properties>
+        <bytecode.version>6</bytecode.version>
+      </properties>
+    </profile>
+
+    <profile>
+      <id>maven-jdk12</id>
+      <activation>
+        <jdk>[12,)</jdk>
+      </activation>
+      <properties>
+        <bytecode.version>7</bytecode.version>
+      </properties>
+    </profile>
+
+    <!-- This profile enables use of JDK from Maven Toolchains -->
     <profile>
       <id>integration-tests</id>
       <activation>
@@ -711,39 +746,7 @@
       </build>
     </profile>
 
-    <!-- This profile is used to launch tests with compilation into specific bytecode version. -->
-    <profile>
-      <id>bytecode</id>
-      <activation>
-        <property>
-          <name>bytecode.version</name>
-        </property>
-      </activation>
-      <properties>
-        <maven.compiler.source>${bytecode.version}</maven.compiler.source>
-        <maven.compiler.target>${bytecode.version}</maven.compiler.target>
-      </properties>
-    </profile>
-    <profile>
-      <id>java9-validation</id>
-      <activation>
-        <property>
-          <name>bytecode.version</name>
-          <value>1.9</value>
-        </property>
-      </activation>
-      <properties>
-        <!--
-        Compile into bytecode version 8 by default,
-        because maven-shade-plugin and maven-plugin-plugin are unable to proceess bytecode version 9,
-        this is overridden for tests
-        -->
-        <maven.compiler.source>1.8</maven.compiler.source>
-        <maven.compiler.target>1.8</maven.compiler.target>
-      </properties>
-    </profile>
-
-    <!-- This profile is used for compilation with ECJ. -->
+    <!-- This profile enables use of ECJ -->
     <profile>
       <id>ecj</id>
       <activation>
@@ -756,9 +759,10 @@
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-compiler-plugin</artifactId>
-            <version>3.6.0</version>
             <configuration>
               <compilerId>eclipse</compilerId>
+              <source>1.8</source>
+              <target>1.8</target>
             </configuration>
             <dependencies>
               <dependency>
@@ -777,12 +781,16 @@
       </build>
     </profile>
 
+    <!--
+    Profiles for different JDK versions:
+    -->
+
     <profile>
-      <id>jdk16</id>
+      <id>jdk6</id>
       <activation>
         <property>
           <name>jdk.version</name>
-          <value>1.6</value>
+          <value>6</value>
         </property>
       </activation>
       <properties>
@@ -791,11 +799,11 @@
     </profile>
 
     <profile>
-      <id>jdk17</id>
+      <id>jdk7</id>
       <activation>
         <property>
           <name>jdk.version</name>
-          <value>1.7</value>
+          <value>7</value>
         </property>
       </activation>
       <properties>
@@ -804,11 +812,11 @@
     </profile>
 
     <profile>
-      <id>jdk18</id>
+      <id>jdk8</id>
       <activation>
         <property>
           <name>jdk.version</name>
-          <value>1.8</value>
+          <value>8</value>
         </property>
       </activation>
       <properties>
@@ -821,15 +829,55 @@
       <activation>
         <property>
           <name>jdk.version</name>
-          <value>1.9</value>
+          <value>9</value>
         </property>
       </activation>
       <properties>
-        <jvm.args>-XX:-FailOverToOldVerifier -Xverify:all</jvm.args>
+        <bytecode.version>6</bytecode.version>
       </properties>
     </profile>
 
     <profile>
+      <id>jdk10</id>
+      <activation>
+        <property>
+          <name>jdk.version</name>
+          <value>10</value>
+        </property>
+      </activation>
+      <properties>
+        <bytecode.version>6</bytecode.version>
+      </properties>
+    </profile>
+
+    <profile>
+      <id>jdk11</id>
+      <activation>
+        <property>
+          <name>jdk.version</name>
+          <value>11</value>
+        </property>
+      </activation>
+      <properties>
+        <bytecode.version>6</bytecode.version>
+      </properties>
+    </profile>
+
+    <profile>
+      <id>jdk12</id>
+      <activation>
+        <property>
+          <name>jdk.version</name>
+          <value>12</value>
+        </property>
+      </activation>
+      <properties>
+        <bytecode.version>7</bytecode.version>
+      </properties>
+    </profile>
+
+    <!-- This profile enables generation of JARs with sources and javadocs -->
+    <profile>
       <id>sources</id>
       <activation>
         <file>
diff --git a/org.jacoco.cli.test/pom.xml b/org.jacoco.cli.test/pom.xml
index 7372fe1..fc6356d 100644
--- a/org.jacoco.cli.test/pom.xml
+++ b/org.jacoco.cli.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/CommandTestBase.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/CommandTestBase.java
index b664b22..ba570b6 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/CommandTestBase.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/CommandTestBase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java
index 9c3d82b..41807a6 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/MainTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,7 +24,7 @@
 
 		assertFailure();
 		assertNoOutput(out);
-		assertContains("Argument \"<command>\" is required", err);
+		assertContains("\"<command>\"", err);
 		assertContains("Usage: java -jar jacococli.jar --help | <command>",
 				err);
 		assertContains("Command line interface for JaCoCo.", err);
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/XmlDocumentationTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/XmlDocumentationTest.java
index ae6cab0..c902fb0 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/XmlDocumentationTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/XmlDocumentationTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ClassInfoTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ClassInfoTest.java
index f972f9c..f1b9df1 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ClassInfoTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ClassInfoTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -25,7 +25,7 @@
 		execute("classinfo", "--invalid");
 
 		assertFailure();
-		assertContains("\"--invalid\" is not a valid option", err);
+		assertContains("\"--invalid\"", err);
 		assertContains(
 				"java -jar jacococli.jar classinfo [<classlocations> ...]",
 				err);
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/DumpTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/DumpTest.java
index 6fc8923..70aeced 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/DumpTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/DumpTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -51,7 +51,7 @@
 			throws Exception {
 		execute("dump");
 		assertFailure();
-		assertContains("Option \"--destfile\" is required", err);
+		assertContains("\"--destfile\"", err);
 		assertContains("java -jar jacococli.jar dump [--address <address>]",
 				err);
 	}
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ExecInfoTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ExecInfoTest.java
index d688625..5308937 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ExecInfoTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ExecInfoTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -37,7 +37,7 @@
 		execute("execinfo", "--invalid");
 
 		assertFailure();
-		assertContains("\"--invalid\" is not a valid option", err);
+		assertContains("\"--invalid\"", err);
 		assertContains("java -jar jacococli.jar execinfo [<execfiles> ...]",
 				err);
 	}
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java
index 75850c1..76f31b8 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,13 +26,14 @@
 import java.util.Set;
 
 import org.jacoco.cli.internal.CommandTestBase;
+import org.jacoco.core.internal.InputStreams;
+import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.MethodVisitor;
 
 /**
  * Unit tests for {@link Instrument}.
@@ -47,7 +48,7 @@
 			throws Exception {
 		execute("instrument");
 		assertFailure();
-		assertContains("Option \"--dest\" is required", err);
+		assertContains("\"--dest\"", err);
 		assertContains(
 				"Usage: java -jar jacococli.jar instrument [<sourcefiles> ...]",
 				err);
@@ -134,18 +135,19 @@
 
 	private void assertInstrumented(File classfile) throws IOException {
 		InputStream in = new FileInputStream(classfile);
-		ClassReader reader = new ClassReader(in);
+		final ClassReader reader = InstrSupport
+				.classReaderFor(InputStreams.readFully(in));
 		in.close();
-		final Set<String> fields = new HashSet<String>();
-		reader.accept(new ClassVisitor(Opcodes.ASM6) {
+		final Set<String> methods = new HashSet<String>();
+		reader.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION) {
 			@Override
-			public FieldVisitor visitField(int access, String name, String desc,
-					String signature, Object value) {
-				fields.add(name);
+			public MethodVisitor visitMethod(int access, String name,
+					String descriptor, String signature, String[] exceptions) {
+				methods.add(name);
 				return null;
 			}
 		}, 0);
-		assertTrue(fields.contains("$jacocoData"));
+		assertTrue(methods.contains("$jacocoInit"));
 	}
 
 }
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/MergeTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/MergeTest.java
index fd04a34..d2dc119 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/MergeTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/MergeTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -43,7 +43,7 @@
 		execute("merge");
 
 		assertFailure();
-		assertContains("Option \"--destfile\" is required", err);
+		assertContains("\"--destfile\"", err);
 		assertContains("java -jar jacococli.jar merge [<execfiles> ...]", err);
 	}
 
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ReportTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ReportTest.java
index 4a941cc..bff4296 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ReportTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/ReportTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -37,7 +37,7 @@
 		execute("report");
 
 		assertFailure();
-		assertContains("Option \"--classfiles\" is required", err);
+		assertContains("\"--classfiles\"", err);
 		assertContains(
 				"Usage: java -jar jacococli.jar report [<execfiles> ...]", err);
 	}
diff --git a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/VersionTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/VersionTest.java
index d12bd03..dab8955 100644
--- a/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/VersionTest.java
+++ b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/VersionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/pom.xml b/org.jacoco.cli/pom.xml
index 203eb47..1b975fe 100644
--- a/org.jacoco.cli/pom.xml
+++ b/org.jacoco.cli/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
@@ -49,11 +49,15 @@
           <execution>
             <phase>package</phase>
             <goals>
-              <goal>java</goal>
+              <goal>exec</goal>
             </goals>
             <configuration>
-              <mainClass>org.jacoco.cli.internal.XmlDocumentation</mainClass>
+              <toolchain>jdk</toolchain>
+              <executable>java</executable>
               <arguments>
+                <argument>-cp</argument>
+                <classpath/>
+                <argument>org.jacoco.cli.internal.XmlDocumentation</argument>
                 <argument>${project.build.directory}/generated-documentation/cli.xml</argument>
               </arguments>
             </configuration>
@@ -101,10 +105,24 @@
                   </manifestEntries>
                 </transformer>
               </transformers>
+              <filters>
+                <filter>
+                  <artifact>args4j:args4j</artifact>
+                  <excludes>
+                    <exclude>**/Messages_*.properties</exclude>
+                  </excludes>
+                </filter>
+                <filter>
+                  <artifact>org.ow2.asm:*</artifact>
+                  <excludes>
+                    <exclude>module-info.class</exclude>
+                  </excludes>
+                </filter>
+              </filters>
             </configuration>
           </execution>
         </executions>
       </plugin>
-    </plugins>    
+    </plugins>
   </build>
 </project>
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/Command.java b/org.jacoco.cli/src/org/jacoco/cli/internal/Command.java
index 5b1a2c6..4d35722 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/Command.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/Command.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/CommandHandler.java b/org.jacoco.cli/src/org/jacoco/cli/internal/CommandHandler.java
index 25d72e5..02bcbbe 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/CommandHandler.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/CommandHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/CommandParser.java b/org.jacoco.cli/src/org/jacoco/cli/internal/CommandParser.java
index 3c11001..a918a7f 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/CommandParser.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/CommandParser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/Main.java b/org.jacoco.cli/src/org/jacoco/cli/internal/Main.java
index 7028a0e..8c3fb11 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/Main.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/Main.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/XmlDocumentation.java b/org.jacoco.cli/src/org/jacoco/cli/internal/XmlDocumentation.java
index 3ed83e0..3ef4aca 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/XmlDocumentation.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/XmlDocumentation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -17,7 +17,6 @@
 import java.util.List;
 
 import org.jacoco.cli.internal.commands.AllCommands;
-import org.jacoco.report.internal.xml.XMLDocument;
 import org.jacoco.report.internal.xml.XMLElement;
 import org.kohsuke.args4j.spi.OptionHandler;
 
@@ -65,8 +64,8 @@
 		final File file = new File(args[0]);
 		file.getParentFile().mkdirs();
 
-		final XMLElement root = new XMLDocument("documentation", null, null,
-				"UTF-8", true, new FileOutputStream(file));
+		final XMLElement root = new XMLElement("documentation", null, null,
+				true, "UTF-8", new FileOutputStream(file));
 
 		for (final Command c : AllCommands.get()) {
 			writeCommand(c, root);
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/AllCommands.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/AllCommands.java
index 13a9a39..c8d713a 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/AllCommands.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/AllCommands.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ClassInfo.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ClassInfo.java
index ee35033..4e33b35 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ClassInfo.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ClassInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Dump.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Dump.java
index 9ca7df8..c63cc8a 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Dump.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Dump.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java
index 48cff20..cacf4cb 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Instrument.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Instrument.java
index 05c4c7c..b628c5b 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Instrument.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Instrument.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Merge.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Merge.java
index 2076889..229ccba 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Merge.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Merge.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java
index 2e20a66..ef984f7 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -139,8 +139,7 @@
 		visitor.visitEnd();
 	}
 
-	private IReportVisitor createReportVisitor()
-			throws IOException, IOException {
+	private IReportVisitor createReportVisitor() throws IOException {
 		final List<IReportVisitor> visitors = new ArrayList<IReportVisitor>();
 
 		if (xml != null) {
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Version.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Version.java
index 6bb5de7..273fc6e 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Version.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Version.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test.validation.groovy/pom.xml b/org.jacoco.core.test.validation.groovy/pom.xml
new file mode 100644
index 0000000..a30cb44
--- /dev/null
+++ b/org.jacoco.core.test.validation.groovy/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+   All rights reserved. This program and the accompanying materials
+   are made available under the terms of the Eclipse Public License v1.0
+   which accompanies this distribution, and is available at
+   http://www.eclipse.org/legal/epl-v10.html
+
+   Contributors:
+      Andres Almiray - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.jacoco</groupId>
+    <artifactId>org.jacoco.core.test.validation</artifactId>
+    <version>0.8.4</version>
+    <relativePath>../org.jacoco.core.test.validation</relativePath>
+  </parent>
+
+  <artifactId>org.jacoco.core.test.validation.groovy</artifactId>
+
+  <name>JaCoCo :: Test :: Core :: Validation Groovy</name>
+
+  <properties>
+    <gmaven.version>1.6.2</gmaven.version>
+    <groovy.version>2.5.3</groovy.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>org.jacoco.core.test</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.groovy</groupId>
+      <artifactId>groovy</artifactId>
+      <version>${groovy.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.gmavenplus</groupId>
+        <artifactId>gmavenplus-plugin</artifactId>
+        <version>${gmaven.version}</version>
+        <executions>
+          <execution>
+            <id>compile</id>
+            <phase>process-sources</phase>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <targetBytecode>${groovy.targetBytecode}</targetBytecode>
+          <sources>
+            <source>
+              <directory>${project.build.sourceDirectory}</directory>
+              <includes>
+                <include>**/*.groovy</include>
+              </includes>
+            </source>
+          </sources>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/org.jacoco.core.test.validation.groovy/src/org/jacoco/core/test/validation/groovy/GroovyDataClassTest.java b/org.jacoco.core.test.validation.groovy/src/org/jacoco/core/test/validation/groovy/GroovyDataClassTest.java
new file mode 100644
index 0000000..f13fc43
--- /dev/null
+++ b/org.jacoco.core.test.validation.groovy/src/org/jacoco/core/test/validation/groovy/GroovyDataClassTest.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Andres Almiray - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.groovy;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.groovy.targets.GroovyDataClassTarget;
+import org.junit.Test;
+
+/**
+ * Test of <code>data class</code>es.
+ */
+public class GroovyDataClassTest extends ValidationTestBase {
+    public GroovyDataClassTest() {
+        super(GroovyDataClassTarget.class);
+    }
+
+    @Test
+    public void test_method_count() {
+        assertMethodCount(1);
+    }
+}
diff --git a/org.jacoco.core.test.validation.groovy/src/org/jacoco/core/test/validation/groovy/targets/GroovyDataClassTarget.groovy b/org.jacoco.core.test.validation.groovy/src/org/jacoco/core/test/validation/groovy/targets/GroovyDataClassTarget.groovy
new file mode 100644
index 0000000..c51b1e5
--- /dev/null
+++ b/org.jacoco.core.test.validation.groovy/src/org/jacoco/core/test/validation/groovy/targets/GroovyDataClassTarget.groovy
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Andres Almiray - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.groovy.targets
+
+/* This annotation generates the following
+ * - a constructor that takes an int as argument
+ * - a suitable implementation of toString()
+ * - a suitable implementation of hashCode()
+ * - a suitable implementation of equals(Object)
+ * - a public method named canEqual(Object)
+ * - a getter & setter for the valRead property
+ */
+@groovy.transform.Canonical
+class GroovyDataClassTarget { // assertEmpty()
+
+    int valRead // assertEmpty()
+
+    static void main(String[] args) {
+        new GroovyDataClassTarget() // assertFullyCovered()
+    }
+}
diff --git a/org.jacoco.core.test.validation.java5/.classpath b/org.jacoco.core.test.validation.java5/.classpath
new file mode 100644
index 0000000..ebe550b
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/.classpath
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/classes" path="src">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.jacoco.core.test.validation.java5/.project b/org.jacoco.core.test.validation.java5/.project
new file mode 100644
index 0000000..cfbae43
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.jacoco.core.test.validation.java5</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>.settings</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/org.jacoco.core.test/.settings</locationURI>
+		</link>
+	</linkedResources>
+</projectDescription>
diff --git a/org.jacoco.core.test.validation.java5/pom.xml b/org.jacoco.core.test.validation.java5/pom.xml
new file mode 100644
index 0000000..4591189
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+   All rights reserved. This program and the accompanying materials
+   are made available under the terms of the Eclipse Public License v1.0
+   which accompanies this distribution, and is available at
+   http://www.eclipse.org/legal/epl-v10.html
+
+   Contributors:
+      Evgeny Mandrikov - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.jacoco</groupId>
+    <artifactId>org.jacoco.core.test.validation</artifactId>
+    <version>0.8.4</version>
+    <relativePath>../org.jacoco.core.test.validation</relativePath>
+  </parent>
+
+  <artifactId>org.jacoco.core.test.validation.java5</artifactId>
+
+  <name>JaCoCo :: Test :: Core :: Validation Java 5</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>org.jacoco.core.test</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/AnnotationGeneratedTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/AnnotationGeneratedTest.java
new file mode 100644
index 0000000..c56e612
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/AnnotationGeneratedTest.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.AnnotationGeneratedTarget;
+
+public class AnnotationGeneratedTest extends ValidationTestBase {
+
+	public AnnotationGeneratedTest() {
+		super(AnnotationGeneratedTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/AnnotationInitializerTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/AnnotationInitializerTest.java
similarity index 73%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/AnnotationInitializerTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/AnnotationInitializerTest.java
index 60a3833..01a721f 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/AnnotationInitializerTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/AnnotationInitializerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,21 +9,20 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.AnnotationInitializer;
-import org.junit.Test;
+package org.jacoco.core.test.validation.java5;
 
 import static org.junit.Assert.assertEquals;
 
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.AnnotationInitializerTarget;
+
 /**
  * Test of initializer in annotations.
  */
 public class AnnotationInitializerTest extends ValidationTestBase {
 
 	public AnnotationInitializerTest() {
-		super(AnnotationInitializer.class);
+		super(AnnotationInitializerTarget.class);
 	}
 
 	@Override
@@ -38,10 +37,4 @@
 		targetClass.getField("CONST").get(null);
 	}
 
-	@Test
-	public void testCoverageResult() {
-		assertLine("const", ICounter.FULLY_COVERED);
-		assertLine("value", ICounter.EMPTY);
-	}
-
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/BadCycleClassTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/BadCycleClassTest.java
similarity index 66%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/BadCycleClassTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/BadCycleClassTest.java
index aa646dd..cb6758b 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/BadCycleClassTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/BadCycleClassTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,10 +9,10 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java5;
 
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.BadCycleClass;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.BadCycleClassTarget;
 import org.junit.Test;
 
 /**
@@ -21,15 +21,11 @@
 public class BadCycleClassTest extends ValidationTestBase {
 
 	public BadCycleClassTest() throws Exception {
-		super(BadCycleClass.class);
+		super(BadCycleClassTarget.class);
 	}
 
 	@Test
-	public void test() throws Exception {
-		assertLine("childinit", ICounter.FULLY_COVERED);
-		assertLine("childsomeMethod", ICounter.FULLY_COVERED);
-		assertLine("childclinit", ICounter.FULLY_COVERED);
-
+	public void method_execution_sequence() throws Exception {
 		// The cycle causes a constructor and instance method to be called
 		// before the static initializer of a class:
 		assertLogEvents("childinit", "childsomeMethod", "childclinit",
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/BooleanExpressionsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/BooleanExpressionsTest.java
new file mode 100644
index 0000000..366730e
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/BooleanExpressionsTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.BooleanExpressionsTarget;
+
+/**
+ * Tests of basic Java boolean expressions.
+ */
+public class BooleanExpressionsTest extends ValidationTestBase {
+
+	public BooleanExpressionsTest() {
+		super(BooleanExpressionsTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ClassInitializerTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ClassInitializerTest.java
new file mode 100644
index 0000000..cefd5bb
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ClassInitializerTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.ClassInitializerTarget;
+
+/**
+ * Tests of static initializer in classes.
+ */
+public class ClassInitializerTest extends ValidationTestBase {
+
+	public ClassInitializerTest() {
+		super(ClassInitializerTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ConstructorsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ConstructorsTest.java
new file mode 100644
index 0000000..674b3df
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ConstructorsTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.ConstructorsTarget;
+
+/**
+ * Tests for different constructors. Private empty constructors without
+ * arguments are filtered.
+ */
+public class ConstructorsTest extends ValidationTestBase {
+
+	public ConstructorsTest() {
+		super(ConstructorsTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ControlStructureBeforeSuperConstructorTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ControlStructureBeforeSuperConstructorTest.java
new file mode 100644
index 0000000..5381ae2
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ControlStructureBeforeSuperConstructorTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.ControlStructureBeforeSuperConstructorTarget;
+
+/**
+ * Test of probes before the super constructor call.
+ */
+public class ControlStructureBeforeSuperConstructorTest
+		extends ValidationTestBase {
+
+	public ControlStructureBeforeSuperConstructorTest() {
+		super(ControlStructureBeforeSuperConstructorTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ControlStructuresTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ControlStructuresTest.java
new file mode 100644
index 0000000..350bbe0
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ControlStructuresTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.ControlStructuresTarget;
+
+/**
+ * Tests of basic Java control structures.
+ */
+public class ControlStructuresTest extends ValidationTestBase {
+
+	public ControlStructuresTest() {
+		super(ControlStructuresTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/CyclomaticComplexityTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/CyclomaticComplexityTest.java
similarity index 98%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/CyclomaticComplexityTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/CyclomaticComplexityTest.java
index 122612c..6bc1614 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/CyclomaticComplexityTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/CyclomaticComplexityTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java5;
 
 import static org.jacoco.core.test.validation.targets.Stubs.nop;
 import static org.junit.Assert.assertEquals;
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumConstructorTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumConstructorTest.java
new file mode 100644
index 0000000..f11a8b4
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumConstructorTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.EnumConstructorTarget;
+
+/**
+ * Test of filtering of enum constructors.
+ */
+public class EnumConstructorTest extends ValidationTestBase {
+
+	public EnumConstructorTest() {
+		super(EnumConstructorTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumImplicitMethodsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumImplicitMethodsTest.java
new file mode 100644
index 0000000..2653606
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumImplicitMethodsTest.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.EnumImplicitMethodsTarget;
+import org.junit.Test;
+
+/**
+ * Test of an implicit methods and static initializer in enums.
+ */
+public class EnumImplicitMethodsTest extends ValidationTestBase {
+
+	public EnumImplicitMethodsTest() {
+		super(EnumImplicitMethodsTarget.class);
+	}
+
+	@Test
+	public void test_method_count() {
+		assertMethodCount(5);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumSwitchTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumSwitchTest.java
new file mode 100644
index 0000000..920c39a
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/EnumSwitchTest.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.Source.Line;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.EnumSwitchTarget;
+
+/**
+ * Test of filtering of a synthetic class that is generated by javac for a enum
+ * in switch statement.
+ */
+public class EnumSwitchTest extends ValidationTestBase {
+
+	public EnumSwitchTest() {
+		super(EnumSwitchTarget.class);
+	}
+
+	public void assertSwitch(final Line line) {
+		if (isJDKCompiler && JAVA_VERSION.isBefore("1.6")) {
+			// class that holds "switch map" is not marked as synthetic when
+			// compiling with javac 1.5
+			assertPartlyCovered(line, 0, 2);
+		} else {
+			assertFullyCovered(line, 0, 2);
+		}
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ExceptionsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ExceptionsTest.java
new file mode 100644
index 0000000..5e0b78c
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ExceptionsTest.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.Source.Line;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.ExceptionsTarget;
+
+/**
+ * Tests of exception based control flow.
+ */
+public class ExceptionsTest extends ValidationTestBase {
+
+	public ExceptionsTest() {
+		super(ExceptionsTarget.class);
+	}
+
+	public void assertCatchNoException(final Line line) {
+		if (isJDKCompiler) {
+			assertNotCovered(line);
+		} else {
+			assertPartlyCovered(line);
+		}
+	}
+
+	public void assertCatchBlockEndNoException(final Line line) {
+		if (isJDKCompiler) {
+			assertFullyCovered(line);
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+	public void assertCatchImplicitException(final Line line) {
+		if (isJDKCompiler) {
+			assertFullyCovered(line);
+		} else {
+			assertPartlyCovered(line);
+		}
+	}
+
+	public void assertCatchBlockEndImplicitException(final Line line) {
+		if (isJDKCompiler) {
+			assertNotCovered(line);
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+	public void assertFinally(final Line line) {
+		if (isJDKCompiler) {
+			assertEmpty(line);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+	public void assertFinallyImplicitException(final Line line) {
+		if (isJDKCompiler) {
+			assertEmpty(line);
+		} else {
+			assertNotCovered(line);
+		}
+	}
+
+	public void assertBlockEndImplicitException(final Line line) {
+		if (isJDKCompiler) {
+			assertEmpty(line);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ExplicitInitialFrameTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ExplicitInitialFrameTest.java
similarity index 65%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/ExplicitInitialFrameTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ExplicitInitialFrameTest.java
index 1c0a02f..8b64541 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ExplicitInitialFrameTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ExplicitInitialFrameTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,11 +9,10 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java5;
 
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target11;
-import org.junit.Test;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.ExplicitInitialFrameTarget;
 
 /**
  * Test for a methods having a explicit initial frame.
@@ -21,14 +20,7 @@
 public class ExplicitInitialFrameTest extends ValidationTestBase {
 
 	public ExplicitInitialFrameTest() {
-		super(Target11.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("dowhilebody", ICounter.FULLY_COVERED);
-
+		super(ExplicitInitialFrameTarget.class);
 	}
 
 }
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FieldInitializationInTwoConstructorsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FieldInitializationInTwoConstructorsTest.java
new file mode 100644
index 0000000..069e35b
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FieldInitializationInTwoConstructorsTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.FieldInitializationInTwoConstructorsTarget;
+
+/**
+ * Test of field initialization in two constructors.
+ */
+public class FieldInitializationInTwoConstructorsTest
+		extends ValidationTestBase {
+
+	public FieldInitializationInTwoConstructorsTest() {
+		super(FieldInitializationInTwoConstructorsTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FinallyTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FinallyTest.java
new file mode 100644
index 0000000..91a8124
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FinallyTest.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.jacoco.core.test.TargetLoader;
+import org.jacoco.core.test.validation.Source.Line;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.FinallyTarget;
+import org.junit.Before;
+import org.junit.Test;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.LineNumberNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Test of filtering of duplicated bytecode that is generated for finally block.
+ */
+public class FinallyTest extends ValidationTestBase {
+
+	private Map<Integer, String> tags;
+
+	public FinallyTest() {
+		super(FinallyTarget.class);
+	}
+
+	@Before
+	@Override
+	public void setup() throws Exception {
+		super.setup();
+		tags = new HashMap<Integer, String>();
+	}
+
+	public void assertFinally(final Line line) {
+		if (isJDKCompiler) {
+			assertEmpty(line);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+	public void assertTwoRegions1(final Line line) {
+		if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) {
+			// https://bugs.openjdk.java.net/browse/JDK-7008643
+			assertPartlyCovered(line);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+	public void assertTwoRegionsReturn1(final Line line) {
+		if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) {
+			// https://bugs.openjdk.java.net/browse/JDK-7008643
+			assertEmpty(line);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+	public void assertTwoRegionsReturn2(final Line line) {
+		if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) {
+			// https://bugs.openjdk.java.net/browse/JDK-7008643
+			assertEmpty(line);
+		} else {
+			assertNotCovered(line);
+		}
+	}
+
+	public void assertEmptyTry1(final Line line) {
+		if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) {
+			// compiler bug fixed in javac >= 1.8:
+			assertPartlyCovered(line);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+	public void assertEmptyTry2(final Line line) {
+		if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) {
+			// compiler bug fixed in javac >= 1.8:
+			assertFullyCovered(line);
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+	public void assertAlwaysCompletesAbruptly0(final Line line) {
+		if (isJDKCompiler) {
+			// uncovered case:
+			assertEmpty(line);
+		} else {
+			assertPartlyCovered(line);
+		}
+	}
+
+	public void assertAlwaysCompletesAbruptly1(final Line line) {
+		if (isJDKCompiler) {
+			// uncovered case:
+			assertPartlyCovered(line);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+	@Test
+	@Override
+	public void execute_assertions_in_comments() throws IOException {
+		super.execute_assertions_in_comments();
+		gotos();
+	}
+
+	/**
+	 * This test studies placement of GOTO instructions.
+	 */
+	private void gotos() throws IOException {
+
+		final Set<String> expected = new HashSet<String>();
+
+		if (isJDKCompiler) {
+			expected.add("example.2");
+		} else {
+			expected.add("example.0");
+		}
+
+		expected.add("breakStatement.for");
+		if (isJDKCompiler) {
+			if (JAVA_VERSION.isBefore("10")) {
+				// https://bugs.openjdk.java.net/browse/JDK-8180141
+				expected.add("breakStatement.1");
+			} else {
+				expected.add("breakStatement");
+			}
+			expected.add("breakStatement.2");
+		} else {
+			expected.add("breakStatement");
+		}
+
+		if (isJDKCompiler) {
+			expected.add("emptyCatch.2");
+		} else {
+			expected.add("emptyCatch");
+			expected.add("emptyCatch.1");
+		}
+
+		if (isJDKCompiler) {
+			expected.add("catchNotExecuted.2");
+		} else {
+			expected.add("catchNotExecuted");
+			expected.add("catchNotExecuted.1");
+		}
+
+		if (isJDKCompiler) {
+			expected.add("nested.5");
+			expected.add("nested.6");
+		} else {
+			expected.add("nested.0");
+			expected.add("nested.3");
+		}
+
+		if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) {
+			expected.add("emptyTry.2");
+		}
+
+		if (!isJDKCompiler) {
+			expected.add("alwaysCompletesAbruptly.0");
+		}
+
+		assertEquals(expected, getTagsWithGotos());
+	}
+
+	private Set<String> getTagsWithGotos() throws IOException {
+		final Set<String> gotoTags = new HashSet<String>();
+
+		byte[] b = TargetLoader.getClassDataAsBytes(FinallyTarget.class);
+
+		final ClassNode classNode = new ClassNode();
+		InstrSupport.classReaderFor(b).accept(classNode, 0);
+		for (final MethodNode m : classNode.methods) {
+			if ("main".equals(m.name)) {
+				// skip it
+				continue;
+			}
+			int lineNumber = -1;
+			for (AbstractInsnNode i = m.instructions
+					.getFirst(); i != null; i = i.getNext()) {
+				if (AbstractInsnNode.LINE == i.getType()) {
+					lineNumber = ((LineNumberNode) i).line;
+				}
+				if (Opcodes.GOTO == i.getOpcode()) {
+					String tag = tags.get(Integer.valueOf(lineNumber));
+					if (tag == null) {
+						throw new AssertionError(
+								"No tag at line " + lineNumber);
+					}
+					gotoTags.add(tag);
+				}
+			}
+		}
+
+		return gotoTags;
+	}
+
+	public void tag(final Line line, String tag) {
+		assertFalse("duplicate tag " + tag, tags.containsValue(tag));
+		assertNull("duplicate tag in " + line,
+				tags.put(Integer.valueOf(line.getNr()), tag));
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/FramesTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FramesTest.java
similarity index 60%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/FramesTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FramesTest.java
index 35fdbf6..88e3903 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/FramesTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FramesTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java5;
 
 import static org.junit.Assert.assertEquals;
 
@@ -22,18 +22,17 @@
 import org.jacoco.core.runtime.IRuntime;
 import org.jacoco.core.runtime.SystemPropertiesRuntime;
 import org.jacoco.core.test.TargetLoader;
-import org.jacoco.core.test.validation.targets.Target01;
-import org.jacoco.core.test.validation.targets.Target02;
-import org.jacoco.core.test.validation.targets.Target03;
-import org.jacoco.core.test.validation.targets.Target04;
-import org.jacoco.core.test.validation.targets.Target05;
-import org.jacoco.core.test.validation.targets.Target06;
-import org.jacoco.core.test.validation.targets.Target07;
-import org.jacoco.core.test.validation.targets.Target08;
-import org.jacoco.core.test.validation.targets.Target09;
-import org.jacoco.core.test.validation.targets.Target10;
-import org.jacoco.core.test.validation.targets.Target11;
-import org.jacoco.core.test.validation.targets.Target12;
+import org.jacoco.core.test.validation.java5.targets.BooleanExpressionsTarget;
+import org.jacoco.core.test.validation.java5.targets.ClassInitializerTarget;
+import org.jacoco.core.test.validation.java5.targets.ConstructorsTarget;
+import org.jacoco.core.test.validation.java5.targets.ControlStructureBeforeSuperConstructorTarget;
+import org.jacoco.core.test.validation.java5.targets.ControlStructuresTarget;
+import org.jacoco.core.test.validation.java5.targets.ExceptionsTarget;
+import org.jacoco.core.test.validation.java5.targets.ExplicitInitialFrameTarget;
+import org.jacoco.core.test.validation.java5.targets.FieldInitializationInTwoConstructorsTarget;
+import org.jacoco.core.test.validation.java5.targets.ImplicitFieldInitializationTarget;
+import org.jacoco.core.test.validation.java5.targets.InterfaceClassInitializerTarget;
+import org.jacoco.core.test.validation.java5.targets.StructuredLockingTarget;
 import org.junit.Test;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
@@ -87,7 +86,7 @@
 	}
 
 	private byte[] calculateFrames(byte[] source) {
-		ClassReader rc = new ClassReader(source);
+		ClassReader rc = InstrSupport.classReaderFor(source);
 		ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 
 		// Adjust Version to 1.6 to enable frames:
@@ -113,63 +112,59 @@
 	}
 
 	@Test
-	public void testTarget01() throws IOException {
-		testFrames(Target01.class);
+	public void boolean_expressions() throws IOException {
+		testFrames(BooleanExpressionsTarget.class);
 	}
 
 	@Test
-	public void testTarget02() throws IOException {
-		testFrames(Target02.class);
+	public void class_initializer() throws IOException {
+		testFrames(ClassInitializerTarget.class);
 	}
 
 	@Test
-	public void testTarget03() throws IOException {
-		testFrames(Target03.class);
+	public void constructors() throws IOException {
+		testFrames(ConstructorsTarget.class);
 	}
 
 	@Test
-	public void testTarget04() throws IOException {
-		testFrames(Target04.class);
+	public void control_structures() throws IOException {
+		testFrames(ControlStructuresTarget.class);
 	}
 
 	@Test
-	public void testTarget05() throws IOException {
-		testFrames(Target05.class);
+	public void control_structure_before_super_constructor()
+			throws IOException {
+		testFrames(ControlStructureBeforeSuperConstructorTarget.class);
 	}
 
 	@Test
-	public void testTarget06() throws IOException {
-		testFrames(Target06.class);
+	public void exceptions() throws IOException {
+		testFrames(ExceptionsTarget.class);
 	}
 
 	@Test
-	public void testTarget07() throws IOException {
-		testFrames(Target07.class);
+	public void explicit_initial_frame() throws IOException {
+		testFrames(ExplicitInitialFrameTarget.class);
 	}
 
 	@Test
-	public void testTarget08() throws IOException {
-		testFrames(Target08.class);
+	public void field_initialization_in_two_constructors() throws IOException {
+		testFrames(FieldInitializationInTwoConstructorsTarget.class);
 	}
 
 	@Test
-	public void testTarget09() throws IOException {
-		testFrames(Target09.class);
+	public void implicit_field_initialization() throws IOException {
+		testFrames(ImplicitFieldInitializationTarget.class);
 	}
 
 	@Test
-	public void testTarget10() throws IOException {
-		testFrames(Target10.class);
+	public void interface_class_initializer() throws IOException {
+		testFrames(InterfaceClassInitializerTarget.class);
 	}
 
 	@Test
-	public void testTarget11() throws IOException {
-		testFrames(Target11.class);
-	}
-
-	@Test
-	public void testTarget12() throws IOException {
-		testFrames(Target12.class);
+	public void structured_locking() throws IOException {
+		testFrames(StructuredLockingTarget.class);
 	}
 
 }
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ImplicitFieldInitializationTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ImplicitFieldInitializationTest.java
new file mode 100644
index 0000000..b46e9c2
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/ImplicitFieldInitializationTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.ImplicitFieldInitializationTarget;
+
+/**
+ * Test of a implicit field initialization.
+ */
+public class ImplicitFieldInitializationTest extends ValidationTestBase {
+
+	public ImplicitFieldInitializationTest() {
+		super(ImplicitFieldInitializationTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/InterfaceClassInitializerTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/InterfaceClassInitializerTest.java
similarity index 63%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/InterfaceClassInitializerTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/InterfaceClassInitializerTest.java
index 5675dbb..ed4843b 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/InterfaceClassInitializerTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/InterfaceClassInitializerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,11 +9,10 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java5;
 
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target04;
-import org.junit.Test;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.InterfaceClassInitializerTarget;
 
 /**
  * Tests of static initializer in interfaces.
@@ -21,7 +20,7 @@
 public class InterfaceClassInitializerTest extends ValidationTestBase {
 
 	public InterfaceClassInitializerTest() {
-		super(Target04.class);
+		super(InterfaceClassInitializerTarget.class);
 	}
 
 	@Override
@@ -30,14 +29,4 @@
 		targetClass.getField("CONST1").get(null);
 	}
 
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("const1", ICounter.EMPTY);
-		assertLine("const2", ICounter.EMPTY);
-
-		assertLine("const3", ICounter.FULLY_COVERED);
-		assertLine("const4", ICounter.FULLY_COVERED);
-	}
-
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/StructuredLockingTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/StructuredLockingTest.java
similarity index 90%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/StructuredLockingTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/StructuredLockingTest.java
index 5640fdc..7e13e65 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/StructuredLockingTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/StructuredLockingTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java5;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -20,12 +20,12 @@
 import java.util.Set;
 
 import org.jacoco.core.instr.Instrumenter;
+import org.jacoco.core.internal.instr.InstrSupport;
 import org.jacoco.core.runtime.IRuntime;
 import org.jacoco.core.runtime.SystemPropertiesRuntime;
 import org.jacoco.core.test.TargetLoader;
-import org.jacoco.core.test.validation.targets.Target12;
+import org.jacoco.core.test.validation.java5.targets.StructuredLockingTarget;
 import org.junit.Test;
-import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.ClassNode;
@@ -54,12 +54,9 @@
 public class StructuredLockingTest {
 
 	@Test
-	public void testTarget12() throws Exception {
-		testMonitorExit(Target12.class);
-	}
-
-	private void testMonitorExit(Class<?> target) throws Exception {
-		assertStructuredLocking(TargetLoader.getClassDataAsBytes(target));
+	public void testMonitorExit() throws Exception {
+		assertStructuredLocking(TargetLoader
+				.getClassDataAsBytes(StructuredLockingTarget.class));
 	}
 
 	private void assertStructuredLocking(byte[] source) throws Exception {
@@ -68,7 +65,7 @@
 		byte[] instrumented = instrumenter.instrument(source, "TestTarget");
 
 		ClassNode cn = new ClassNode();
-		new ClassReader(instrumented).accept(cn, 0);
+		InstrSupport.classReaderFor(instrumented).accept(cn, 0);
 		for (MethodNode mn : cn.methods) {
 			assertStructuredLocking(cn.name, mn);
 		}
@@ -85,7 +82,8 @@
 			}
 
 			@Override
-			protected Frame<BasicValue> newFrame(Frame<? extends BasicValue> src) {
+			protected Frame<BasicValue> newFrame(
+					Frame<? extends BasicValue> src) {
 				return new LockFrame(src);
 			}
 		};
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/SynchronizedTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/SynchronizedTest.java
new file mode 100644
index 0000000..e4a841d
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/SynchronizedTest.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5;
+
+import org.jacoco.core.test.validation.Source.Line;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java5.targets.SynchronizedTarget;
+
+/**
+ * Test of filtering of a bytecode that is generated for a synchronized
+ * statement.
+ */
+public class SynchronizedTest extends ValidationTestBase {
+
+	public SynchronizedTest() {
+		super(SynchronizedTarget.class);
+	}
+
+	public void assertMonitorEnterImplicitException(final Line line) {
+		if (isJDKCompiler) {
+			assertFullyCovered(line);
+		} else {
+			assertPartlyCovered(line);
+		}
+	}
+
+	public void assertMonitorExit(final Line line) {
+		if (isJDKCompiler) {
+			// without filter next line covered partly:
+			assertFullyCovered(line);
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+	public void assertMonitorExitImplicitException(final Line line) {
+		if (isJDKCompiler) {
+			// without filter next line covered partly:
+			assertNotCovered(line);
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/SyntheticTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/SyntheticTest.java
similarity index 63%
rename from org.jacoco.core.test/src/org/jacoco/core/test/filter/SyntheticTest.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/SyntheticTest.java
index f439736..ce690bf 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/SyntheticTest.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/SyntheticTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,12 +9,10 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.filter;
+package org.jacoco.core.test.validation.java5;
 
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.filter.targets.Synthetic;
 import org.jacoco.core.test.validation.ValidationTestBase;
-import org.junit.Test;
+import org.jacoco.core.test.validation.java5.targets.SyntheticTarget;
 
 /**
  * Test of filtering of synthetic methods.
@@ -22,17 +20,11 @@
 public class SyntheticTest extends ValidationTestBase {
 
 	public SyntheticTest() {
-		super(Synthetic.class);
+		super(SyntheticTarget.class);
 	}
 
-	@Test
-	public void testCoverageResult() {
+	public void test_method_count() {
 		assertMethodCount(5);
-
-		assertLine("classdef", ICounter.EMPTY);
-		assertLine("field", ICounter.EMPTY);
-
-		assertLine("inner.classdef", ICounter.EMPTY);
 	}
 
 }
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/AnnotationGeneratedTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/AnnotationGeneratedTarget.java
new file mode 100644
index 0000000..7effe60
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/AnnotationGeneratedTarget.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class AnnotationGeneratedTarget {
+
+	private static class RetentionPolicyRuntime {
+
+		@Retention(RetentionPolicy.RUNTIME)
+		@interface Generated {
+		}
+
+		@RetentionPolicyRuntime.Generated
+		static void annotatedMethod() {
+			nop(); // assertEmpty()
+		}
+
+		@RetentionPolicyRuntime.Generated
+		static class AnnotatedClass {
+			AnnotatedClass() {
+				nop(); // assertEmpty()
+			}
+		}
+
+	}
+
+	private static class RetentionPolicyClass {
+
+		@Retention(RetentionPolicy.CLASS)
+		@interface Generated {
+		}
+
+		@RetentionPolicyClass.Generated
+		static void annotatedMethod() {
+			nop(); // assertEmpty()
+		}
+
+		@RetentionPolicyClass.Generated
+		static class AnnotatedClass {
+			AnnotatedClass() {
+				nop(); // assertEmpty()
+			}
+		}
+
+	}
+
+	private static class RetentionPolicySource {
+
+		@Retention(RetentionPolicy.SOURCE)
+		@interface Generated {
+		}
+
+		@RetentionPolicySource.Generated
+		static void annotatedMethod() {
+			nop(); // assertFullyCovered()
+		}
+
+		@RetentionPolicySource.Generated
+		static class AnnotatedClass {
+			AnnotatedClass() {
+				nop(); // assertFullyCovered()
+			}
+		}
+
+	}
+
+	public static void main(String[] args) {
+		RetentionPolicyRuntime.annotatedMethod();
+		new RetentionPolicyRuntime.AnnotatedClass();
+
+		RetentionPolicyClass.annotatedMethod();
+		new RetentionPolicyClass.AnnotatedClass();
+
+		RetentionPolicySource.annotatedMethod();
+		new RetentionPolicySource.AnnotatedClass();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/AnnotationInitializerTarget.java
similarity index 67%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/AnnotationInitializerTarget.java
index f7b9e0a..841f096 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/AnnotationInitializerTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,15 +9,15 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
 /**
  * This test target is an annotation with an initializer.
  */
-public @interface AnnotationInitializer {
+public @interface AnnotationInitializerTarget {
 
-	Object CONST = new Object(); // $line-const$
+	Object CONST = new Object(); // assertFullyCovered()
 
-	int value() default 0; // $line-value$
+	int value() default 0; // assertEmpty()
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/BadCycleClass.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/BadCycleClassTarget.java
similarity index 66%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/BadCycleClass.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/BadCycleClassTarget.java
index c182664..c37fa8a 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/BadCycleClass.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/BadCycleClassTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,9 +9,11 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
-public class BadCycleClass {
+import org.jacoco.core.test.validation.targets.Stubs;
+
+public class BadCycleClassTarget {
 
 	public static class Base {
 		static final Child b = new Child();
@@ -24,15 +26,15 @@
 	public static class Child extends Base {
 
 		static {
-			Stubs.logEvent("childclinit"); // $line-childclinit$
+			Stubs.logEvent("childclinit"); // assertFullyCovered()
 		}
 
 		public Child() {
-			Stubs.logEvent("childinit"); // $line-childinit$
+			Stubs.logEvent("childinit"); // assertFullyCovered()
 		}
 
 		void someMethod() {
-			Stubs.logEvent("childsomeMethod"); // $line-childsomeMethod$
+			Stubs.logEvent("childsomeMethod"); // assertFullyCovered()
 		}
 
 	}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/BooleanExpressionsTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/BooleanExpressionsTarget.java
new file mode 100644
index 0000000..6015cea
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/BooleanExpressionsTarget.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.i1;
+import static org.jacoco.core.test.validation.targets.Stubs.i2;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+import static org.jacoco.core.test.validation.targets.Stubs.t;
+
+/**
+ * This target exercises boolean expressions.
+ */
+public class BooleanExpressionsTarget {
+
+	public static void main(String[] args) {
+
+		/* 1. Boolean comparison result (one case) */
+		nop(i2() > 3); // assertPartlyCovered(1, 1)
+
+		/* 2. Boolean comparison result (both cases) */
+		for (int i = 0; i < 2; i++) {
+			nop(i < 1); // assertFullyCovered(0, 2)
+		}
+
+		/* 3. And */
+		if (f() & f()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (f() & t()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (t() & f()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (t() & t()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+
+		/* 4. Conditional And */
+		if (f() && f()) { // assertPartlyCovered(3, 1)
+			nop();
+		}
+		if (f() && t()) { // assertPartlyCovered(3, 1)
+			nop();
+		}
+		if (t() && f()) { // assertFullyCovered(2, 2)
+			nop();
+		}
+		if (t() && t()) { // assertFullyCovered(2, 2)
+			nop();
+		}
+
+		/* 5. Or */
+		if (f() | f()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (f() | t()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (t() | f()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (t() | t()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+
+		/* 6. Conditional Or */
+		if (f() || f()) { // assertFullyCovered(2, 2)
+			nop();
+		}
+		if (f() || t()) { // assertFullyCovered(2, 2)
+			nop();
+		}
+		if (t() || f()) { // assertPartlyCovered(3, 1)
+			nop();
+		}
+		if (t() || t()) { // assertPartlyCovered(3, 1)
+			nop();
+		}
+
+		/* 7. Exclusive Or */
+		if (f() ^ f()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (f() ^ t()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (t() ^ f()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+		if (t() ^ t()) { // assertFullyCovered(1, 1)
+			nop();
+		}
+
+		/* 8. Conditional Operator */
+		nop(t() ? i1() : i2()); // assertPartlyCovered(1, 1)
+		nop(f() ? i1() : i2()); // assertPartlyCovered(1, 1)
+
+		/* 9. Not (one case) */
+		nop(!t()); // assertPartlyCovered(1, 1)
+		nop(!f()); // assertPartlyCovered(1, 1)
+
+		/* 10. Not (both cases) */
+		for (boolean b : new boolean[] { true, false }) {
+			nop(!b); // assertFullyCovered(0, 2)
+		}
+
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ClassInitializerTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ClassInitializerTarget.java
new file mode 100644
index 0000000..5b1f554
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ClassInitializerTarget.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.i1;
+
+import org.jacoco.core.test.validation.targets.Stubs;
+
+/**
+ * This test target is a class with a static initializer.
+ */
+public class ClassInitializerTarget {
+
+	/* No code required to initialize these fields: */
+
+	public static final int CONST1 = 3; // assertEmpty()
+
+	public static final String CONST2 = "Hello"; // assertEmpty()
+
+	/* These fields are initialized within <clinit> */
+
+	public static final int CONST3 = i1(); // assertFullyCovered()
+
+	public static final Object CONST4 = new Object(); // assertFullyCovered()
+
+	public static int field1 = 3; // assertFullyCovered()
+
+	public static String field2 = "Hello"; // assertFullyCovered()
+
+	public static int field3 = i1(); // assertFullyCovered()
+
+	public static Object field4 = new Object(); // assertFullyCovered()
+
+	static {
+		Stubs.nop(); // assertFullyCovered()
+	}
+
+	private ClassInitializerTarget() {
+	}
+
+	public static void main(String[] args) {
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ConstructorsTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ConstructorsTarget.java
new file mode 100644
index 0000000..f818440
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ConstructorsTarget.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+/**
+ * This test target calls different constructors.
+ */
+public class ConstructorsTarget {
+
+	/* not filtered because not private: */
+	ConstructorsTarget() { // assertFullyCovered()
+	}
+
+	/* not filtered because has argument: */
+	private ConstructorsTarget(Object arg) { // assertFullyCovered()
+	}
+
+	private static class Super extends ConstructorsTarget {
+		private Super() {
+			/*
+			 * not filtered because not empty - prepares arguments for super
+			 * constructor:
+			 */
+			super(null); // assertFullyCovered()
+		}
+	}
+
+	private class Inner {
+		/*
+		 * not filtered because contains initialization of a field to hold
+		 * reference to an instance of outer class that is passed as an
+		 * argument:
+		 */
+		private Inner() { // assertFullyCovered()
+		}
+	}
+
+	private static class InnerStatic {
+		@SuppressWarnings("unused")
+		private final Object field = this;
+
+		/*
+		 * not filtered because not empty - contains initialization of a field:
+		 */
+		private InnerStatic() { // assertFullyCovered()
+		}
+	}
+
+	/*
+	 * not filtered because default constructor for not private inner classes is
+	 * not private:
+	 */
+	public static class PublicDefault { // assertFullyCovered()
+	}
+
+	static class PackageLocalDefault { // assertFullyCovered()
+	}
+
+	private static class PrivateDefault { // assertEmpty()
+	}
+
+	private static class PrivateNonEmptyNoArg {
+		private PrivateNonEmptyNoArg() {
+			nop(); // assertFullyCovered()
+		}
+	}
+
+	private static class PrivateEmptyNoArg {
+		private PrivateEmptyNoArg() { // assertEmpty()
+		} // assertEmpty()
+	}
+
+	public static void main(String[] args) {
+		new Super();
+		new ConstructorsTarget().new Inner();
+		new InnerStatic();
+		new PublicDefault();
+		new PackageLocalDefault();
+		new PrivateDefault();
+		new PrivateNonEmptyNoArg();
+		new PrivateEmptyNoArg();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target10.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructureBeforeSuperConstructorTarget.java
similarity index 70%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target10.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructureBeforeSuperConstructorTarget.java
index bb4496e..3af4047 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target10.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructureBeforeSuperConstructorTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
 import static org.jacoco.core.test.validation.targets.Stubs.f;
 import static org.jacoco.core.test.validation.targets.Stubs.t;
@@ -20,14 +20,14 @@
  * This test target has a constructor containing control structures before the
  * superclass constructor is called.
  */
-public class Target10 extends SuperClass {
+public class ControlStructureBeforeSuperConstructorTarget extends SuperClass {
 
-	public Target10() {
-		super(t() || f()); // $line-super$
+	public ControlStructureBeforeSuperConstructorTarget() {
+		super(t() || f()); // assertPartlyCovered(3, 1)
 	}
 
 	public static void main(String[] args) {
-		new Target10();
+		new ControlStructureBeforeSuperConstructorTarget();
 	}
 
 }
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructuresTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructuresTarget.java
new file mode 100644
index 0000000..571adca
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ControlStructuresTarget.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.i2;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+import static org.jacoco.core.test.validation.targets.Stubs.t;
+
+import java.util.Collections;
+
+/**
+ * This target exercises a set of common Java control structures.
+ */
+public class ControlStructuresTarget {
+
+	public static void main(String[] args) {
+
+		unconditionalExecution();
+		missedIfBlock();
+		executedIfBlock();
+		missedWhileBlock();
+		alwaysExecutedWhileBlock();
+		executedWhileBlock();
+		executedDoWhileBlock();
+		missedForBlock();
+		executedForBlock();
+		missedForEachBlock();
+		executedForEachBlock();
+		tableSwitchWithHit();
+		continuedTableSwitchWithHit();
+		tableSwitchWithoutHit();
+		lookupSwitchWithHit();
+		continuedLookupSwitchWithHit();
+		lookupSwitchWithoutHit();
+		breakStatement();
+		continueStatement();
+		conditionalReturn();
+		implicitReturn();
+		explicitReturn();
+
+	}
+
+	private static void unconditionalExecution() {
+
+		nop(); // assertFullyCovered()
+
+	}
+
+	private static void missedIfBlock() {
+
+		if (f()) { // assertFullyCovered(1, 1)
+			nop(); // assertNotCovered()
+		} else {
+			nop(); // assertFullyCovered()
+		}
+
+	}
+
+	private static void executedIfBlock() {
+
+		if (t()) { // assertFullyCovered(1, 1)
+			nop(); // assertFullyCovered()
+		} else {
+			nop(); // assertNotCovered()
+		}
+
+	}
+
+	private static void missedWhileBlock() {
+
+		while (f()) { // assertFullyCovered(1, 1)
+			nop(); // assertNotCovered()
+		}
+
+	}
+
+	private static void alwaysExecutedWhileBlock() {
+
+		while (t()) { // assertFullyCovered(1, 1)
+			if (t()) {
+				break;
+			}
+		}
+
+	}
+
+	private static void executedWhileBlock() {
+
+		int i = 0;
+		while (i++ < 3) { // assertFullyCovered(0, 2)
+			nop(); // assertFullyCovered()
+		}
+
+	}
+
+	private static void executedDoWhileBlock() {
+
+		do {
+			nop(); // assertFullyCovered()
+		} while (f()); // assertFullyCovered(1, 1)
+
+	}
+
+	private static void missedForBlock() {
+
+		for (nop(); f(); nop()) { // assertPartlyCovered(1, 1)
+			nop(); // assertNotCovered()
+		}
+
+	}
+
+	private static void executedForBlock() {
+
+		for (int j = 0; j < 1; j++) { // assertFullyCovered(0, 2)
+			nop(); // assertFullyCovered()
+		}
+
+	}
+
+	private static void missedForEachBlock() {
+
+		for (Object o : Collections.emptyList()) { // assertPartlyCovered(1, 1)
+			nop(o); // assertNotCovered()
+		}
+
+	}
+
+	private static void executedForEachBlock() {
+
+		for (Object o : Collections.singleton(new Object())) { // assertFullyCovered(0,2)
+			nop(o); // assertFullyCovered()
+		}
+
+	}
+
+	private static void tableSwitchWithHit() {
+
+		switch (i2()) { // assertFullyCovered(3, 1)
+		case 1:
+			nop(); // assertNotCovered()
+			break;
+		case 2:
+			nop(); // assertFullyCovered()
+			break;
+		case 3:
+			nop(); // assertNotCovered()
+			break;
+		default:
+			nop(); // assertNotCovered()
+			break;
+		}
+
+	}
+
+	private static void continuedTableSwitchWithHit() {
+
+		switch (i2()) { // assertFullyCovered(3, 1)
+		case 1:
+			nop(); // assertNotCovered()
+		case 2:
+			nop(); // assertFullyCovered()
+		case 3:
+			nop(); // assertFullyCovered()
+		default:
+			nop(); // assertFullyCovered()
+		}
+
+	}
+
+	private static void tableSwitchWithoutHit() {
+
+		switch (i2()) { // assertFullyCovered(3, 1)
+		case 3:
+			nop(); // assertNotCovered()
+			break;
+		case 4:
+			nop(); // assertNotCovered()
+			break;
+		case 5:
+			nop(); // assertNotCovered()
+			break;
+		default:
+			nop(); // assertFullyCovered()
+			break;
+		}
+
+	}
+
+	private static void lookupSwitchWithHit() {
+
+		switch (i2()) { // assertFullyCovered(3, 1)
+		case -123:
+			nop(); // assertNotCovered()
+			break;
+		case 2:
+			nop(); // assertFullyCovered()
+			break;
+		case 456:
+			nop(); // assertNotCovered()
+			break;
+		default:
+			nop(); // assertNotCovered()
+			break;
+		}
+
+	}
+
+	private static void continuedLookupSwitchWithHit() {
+
+		switch (i2()) { // assertFullyCovered(3, 1)
+		case -123:
+			nop(); // assertNotCovered()
+		case 2:
+			nop(); // assertFullyCovered()
+		case 456:
+			nop(); // assertFullyCovered()
+		default:
+			nop(); // assertFullyCovered()
+		}
+
+	}
+
+	private static void lookupSwitchWithoutHit() {
+
+		switch (i2()) { // assertFullyCovered(3, 1)
+		case -123:
+			nop(); // assertNotCovered()
+			break;
+		case 456:
+			nop(); // assertNotCovered()
+			break;
+		case 789:
+			nop(); // assertNotCovered()
+			break;
+		default:
+			nop(); // assertFullyCovered()
+			break;
+		}
+
+	}
+
+	private static void breakStatement() {
+
+		while (true) {
+			if (t()) {
+				break; // assertFullyCovered()
+			}
+			nop(); // assertNotCovered()
+		}
+
+	}
+
+	private static void continueStatement() {
+
+		for (int j = 0; j < 1; j++) {
+			if (t()) {
+				continue; // assertFullyCovered()
+			}
+			nop(); // assertNotCovered()
+		}
+
+	}
+
+	private static void conditionalReturn() {
+
+		if (t()) {
+			return; // assertFullyCovered()
+		}
+		nop(); // assertNotCovered()
+
+	}
+
+	private static void implicitReturn() {
+
+	} // assertFullyCovered()
+
+	private static void explicitReturn() {
+
+		return; // assertFullyCovered()
+
+	} // assertEmpty()
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumConstructorTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumConstructorTarget.java
new file mode 100644
index 0000000..5b526b9
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumConstructorTarget.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+/**
+ * This test target is an enum constructor.
+ */
+public class EnumConstructorTarget {
+
+	/*
+	 * Implicit constructor should be filtered. without filter next line is
+	 * partly covered:
+	 */
+	private enum ImplicitConstructor { // assertFullyCovered()
+	}
+
+	/* Explicit non empty constructor should not be filtered: */
+	private enum ExplicitNonEmptyConstructor {
+		;
+
+		ExplicitNonEmptyConstructor() {
+			nop(); // assertNotCovered()
+		}
+	}
+
+	/* Explicit empty constructor should be filtered: */
+	private enum ExplicitEmptyConstructor {
+		;
+
+		ExplicitEmptyConstructor() {
+			/* without filter next line is not covered: */
+		} // assertEmpty()
+
+		ExplicitEmptyConstructor(Object p) {
+		} // assertNotCovered()
+	}
+
+	public static void main(String[] args) {
+		ImplicitConstructor.values();
+		ExplicitEmptyConstructor.values();
+		ExplicitNonEmptyConstructor.values();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/EnumImplicitMethods.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumImplicitMethodsTarget.java
similarity index 61%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/EnumImplicitMethods.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumImplicitMethodsTarget.java
index afbc46f..687bc4e 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/EnumImplicitMethods.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumImplicitMethodsTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,22 +9,24 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
-public enum EnumImplicitMethods { // $line-classdef$
+import org.jacoco.core.test.validation.targets.Stubs;
 
-	CONST(Stubs.f() ? new Object() : new Object()); // $line-const$
+public enum EnumImplicitMethodsTarget { // assertFullyCovered()
+
+	CONST(Stubs.f() ? new Object() : new Object()); // assertPartlyCovered(1, 1)
 
 	static {
-	} // $line-staticblock$
+	} // assertFullyCovered()
 
 	/**
-	 * Unlike in {@link Target07 regular classes}, even if enum has explicit
-	 * constructor, {@code clinit} method in any case has a reference to the
-	 * line of enum definition.
+	 * Unlike in {@link ConstructorsTarget regular classes}, even if enum has
+	 * explicit constructor, {@code clinit} method in any case has a reference
+	 * to the line of enum definition.
 	 */
-	EnumImplicitMethods(Object o) { // $line-super$
-	} // $line-constructor$
+	EnumImplicitMethodsTarget(Object o) { // assertFullyCovered()
+	} // assertFullyCovered()
 
 	/**
 	 * This method should not be excluded from analysis unlike implicitly
@@ -32,7 +34,7 @@
 	 * definition in case of javac and to the first line in case of ECJ.
 	 */
 	public void valueOf() {
-	} // $line-customValueOfMethod$
+	} // assertNotCovered()
 
 	/**
 	 * This method should not be excluded from analysis unlike implicitly
@@ -40,7 +42,7 @@
 	 * definition in case of javac and to the first line in case of ECJ.
 	 */
 	public void values(Object o) {
-	} // $line-customValuesMethod$
+	} // assertNotCovered()
 
 	public static void main(String[] args) {
 	}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumSwitchTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumSwitchTarget.java
new file mode 100644
index 0000000..51ca47e
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/EnumSwitchTarget.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+/**
+ * This test target is a switch statement with a enum.
+ */
+public class EnumSwitchTarget {
+
+	private enum E {
+		V1, V2
+	}
+
+	private static void example(E e) {
+		switch (e) { // assertSwitch()
+		case V1:
+			nop("V1");
+			break;
+		case V2:
+		default:
+			nop("V2");
+			break;
+		}
+	}
+
+	public static void main(String[] args) {
+		example(E.V1);
+		example(E.V2);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ExceptionsTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ExceptionsTarget.java
new file mode 100644
index 0000000..efac5a6
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ExceptionsTarget.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.ex;
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+import org.jacoco.core.test.validation.targets.Stubs.StubException;
+
+/**
+ * This target produces exception based control flow examples.
+ */
+public class ExceptionsTarget {
+
+	public static void main(String[] args) {
+
+		try {
+			implicitNullPointerException(null);
+		} catch (NullPointerException e) {
+		}
+		try {
+			implicitException();
+		} catch (StubException e) {
+		}
+		try {
+			explicitException();
+		} catch (StubException e) {
+		}
+		noExceptionTryCatch();
+		implicitExceptionTryCatch();
+		implicitExceptionTryCatchAfterCondition();
+		explicitExceptionTryCatch();
+		noExceptionFinally();
+		try {
+			explicitExceptionFinally();
+		} catch (StubException e) {
+		}
+		try {
+			implicitExceptionFinally();
+		} catch (StubException e) {
+		}
+	}
+
+	/**
+	 * Currently no coverage at all, as we don't see when a block aborts
+	 * somewhere in the middle.
+	 */
+	private static void implicitNullPointerException(int[] a) {
+		nop(); // assertNotCovered()
+		a[0] = 0; // assertNotCovered()
+		nop(); // assertNotCovered()
+	}
+
+	/**
+	 * For each line with method invocations a extra probe is inserted.
+	 * Therefore the lines before the exception are marked as covered.
+	 */
+	private static void implicitException() {
+		nop(); // assertFullyCovered()
+		ex(); // assertNotCovered()
+		nop(); // assertNotCovered()
+	}
+
+	private static void explicitException() {
+		nop(); // assertFullyCovered()
+		throw new StubException(); // assertFullyCovered()
+	}
+
+	private static void noExceptionTryCatch() {
+		nop(); // assertFullyCovered()
+		try {
+			nop(); // assertFullyCovered()
+		} catch (StubException e) { // assertCatchNoException()
+			nop(); // assertNotCovered()
+		} // assertCatchBlockEndNoException()
+	} // assertFullyCovered()
+
+	private static void implicitExceptionTryCatch() {
+		nop(); // assertFullyCovered()
+		try {
+			nop(); // assertFullyCovered()
+			ex(); // assertNotCovered()
+			nop(); // assertNotCovered()
+		} catch (StubException e) { // assertCatchImplicitException()
+			nop(); // assertFullyCovered()
+		} // assertCatchBlockEndImplicitException()
+	} // assertFullyCovered()
+
+	/**
+	 * As the try/catch block is entered at one branch of the condition should
+	 * be marked as executed
+	 */
+	private static void implicitExceptionTryCatchAfterCondition() {
+		if (f()) { // assertFullyCovered(1, 1)
+			return;
+		}
+		try {
+			ex(); // assertNotCovered()
+		} catch (StubException e) {
+			nop(); // assertFullyCovered()
+		}
+	}
+
+	private static void explicitExceptionTryCatch() {
+		nop(); // assertFullyCovered()
+		try {
+			nop(); // assertFullyCovered()
+			throw new StubException(); // assertFullyCovered()
+		} catch (StubException e) { // assertFullyCovered()
+			nop(); // assertFullyCovered()
+		} // assertEmpty()
+	} // assertFullyCovered()
+
+	private static void noExceptionFinally() {
+		nop(); // assertFullyCovered()
+		try {
+			nop(); // assertFullyCovered()
+		} finally { // assertFinally()
+			nop(); // assertFullyCovered()
+		} // assertEmpty()
+	} // assertFullyCovered()
+
+	private static void implicitExceptionFinally() {
+		nop(); // assertFullyCovered()
+		try {
+			nop(); // assertFullyCovered()
+			ex(); // assertNotCovered()
+			nop(); // assertNotCovered()
+		} finally { // assertFinallyImplicitException()
+			nop(); // assertFullyCovered()
+		} // assertEmpty()
+	} // assertNotCovered()
+
+	private static void explicitExceptionFinally() {
+		nop(); // assertFullyCovered()
+		try {
+			nop(); // assertFullyCovered()
+			throw new StubException(); // assertFullyCovered()
+		} finally { // assertFinally()
+			nop(); // assertFullyCovered()
+		} // assertBlockEndImplicitException()
+	} // assertEmpty()
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target11.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ExplicitInitialFrameTarget.java
similarity index 80%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target11.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ExplicitInitialFrameTarget.java
index d393cb7..475de0a 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target11.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ExplicitInitialFrameTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
 import static org.jacoco.core.test.validation.targets.Stubs.f;
 import static org.jacoco.core.test.validation.targets.Stubs.nop;
@@ -18,12 +18,12 @@
  * This test target needs an explicit initial frame as the first instruction
  * already is a jump target.
  */
-public class Target11 {
+public class ExplicitInitialFrameTarget {
 
 	public static void main(String[] args) {
 
 		do {
-			nop(); // $line-dowhilebody$
+			nop(); // assertFullyCovered()
 		} while (f());
 
 	}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/FieldInitializationInTwoConstructorsTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/FieldInitializationInTwoConstructorsTarget.java
new file mode 100644
index 0000000..b79b922
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/FieldInitializationInTwoConstructorsTarget.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+/**
+ * This test target has instance members with initialization in two
+ * constructors.
+ */
+public class FieldInitializationInTwoConstructorsTarget {
+
+	Object field1 = null; // assertPartlyCovered()
+
+	int field2 = 123; // assertPartlyCovered()
+
+	public FieldInitializationInTwoConstructorsTarget() {
+	} // assertFullyCovered()
+
+	public FieldInitializationInTwoConstructorsTarget(String arg) {
+	} // assertNotCovered()
+
+	public static void main(String[] args) {
+		new FieldInitializationInTwoConstructorsTarget();
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/FinallyTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/FinallyTarget.java
new file mode 100644
index 0000000..66aeabe
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/FinallyTarget.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.ex;
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+import static org.jacoco.core.test.validation.targets.Stubs.t;
+
+public class FinallyTarget {
+
+	/**
+	 * <pre>
+	 *   InputStream in = null;
+	 *   try {
+	 *     in = ...;
+	 *     ...
+	 *   } finally {
+	 *     if (in != null) {
+	 *       in.close();
+	 *     }
+	 *   }
+	 * </pre>
+	 */
+	private static void example(boolean t) {
+		Object in = null;
+		try {
+			in = open(t);
+		} finally { // assertFinally() tag("example.0")
+			if (in != null) { // assertFullyCovered(0, 2)
+				nop(); // assertFullyCovered() tag("example.2")
+			} // assertEmpty()
+		} // assertEmpty()
+	}
+
+	private static Object open(boolean t) {
+		ex(t);
+		return new Object();
+	}
+
+	/**
+	 * GOTO instructions at the end of duplicates of finally block might have
+	 * line number of a last instruction of finally block and hence lead to
+	 * unexpected coverage results, like for example in case of ECJ for
+	 * {@link FinallyTarget#catchNotExecuted()},
+	 * {@link FinallyTarget#emptyCatch()}. So we decided to ignore them, even if
+	 * they can correspond to a real break statement.
+	 * <p>
+	 * See also <a href=
+	 * "https://bugs.openjdk.java.net/browse/JDK-8180141">JDK-8180141</a> and
+	 * <a href=
+	 * "https://bugs.openjdk.java.net/browse/JDK-7008643">JDK-7008643</a>.
+	 */
+	private static void breakStatement() {
+		for (int i = 0; i < 1; i++) { // tag("breakStatement.for")
+			try {
+				if (f()) {
+					break; // assertEmpty() tag("breakStatement")
+				}
+			} finally {
+				nop("finally"); // assertFullyCovered() tag("breakStatement.1")
+			} // assertEmpty() tag("breakStatement.2")
+		}
+	}
+
+	private static void catchNotExecuted() {
+		try {
+			nop("try");
+		} catch (Exception e) { // tag("catchNotExecuted")
+			nop("catch"); // assertNotCovered()
+		} finally { // assertEmpty()
+			nop("finally"); // assertFullyCovered() tag("catchNotExecuted.1")
+		} // assertEmpty() tag("catchNotExecuted.2")
+	}
+
+	private static void emptyCatch() {
+		try {
+			nop("try");
+		} catch (Exception e) { // tag("emptyCatch")
+			/* empty */
+		} finally { // assertEmpty()
+			nop("finally"); // assertFullyCovered() tag("emptyCatch.1")
+		} // assertEmpty() tag("emptyCatch.2")
+	}
+
+	private static void twoRegions() {
+		try {
+			/* jump to another region associated with same handler: */
+			if (t()) { // assertFullyCovered(1, 1)
+				nop(); // assertFullyCovered()
+				return; // assertTwoRegionsReturn1()
+			} else {
+				nop(); // assertNotCovered()
+				return; // assertTwoRegionsReturn2()
+			}
+		} finally { // assertEmpty()
+			nop(); // assertTwoRegions1()
+		} // assertEmpty()
+	}
+
+	private static void nested() {
+		try {
+			nop();
+		} finally { // assertFinally() tag("nested.0")
+			try { // assertEmpty()
+				nop(); // assertFullyCovered()
+			} finally { // assertFinally() tag("nested.3")
+				nop(); // assertFullyCovered()
+			} // assertEmpty() tag("nested.5")
+		} // assertEmpty() tag("nested.6")
+	}
+
+	private static void emptyTry() {
+		try {
+			/* empty */
+		} finally { // assertEmpty()
+			nop(); // assertEmptyTry1()
+		} // assertEmptyTry2() tag("emptyTry.2")
+	}
+
+	@SuppressWarnings("finally")
+	private static void alwaysCompletesAbruptly() {
+		try {
+			nop();
+		} finally { // assertAlwaysCompletesAbruptly0()tag("alwaysCompletesAbruptly.0")
+			return; // assertAlwaysCompletesAbruptly1()
+		} // assertEmpty()
+	}
+
+	public static void main(String[] args) {
+		example(false);
+		try {
+			example(true);
+		} catch (Exception ignore) {
+		}
+
+		breakStatement();
+
+		catchNotExecuted();
+
+		emptyCatch();
+
+		twoRegions();
+
+		nested();
+
+		emptyTry();
+
+		alwaysCompletesAbruptly();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target08.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ImplicitFieldInitializationTarget.java
similarity index 61%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target08.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ImplicitFieldInitializationTarget.java
index 1fe938a..4643345 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target08.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/ImplicitFieldInitializationTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,23 +9,23 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
 /**
  * This test target has instance members with implicit initializers.
  */
-public class Target08 { // $line-classdef$
+public class ImplicitFieldInitializationTarget { // assertFullyCovered()
 
-	Object field1; // $line-field1$
+	Object field1; // assertEmpty()
 
-	Object field2 = this; // $line-field2$
+	Object field2 = this; // assertFullyCovered()
 
-	int field3; // $line-field3$
+	int field3; // assertEmpty()
 
-	int field4 = 2000; // $line-field4$
+	int field4 = 2000; // assertFullyCovered()
 
 	public static void main(String[] args) {
-		new Target08();
+		new ImplicitFieldInitializationTarget();
 	}
 
 }
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/InterfaceClassInitializerTarget.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/InterfaceClassInitializerTarget.java
new file mode 100644
index 0000000..81bcda8
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/InterfaceClassInitializerTarget.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java5.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.i1;
+
+/**
+ * This test target is an interface with a class initializer.
+ */
+public interface InterfaceClassInitializerTarget {
+
+	/* No code required to initialize these fields: */
+
+	static final int CONST1 = 12345; // assertEmpty()
+
+	static final String CONST2 = "const"; // assertEmpty()
+
+	/* These fields are initialized within <clinit> */
+
+	static final int CONST3 = i1(); // assertFullyCovered()
+
+	static final Object CONST4 = new Object(); // assertFullyCovered()
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target12.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/StructuredLockingTarget.java
similarity index 85%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target12.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/StructuredLockingTarget.java
index 5ee2e32..76b57f9 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target12.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/StructuredLockingTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,14 +9,14 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
 import static org.jacoco.core.test.validation.targets.Stubs.nop;
 
 /**
  * This target uses synchronized blocks which compile to try/catch statements.
  */
-public class Target12 {
+public class StructuredLockingTarget {
 
 	static void simple() {
 		Object lock1 = new Object();
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synchronized.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/SynchronizedTarget.java
similarity index 62%
rename from org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synchronized.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/SynchronizedTarget.java
index b2d503f..b9b9ce6 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synchronized.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/SynchronizedTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.filter.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
 import static org.jacoco.core.test.validation.targets.Stubs.ex;
 import static org.jacoco.core.test.validation.targets.Stubs.nop;
@@ -19,28 +19,29 @@
 /**
  * This test target is a synchronized statement.
  */
-public class Synchronized {
+public class SynchronizedTarget {
 
 	private static final Object lock = new Object();
 
 	private static void normal() {
-		nop(); // $line-before$
-		synchronized (lock) { // $line-monitorEnter$
-			nop(); // $line-body$
-		} // $line-monitorExit$
-		nop(); // $line-after$
+		nop(); // assertFullyCovered()
+		/* when compiled with ECJ next line covered partly without filter: */
+		synchronized (lock) { // assertFullyCovered()
+			nop(); // assertFullyCovered()
+		} // assertMonitorExit()
+		nop(); // assertFullyCovered()
 	}
 
 	private static void explicitException() {
-		synchronized (lock) { // $line-explicitException.monitorEnter$
-			throw new StubException(); // $line-explicitException.exception$
-		} // $line-explicitException.monitorExit$
+		synchronized (lock) { // assertFullyCovered()
+			throw new StubException(); // assertFullyCovered()
+		} // assertEmpty()
 	}
 
 	private static void implicitException() {
-		synchronized (lock) { // $line-implicitException.monitorEnter$
-			ex(); // $line-implicitException.exception$
-		} // $line-implicitException.monitorExit$
+		synchronized (lock) { // assertMonitorEnterImplicitException()
+			ex(); // assertNotCovered()
+		} // assertMonitorExitImplicitException()
 	}
 
 	public static void main(String[] args) {
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synthetic.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/SyntheticTarget.java
similarity index 68%
rename from org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synthetic.java
rename to org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/SyntheticTarget.java
index 6e2f626..efede92 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synthetic.java
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/targets/SyntheticTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,25 +9,25 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.filter.targets;
+package org.jacoco.core.test.validation.java5.targets;
 
 /**
- * This test target is synthetic methods.
+ * This test target results in synthetic methods.
  */
-public class Synthetic { // $line-classdef$
+public class SyntheticTarget { // assertEmpty()
 
-	private static int counter; // $line-field$
+	private static int counter; // assertEmpty()
 
 	/**
-	 * {@link org.jacoco.core.test.validation.targets.Target06 Default
-	 * constructor will refer to a line of class definition}, so that we define
-	 * constructor explicitly in order to verify that we filter all other
+	 * {@link org.jacoco.core.test.validation.java5.targets.ConstructorsTarget
+	 * Default constructor will refer to a line of class definition}, so that we
+	 * define constructor explicitly in order to verify that we filter all other
 	 * constructions here that might refer to line of class definition.
 	 */
-	private Synthetic() {
+	private SyntheticTarget() {
 	}
 
-	static class Inner extends Synthetic { // $line-inner.classdef$
+	static class Inner extends SyntheticTarget { // assertEmpty()
 
 		Inner() {
 		}
diff --git a/org.jacoco.core.test.validation.java7/.classpath b/org.jacoco.core.test.validation.java7/.classpath
new file mode 100644
index 0000000..c60c5da
--- /dev/null
+++ b/org.jacoco.core.test.validation.java7/.classpath
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/classes" path="src">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.jacoco.core.test.validation.java7/.project b/org.jacoco.core.test.validation.java7/.project
new file mode 100644
index 0000000..5ce971f
--- /dev/null
+++ b/org.jacoco.core.test.validation.java7/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.jacoco.core.test.validation.java7</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>.settings</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/org.jacoco.core.test/.settings</locationURI>
+		</link>
+	</linkedResources>
+</projectDescription>
diff --git a/org.jacoco.core.test.validation.java7/pom.xml b/org.jacoco.core.test.validation.java7/pom.xml
new file mode 100644
index 0000000..3f58d8b
--- /dev/null
+++ b/org.jacoco.core.test.validation.java7/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+   All rights reserved. This program and the accompanying materials
+   are made available under the terms of the Eclipse Public License v1.0
+   which accompanies this distribution, and is available at
+   http://www.eclipse.org/legal/epl-v10.html
+
+   Contributors:
+      Evgeny Mandrikov - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.jacoco</groupId>
+    <artifactId>org.jacoco.core.test.validation</artifactId>
+    <version>0.8.4</version>
+    <relativePath>../org.jacoco.core.test.validation</relativePath>
+  </parent>
+
+  <artifactId>org.jacoco.core.test.validation.java7</artifactId>
+
+  <name>JaCoCo :: Test :: Core :: Validation Java 7</name>
+
+  <properties>
+    <bytecode.version>7</bytecode.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>org.jacoco.core.test</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/StringSwitchTest.java b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/StringSwitchTest.java
new file mode 100644
index 0000000..2e42946
--- /dev/null
+++ b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/StringSwitchTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java7;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java7.targets.StringSwitchTarget;
+
+/**
+ * Test of filtering of a bytecode that is generated for a String in switch
+ * statement.
+ */
+public class StringSwitchTest extends ValidationTestBase {
+
+	public StringSwitchTest() {
+		super(StringSwitchTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/TryWithResourcesTest.java b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/TryWithResourcesTest.java
new file mode 100644
index 0000000..47b09d4
--- /dev/null
+++ b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/TryWithResourcesTest.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java7;
+
+import org.jacoco.core.test.validation.Source.Line;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java7.targets.TryWithResourcesTarget;
+
+/**
+ * Test of filtering of a bytecode that is generated for a try-with-resources
+ * statement.
+ */
+public class TryWithResourcesTest extends ValidationTestBase {
+
+	public TryWithResourcesTest() {
+		super(TryWithResourcesTarget.class);
+	}
+
+	public void assertTry(final Line line) {
+		// without filter this line is covered partly:
+		if (!isJDKCompiler || JAVA_VERSION.isBefore("11")) {
+			assertFullyCovered(line);
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+	public void assertReturnInBodyClose(final Line line) {
+		// without filter next line has branches:
+		if (isJDKCompiler) {
+			// https://bugs.openjdk.java.net/browse/JDK-8134759
+			// javac 7 and 8 up to 8u92 are affected
+			if (JAVA_VERSION.isBefore("1.8.0_92")) {
+				assertFullyCovered(line);
+			} else {
+				assertEmpty(line);
+			}
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+	public void assertHandwritten(final Line line) {
+		if (isJDKCompiler) {
+			assertEmpty(line);
+		} else {
+			assertFullyCovered(line, 1, 1);
+		}
+	}
+
+	public void assertEmptyClose(final Line line) {
+		if (!isJDKCompiler) {
+			assertPartlyCovered(line, 7, 1);
+		} else if (JAVA_VERSION.isBefore("8")) {
+			assertPartlyCovered(line, 6, 2);
+		} else if (JAVA_VERSION.isBefore("9")) {
+			assertPartlyCovered(line, 2, 2);
+		} else {
+			assertFullyCovered(line);
+		}
+	}
+
+	public void assertThrowInBodyClose(final Line line) {
+		// not filtered
+		if (!isJDKCompiler) {
+			assertNotCovered(line, 6, 0);
+		} else if (JAVA_VERSION.isBefore("9")) {
+			assertNotCovered(line, 4, 0);
+		} else if (JAVA_VERSION.isBefore("11")) {
+			assertNotCovered(line);
+		} else {
+			assertEmpty(line);
+		}
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java
new file mode 100644
index 0000000..a3b57bc
--- /dev/null
+++ b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/StringSwitchTarget.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java7.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+/**
+ * This test target is a switch statement with a String.
+ */
+public class StringSwitchTarget {
+
+	private static void covered(Object s) {
+		switch (String.valueOf(s)) { // assertFullyCovered(0, 4)
+		case "a":
+			nop("case a"); // assertFullyCovered()
+			break;
+		case "b":
+			nop("case b"); // assertFullyCovered()
+			break;
+		case "\0a":
+			nop("case \0a"); // assertFullyCovered()
+			break;
+		default:
+			nop("case default"); // assertFullyCovered()
+			break;
+		}
+	}
+
+	private static void notCovered(Object s) {
+		switch (String.valueOf(s)) { // assertNotCovered(4, 0)
+		case "a":
+			nop("case a");
+			break;
+		case "b":
+			nop("case b");
+			break;
+		case "\0a":
+			nop("case \0a");
+			break;
+		default:
+			nop("default");
+			break;
+		}
+	}
+
+	private static void handwritten(String s) {
+		int c = -1;
+		switch (s.hashCode()) { // assertFullyCovered(2, 1)
+		case 97:
+			if ("a".equals(s)) { // assertFullyCovered(1, 1)
+				c = 0;
+			} else if ("\0a".equals(s)) {
+				c = 1;
+			}
+			break;
+		case 98:
+			if ("b".equals(s)) {
+				c = 2;
+			}
+			break;
+		}
+		switch (c) { // assertFullyCovered(3, 1)
+		case 0:
+			nop("case a"); // assertFullyCovered()
+			break;
+		case 1:
+			nop("case \0a"); // assertNotCovered()
+			break;
+		case 2:
+			nop("case b");
+			break;
+		default:
+			nop("default");
+			break;
+		}
+	}
+
+	/**
+	 * In this case javac generates <code>LOOKUPSWITCH</code> for second switch.
+	 */
+	private static void lookupswitch(Object s) {
+		switch (String.valueOf(s)) { // assertNotCovered(3, 0)
+		case "a":
+			nop("case a");
+			break;
+		case "b":
+			nop("case b");
+			break;
+		default:
+			nop("default");
+			break;
+		}
+	}
+
+	private static void default_is_first(Object s) {
+		switch (String.valueOf(s)) { // assertFullyCovered(0, 2)
+		default:
+			nop("default");
+			break;
+		case "a":
+			nop("case a");
+			break;
+		}
+	}
+
+	public static void main(String[] args) {
+		covered("");
+		covered("a");
+		covered("b");
+		covered("\0a");
+
+		handwritten("a");
+
+		default_is_first("");
+		default_is_first("a");
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/TryWithResourcesTarget.java b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/TryWithResourcesTarget.java
new file mode 100644
index 0000000..061db23
--- /dev/null
+++ b/org.jacoco.core.test.validation.java7/src/org/jacoco/core/test/validation/java7/targets/TryWithResourcesTarget.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java7.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * This test target is a try-with-resources statement.
+ */
+public class TryWithResourcesTarget {
+
+	private static class Resource implements Closeable {
+		@Override
+		public void close() {
+		}
+	}
+
+	/**
+	 * Closing performed using {@link org.objectweb.asm.Opcodes#INVOKEVIRTUAL}
+	 * or {@link org.objectweb.asm.Opcodes#INVOKEINTERFACE} depending on a class
+	 * of resource.
+	 */
+	private static Object test() throws Exception {
+		nop(); // assertFullyCovered()
+		try ( // assertTry()
+				Resource r1 = new Resource(); // assertFullyCovered()
+				Closeable r2 = new Resource(); // assertFullyCovered()
+				AutoCloseable r3 = new Resource() // assertFullyCovered()
+		) {
+			return read(r1, r2, r3); // assertFullyCovered()
+			/* without filter next line has branches: */
+		} // assertEmpty()
+		catch (Exception e) {
+			nop(); // assertNotCovered()
+			throw e;
+		} finally {
+			nop(); // assertFullyCovered()
+		}
+	}
+
+	private static void test2() throws Exception {
+		nop(); // assertFullyCovered()
+		try ( // assertTry()
+				Resource r1 = new Resource(); // assertFullyCovered()
+				Closeable r2 = new Resource(); // assertFullyCovered()
+				AutoCloseable r3 = new Resource() // assertFullyCovered()
+		) {
+			read(r1, r2, r3); // assertFullyCovered()
+			/* without filter next line has branches: */
+		} // assertEmpty()
+		catch (Exception e) {
+			nop(); // assertNotCovered()
+		} finally {
+			nop(); // assertFullyCovered()
+		}
+		nop(); // assertFullyCovered()
+	}
+
+	private static Object returnInBody() throws IOException {
+		try ( // assertTry()
+				Closeable r = new Resource() // assertFullyCovered()
+		) {
+			return read(r); // assertFullyCovered()
+		} // assertReturnInBodyClose()
+	}
+
+	private static void nested() {
+		try ( // assertTry()
+				Resource r1 = new Resource() // assertFullyCovered()
+		) {
+
+			try ( // assertTry()
+					Resource r2 = new Resource() // assertFullyCovered()
+			) {
+				nop(r1.toString() + r2.toString()); // assertFullyCovered()
+			} // assertEmpty()
+			catch (Exception e) {
+				nop(); // assertNotCovered()
+			} finally {
+				nop(); // assertFullyCovered()
+			}
+
+		} // assertEmpty()
+		catch (Exception e) {
+			nop(); // assertNotCovered()
+		} finally {
+
+			try ( // assertTry()
+					Resource r2 = new Resource() // assertFullyCovered()
+			) {
+				nop(r2); // assertFullyCovered()
+			} // assertEmpty()
+			catch (Exception e) {
+				nop(); // assertNotCovered()
+			} finally {
+				nop(); // assertFullyCovered()
+			}
+
+		}
+	}
+
+	/**
+	 * In this case bytecode will contain 3 copies of <code>finally</code>
+	 * block, each containing 2 branches, resulting in 6 branches in total. One
+	 * could think that this is artifact of try-with-resources, but the same
+	 * happens without it.
+	 */
+	private static Object returnInCatch() {
+		try ( // assertTry()
+				Resource r = new Resource() // assertFullyCovered()
+		) {
+			read(r);
+			/* without filter next line has branches: */
+		} // assertEmpty()
+		catch (Exception e) {
+			return null;
+		} finally {
+			nop(!f()); // assertPartlyCovered(1, 1)
+		}
+
+		try { // assertEmpty()
+			read(new Resource());
+		} catch (Exception e) {
+			return null;
+		} finally {
+			nop(!f()); // assertPartlyCovered(1, 1)
+		}
+
+		return null;
+	}
+
+	private static Object read(Object r1, Object r2, Object r3) {
+		return r1.toString() + r2.toString() + r3.toString();
+	}
+
+	private static Object read(Object r1) {
+		return r1.toString();
+	}
+
+	/*
+	 * Corner cases
+	 */
+
+	private static void empty() throws Exception {
+		try ( // assertTry()
+				Closeable r = new Resource() // assertFullyCovered()
+		) {
+		} // assertEmptyClose()
+	}
+
+	private static void handwritten() throws IOException {
+		Closeable r = new Resource();
+		Throwable primaryExc = null;
+		try {
+			nop(r);
+		} catch (Throwable t) {
+			primaryExc = t;
+			throw t;
+		} finally {
+			if (r != null) { // assertHandwritten()
+				if (primaryExc != null) {
+					try {
+						r.close();
+					} catch (Throwable suppressedExc) {
+						primaryExc.addSuppressed(suppressedExc);
+					}
+				} else {
+					r.close();
+				}
+			}
+		}
+	}
+
+	private static void throwInBody() throws IOException {
+		try ( // assertNotCovered()
+				Closeable r = new Resource()) {
+			nop(r);
+			throw new RuntimeException();
+		} // assertThrowInBodyClose()
+	}
+
+	public static void main(String[] args) throws Exception {
+		test();
+		test2();
+		returnInBody();
+		nested();
+
+		returnInCatch();
+
+		empty();
+		handwritten();
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java8/.classpath b/org.jacoco.core.test.validation.java8/.classpath
new file mode 100644
index 0000000..9f0c38b
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/.classpath
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/classes" path="src">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.jacoco.core.test.validation.java8/.project b/org.jacoco.core.test.validation.java8/.project
new file mode 100644
index 0000000..deab0f7
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.jacoco.core.test.validation.java8</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>.settings</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/org.jacoco.core.test/.settings</locationURI>
+		</link>
+	</linkedResources>
+</projectDescription>
diff --git a/org.jacoco.core.test.validation.java8/pom.xml b/org.jacoco.core.test.validation.java8/pom.xml
new file mode 100644
index 0000000..5edd498
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+   All rights reserved. This program and the accompanying materials
+   are made available under the terms of the Eclipse Public License v1.0
+   which accompanies this distribution, and is available at
+   http://www.eclipse.org/legal/epl-v10.html
+
+   Contributors:
+      Evgeny Mandrikov - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.jacoco</groupId>
+    <artifactId>org.jacoco.core.test.validation</artifactId>
+    <version>0.8.4</version>
+    <relativePath>../org.jacoco.core.test.validation</relativePath>
+  </parent>
+
+  <artifactId>org.jacoco.core.test.validation.java8</artifactId>
+
+  <name>JaCoCo :: Test :: Core :: Validation Java 8</name>
+
+  <properties>
+    <bytecode.version>8</bytecode.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>org.jacoco.core.test</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/AnnotationOnLocalVariableTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/AnnotationOnLocalVariableTest.java
new file mode 100644
index 0000000..e3a3221
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/AnnotationOnLocalVariableTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java8;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java8.targets.AnnotationOnLocalVariableTarget;
+
+/**
+ * Test of ASM bug
+ * <a href="https://gitlab.ow2.org/asm/asm/issues/317815">#317815</a>
+ */
+public class AnnotationOnLocalVariableTest extends ValidationTestBase {
+
+	public AnnotationOnLocalVariableTest() {
+		super(AnnotationOnLocalVariableTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/BadCycleInterfaceTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/BadCycleInterfaceTest.java
new file mode 100644
index 0000000..96896f6
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/BadCycleInterfaceTest.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java8;
+
+import org.jacoco.core.test.validation.Source.Line;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java8.targets.BadCycleInterfaceTarget;
+import org.junit.Test;
+
+/**
+ * Test of "bad cycles" with interfaces.
+ */
+public class BadCycleInterfaceTest extends ValidationTestBase {
+
+	public BadCycleInterfaceTest() throws Exception {
+		super(BadCycleInterfaceTarget.class);
+	}
+
+	@Test
+	public void method_execution_sequence() throws Exception {
+		if (JAVA_VERSION.isBefore("1.8.0_152")) {
+			assertLogEvents("baseclinit", "childdefaultmethod", "childclinit",
+					"childstaticmethod");
+		} else {
+			assertLogEvents("childclinit", "childstaticmethod");
+		}
+	}
+
+	public void assertBaseClInit(final Line line) {
+		if (JAVA_VERSION.isBefore("1.8.0_152")) {
+			// Incorrect interpetation of JVMS 5.5 in JDK 8 causes a default
+			// method to be called before the static initializer of an interface
+			// (see JDK-8098557 and JDK-8164302):
+			assertFullyCovered(line);
+
+		} else {
+			// This shouldn't happen with JDK 9 (see also JDK-8043275)
+			// and starting with JDK 8u152 (see JDK-8167607):
+			assertEmpty(line);
+		}
+	}
+
+	public void assertChildDefault(final Line line) throws Exception {
+		if (JAVA_VERSION.isBefore("1.8.0_152")) {
+			// Incorrect interpetation of JVMS 5.5 in JDK 8 causes a default
+			// method to be called before the static initializer of an interface
+			// (see JDK-8098557 and JDK-8164302):
+			assertFullyCovered(line);
+
+		} else {
+			// This shouldn't happen with JDK 9 (see also JDK-8043275)
+			// and starting with JDK 8u152 (see JDK-8167607):
+			assertNotCovered(line);
+		}
+	}
+
+}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/BootstrapMethodReferenceTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/BootstrapMethodReferenceTest.java
similarity index 84%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/BootstrapMethodReferenceTest.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/BootstrapMethodReferenceTest.java
index 7974424..e723afa 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/BootstrapMethodReferenceTest.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/BootstrapMethodReferenceTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java8;
 
 import static org.junit.Assert.assertEquals;
 
@@ -42,11 +42,13 @@
  */
 public class BootstrapMethodReferenceTest {
 
-	private final IRuntime runtime = new SystemPropertiesRuntime();
-	private final Instrumenter instrumenter = new Instrumenter(runtime);
+	private IRuntime runtime;
+	private Instrumenter instrumenter;
 
 	@Before
 	public void setup() throws Exception {
+		runtime = new SystemPropertiesRuntime();
+		instrumenter = new Instrumenter(runtime);
 		runtime.startup(new RuntimeData());
 	}
 
@@ -91,13 +93,14 @@
 	private static int run(final String className, final byte[] bytes)
 			throws ClassNotFoundException, NoSuchMethodException,
 			InvocationTargetException, IllegalAccessException {
-		return (Integer) new TargetLoader().add(className, bytes)
-				.getMethod("run").invoke(null);
+		final Integer result = (Integer) new TargetLoader()
+				.add(className, bytes).getMethod("run").invoke(null);
+		return result.intValue();
 	}
 
 	/**
 	 * Adds code that triggers usage of
-	 * {@link org.objectweb.asm.MethodWriter#INSERTED_FRAMES} during
+	 * {@link org.objectweb.asm.MethodWriter#COMPUTE_INSERTED_FRAMES} during
 	 * instrumentation.
 	 */
 	private static void addCauseOfResizeInstructions(final MethodVisitor mv) {
@@ -111,14 +114,13 @@
 		mv.visitLabel(target);
 	}
 
-	@SuppressWarnings("unused")
 	public static CallSite bootstrap(final MethodHandles.Lookup caller,
 			final String name, final MethodType type) throws Exception {
-		return new ConstantCallSite(caller.findStatic(BootstrapMethodReferenceTest.class,
-				"callTarget", MethodType.methodType(int.class)));
+		return new ConstantCallSite(
+				caller.findStatic(BootstrapMethodReferenceTest.class,
+						"callTarget", MethodType.methodType(int.class)));
 	}
 
-	@SuppressWarnings("unused")
 	public static int callTarget() {
 		return 42;
 	}
diff --git a/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/InterfaceDefaultMethodsTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/InterfaceDefaultMethodsTest.java
new file mode 100644
index 0000000..b047ceb
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/InterfaceDefaultMethodsTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java8;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java8.targets.InterfaceDefaultMethodsTarget;
+
+/**
+ * Tests of static initializer and default methods in interfaces.
+ */
+public class InterfaceDefaultMethodsTest extends ValidationTestBase {
+
+	public InterfaceDefaultMethodsTest() {
+		super(InterfaceDefaultMethodsTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/InterfaceOnlyDefaultMethodsTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/InterfaceOnlyDefaultMethodsTest.java
similarity index 60%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/InterfaceOnlyDefaultMethodsTest.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/InterfaceOnlyDefaultMethodsTest.java
index e572c63..6915ec9 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/InterfaceOnlyDefaultMethodsTest.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/InterfaceOnlyDefaultMethodsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,11 +9,10 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java8;
 
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.InterfaceOnlyDefaultMethodsTarget;
-import org.junit.Test;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java8.targets.InterfaceOnlyDefaultMethodsTarget;
 
 /**
  * Tests of default methods in interfaces.
@@ -21,13 +20,7 @@
 public class InterfaceOnlyDefaultMethodsTest extends ValidationTestBase {
 
 	public InterfaceOnlyDefaultMethodsTest() {
-		super("src-java8", InterfaceOnlyDefaultMethodsTarget.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-		assertLine("m1", ICounter.FULLY_COVERED);
-		assertLine("m2", ICounter.NOT_COVERED);
+		super(InterfaceOnlyDefaultMethodsTarget.class);
 	}
 
 }
diff --git a/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaExpressionsTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaExpressionsTest.java
new file mode 100644
index 0000000..1128f70
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaExpressionsTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java8;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java8.targets.LambdaExpressionsTarget;
+
+/**
+ * Tests for different lambda expressions.
+ */
+public class LambdaExpressionsTest extends ValidationTestBase {
+
+	public LambdaExpressionsTest() {
+		super(LambdaExpressionsTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/LambdaInInterfaceTest.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaInInterfaceTest.java
similarity index 65%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/LambdaInInterfaceTest.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaInInterfaceTest.java
index afa2e98..9e24240 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/LambdaInInterfaceTest.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/LambdaInInterfaceTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,11 +9,10 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.test.validation.java8;
 
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.LambdaInInterfaceTarget;
-import org.junit.Test;
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.java8.targets.LambdaInInterfaceTarget;
 
 /**
  * Tests a constant with a lambda value in an interface.
@@ -21,7 +20,7 @@
 public class LambdaInInterfaceTest extends ValidationTestBase {
 
 	public LambdaInInterfaceTest() {
-		super("src-java8", LambdaInInterfaceTarget.class);
+		super(LambdaInInterfaceTarget.class);
 	}
 
 	@Override
@@ -29,12 +28,4 @@
 		((Runnable) targetClass.getField("RUN").get(null)).run();
 	}
 
-	@Test
-	public void testCoverageResult() {
-
-		// Coverage of lambda body
-		assertLine("lambdabody", ICounter.FULLY_COVERED);
-
-	}
-
 }
diff --git a/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/AnnotationOnLocalVariableTarget.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/AnnotationOnLocalVariableTarget.java
new file mode 100644
index 0000000..976825b
--- /dev/null
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/AnnotationOnLocalVariableTarget.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.java8.targets;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This test target contains annotation on local variable.
+ */
+public class AnnotationOnLocalVariableTarget {
+
+	@Documented
+	@Retention(RetentionPolicy.CLASS)
+	@Target(ElementType.TYPE_USE)
+	@interface NonNull {
+	}
+
+	private static Object legacy() {
+		return new Object();
+	}
+
+	public static void main(String[] args) {
+		@NonNull
+		Object o = legacy(); // assertFullyCovered()
+	}
+
+}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/BadCycleInterface.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/BadCycleInterfaceTarget.java
similarity index 66%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/BadCycleInterface.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/BadCycleInterfaceTarget.java
index d7e7a74..24515a0 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/BadCycleInterface.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/BadCycleInterfaceTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,14 +9,16 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java8.targets;
 
-public class BadCycleInterface {
+import org.jacoco.core.test.validation.targets.Stubs;
+
+public class BadCycleInterfaceTarget {
 
 	public interface Base {
 		static final Object BASE_CONST = new Child() {
 			{
-				Stubs.logEvent("baseclinit"); // $line-baseclinit$
+				Stubs.logEvent("baseclinit"); // assertBaseClInit()
 			}
 		}.childDefaultMethod();
 
@@ -27,17 +29,17 @@
 	public interface Child extends Base {
 		static final Object CHILD_CONST = new Object() {
 			{
-				Stubs.logEvent("childclinit"); // $line-childclinit$
+				Stubs.logEvent("childclinit"); // assertFullyCovered()
 			}
 		};
 
 		default Object childDefaultMethod() {
-			Stubs.logEvent("childdefaultmethod"); // $line-childdefault$
+			Stubs.logEvent("childdefaultmethod"); // assertChildDefault()
 			return null;
 		}
 
 		static void childStaticMethod() {
-			Stubs.logEvent("childstaticmethod"); // $line-childstatic$
+			Stubs.logEvent("childstaticmethod"); // assertFullyCovered()
 		}
 	}
 
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/InterfaceDefaultMethodsTarget.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/InterfaceDefaultMethodsTarget.java
similarity index 76%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/InterfaceDefaultMethodsTarget.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/InterfaceDefaultMethodsTarget.java
index 2e95299..6b44830 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/InterfaceDefaultMethodsTarget.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/InterfaceDefaultMethodsTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,23 +9,24 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java8.targets;
 
 import static org.jacoco.core.test.validation.targets.Stubs.i1;
 
 /**
- * This test target is an interface with a class initializer and default methods.
+ * This test target is an interface with a class initializer and default
+ * methods.
  */
 public interface InterfaceDefaultMethodsTarget {
 
-	public static final int CONST = i1(); // $line-clinit$
+	public static final int CONST = i1(); // assertFullyCovered()
 
 	default void m1() {
-		return; // $line-m1$
+		return; // assertFullyCovered()
 	}
 
 	default void m2() {
-		return; // $line-m2$
+		return; // assertNotCovered()
 	}
 
 	public class Impl implements InterfaceDefaultMethodsTarget {
@@ -34,7 +35,7 @@
 			m1();
 		}
 	}
-	
+
 	public static void main(String[] args) {
 		new Impl();
 	}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/InterfaceOnlyDefaultMethodsTarget.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/InterfaceOnlyDefaultMethodsTarget.java
similarity index 78%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/InterfaceOnlyDefaultMethodsTarget.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/InterfaceOnlyDefaultMethodsTarget.java
index 5fa48fb..bd50d43 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/InterfaceOnlyDefaultMethodsTarget.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/InterfaceOnlyDefaultMethodsTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,21 +9,21 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java8.targets;
 
 /**
  * This test target is an interface with only default methods.
  */
 public interface InterfaceOnlyDefaultMethodsTarget {
 
-	// no <clinit>, only default methods:
+	/* no <clinit>, only default methods: */
 
 	default void m1() {
-		return; // $line-m1$
+		return; // assertFullyCovered()
 	}
 
 	default void m2() {
-		return; // $line-m2$
+		return; // assertNotCovered()
 	}
 
 	public class Impl implements InterfaceOnlyDefaultMethodsTarget {
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/LambdaExpressionsTarget.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaExpressionsTarget.java
similarity index 81%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/LambdaExpressionsTarget.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaExpressionsTarget.java
index bcb65b6..719237f 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/LambdaExpressionsTarget.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaExpressionsTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java8.targets;
 
 import static org.jacoco.core.test.validation.targets.Stubs.exec;
 import static org.jacoco.core.test.validation.targets.Stubs.noexec;
@@ -23,11 +23,11 @@
 	public static void main(String[] args) {
 
 		exec(() -> {
-			nop(); // $line-executedlambdabody$
+			nop(); // assertFullyCovered()
 		});
-		
+
 		noexec(() -> {
-			nop(); // $line-notexecutedlambdabody$
+			nop(); // assertNotCovered()
 		});
 
 	}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/LambdaInInterfaceTarget.java b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaInInterfaceTarget.java
similarity index 82%
rename from org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/LambdaInInterfaceTarget.java
rename to org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaInInterfaceTarget.java
index 23edc6d..0bafd43 100644
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/targets/LambdaInInterfaceTarget.java
+++ b/org.jacoco.core.test.validation.java8/src/org/jacoco/core/test/validation/java8/targets/LambdaInInterfaceTarget.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *    Marc R. Hoffmann - initial API and implementation
  *    
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.java8.targets;
 
 import static org.jacoco.core.test.validation.targets.Stubs.nop;
 
@@ -19,7 +19,7 @@
 public interface LambdaInInterfaceTarget {
 
 	public static final Runnable RUN = () -> {
-		nop(); // $line-lambdabody$
+		nop(); // assertFullyCovered()
 	};
 
 }
diff --git a/org.jacoco.core.test.validation.kotlin/.classpath b/org.jacoco.core.test.validation.kotlin/.classpath
new file mode 100644
index 0000000..80ba0e5
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/.classpath
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/classes" path="src">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.jacoco.core.test.validation.kotlin/.project b/org.jacoco.core.test.validation.kotlin/.project
new file mode 100644
index 0000000..1454c19
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.jacoco.core.test.validation.kotlin</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>.settings</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/org.jacoco.core.test/.settings</locationURI>
+		</link>
+	</linkedResources>
+</projectDescription>
diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml
new file mode 100644
index 0000000..0541e00
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+   All rights reserved. This program and the accompanying materials
+   are made available under the terms of the Eclipse Public License v1.0
+   which accompanies this distribution, and is available at
+   http://www.eclipse.org/legal/epl-v10.html
+
+   Contributors:
+      Evgeny Mandrikov - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.jacoco</groupId>
+    <artifactId>org.jacoco.core.test.validation</artifactId>
+    <version>0.8.4</version>
+    <relativePath>../org.jacoco.core.test.validation</relativePath>
+  </parent>
+
+  <artifactId>org.jacoco.core.test.validation.kotlin</artifactId>
+
+  <name>JaCoCo :: Test :: Core :: Validation Kotlin</name>
+
+  <properties>
+    <bytecode.version>6</bytecode.version>
+    <kotlin.version>1.3.31</kotlin.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>org.jacoco.core.test</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlin</groupId>
+      <artifactId>kotlin-stdlib</artifactId>
+      <version>${kotlin.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlinx</groupId>
+      <artifactId>kotlinx-coroutines-core</artifactId>
+      <version>1.0.1</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.jetbrains.kotlin</groupId>
+        <artifactId>kotlin-maven-plugin</artifactId>
+        <version>${kotlin.version}</version>
+        <executions>
+          <execution>
+            <id>compile</id>
+            <phase>process-sources</phase>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCallableReferenceTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCallableReferenceTest.java
new file mode 100644
index 0000000..321c717
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCallableReferenceTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinCallableReferenceTarget;
+
+/**
+ * Test of callable references.
+ */
+public class KotlinCallableReferenceTest extends ValidationTestBase {
+
+	public KotlinCallableReferenceTest() {
+		super(KotlinCallableReferenceTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineTest.java
new file mode 100644
index 0000000..aa537d7
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinCoroutineTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinCoroutineTarget;
+
+/**
+ * Test of coroutines.
+ */
+public class KotlinCoroutineTest extends ValidationTestBase {
+
+	public KotlinCoroutineTest() {
+		super(KotlinCoroutineTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDataClassTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDataClassTest.java
new file mode 100644
index 0000000..2bb94d9
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDataClassTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Fabian Mastenbroek - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinDataClassTarget;
+
+/**
+ * Test of <code>data class</code>es.
+ */
+public class KotlinDataClassTest extends ValidationTestBase {
+
+	public KotlinDataClassTest() {
+		super(KotlinDataClassTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDefaultArgumentsTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDefaultArgumentsTest.java
new file mode 100644
index 0000000..660cd9c
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinDefaultArgumentsTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinDefaultArgumentsTarget;
+
+/**
+ * Test of functions with default arguments.
+ */
+public class KotlinDefaultArgumentsTest extends ValidationTestBase {
+
+	public KotlinDefaultArgumentsTest() {
+		super(KotlinDefaultArgumentsTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinElvisOperatorTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinElvisOperatorTest.java
new file mode 100644
index 0000000..8a0ae78
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinElvisOperatorTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinElvisOperatorTarget;
+
+/**
+ * Test of elvis operator.
+ */
+public class KotlinElvisOperatorTest extends ValidationTestBase {
+
+	public KotlinElvisOperatorTest() {
+		super(KotlinElvisOperatorTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineTest.java
new file mode 100644
index 0000000..2027611
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinInlineTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinInlineTargetKt;
+
+/**
+ * Test of <code>inline</code> functions.
+ */
+public class KotlinInlineTest extends ValidationTestBase {
+
+	public KotlinInlineTest() {
+		super(KotlinInlineTargetKt.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinLateinitTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinLateinitTest.java
new file mode 100644
index 0000000..b770ddb
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinLateinitTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Fabian Mastenbroek - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinLateinitTarget;
+
+/**
+ * Test of <code>lateinit</code> properties.
+ */
+public class KotlinLateinitTest extends ValidationTestBase {
+
+	public KotlinLateinitTest() {
+		super(KotlinLateinitTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinNotNullOperatorTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinNotNullOperatorTest.java
new file mode 100644
index 0000000..e92cee9
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinNotNullOperatorTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinNotNullOperatorTarget;
+
+/**
+ * Test of not-null assertion operator.
+ */
+public class KotlinNotNullOperatorTest extends ValidationTestBase {
+
+	public KotlinNotNullOperatorTest() {
+		super(KotlinNotNullOperatorTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCallOperatorTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCallOperatorTest.java
new file mode 100644
index 0000000..2feb555
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCallOperatorTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinSafeCallOperatorTarget;
+
+/**
+ * Test of safe call operator.
+ */
+public class KotlinSafeCallOperatorTest extends ValidationTestBase {
+
+	public KotlinSafeCallOperatorTest() {
+		super(KotlinSafeCallOperatorTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java
new file mode 100644
index 0000000..0fc1e65
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinSafeCastTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinElvisOperatorTarget;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinSafeCastTarget;
+
+/**
+ * Test of "safe" cast operator.
+ */
+public class KotlinSafeCastTest extends ValidationTestBase {
+
+	public KotlinSafeCastTest() {
+		super(KotlinSafeCastTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinTopLevelFunctionTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinTopLevelFunctionTest.java
new file mode 100644
index 0000000..473c9bb
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinTopLevelFunctionTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinTopLevelFunctionTargetKt;
+
+/**
+ * Test of top level function.
+ */
+public class KotlinTopLevelFunctionTest extends ValidationTestBase {
+
+	public KotlinTopLevelFunctionTest() {
+		super(KotlinTopLevelFunctionTargetKt.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinUnsafeCastOperatorTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinUnsafeCastOperatorTest.java
new file mode 100644
index 0000000..f7c10fd
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinUnsafeCastOperatorTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinUnsafeCastOperatorTarget;
+
+/**
+ * Test of "unsafe" cast operator.
+ */
+public class KotlinUnsafeCastOperatorTest extends ValidationTestBase {
+
+	public KotlinUnsafeCastOperatorTest() {
+		super(KotlinUnsafeCastOperatorTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenExpressionTest.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenExpressionTest.java
new file mode 100644
index 0000000..ae07b48
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/KotlinWhenExpressionTest.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin;
+
+import org.jacoco.core.test.validation.ValidationTestBase;
+import org.jacoco.core.test.validation.kotlin.targets.KotlinWhenExpressionTarget;
+
+/**
+ * Test of <code>when</code> expressions.
+ */
+public class KotlinWhenExpressionTest extends ValidationTestBase {
+
+	public KotlinWhenExpressionTest() {
+		super(KotlinWhenExpressionTarget.class);
+	}
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCallableReferenceTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCallableReferenceTarget.kt
new file mode 100644
index 0000000..b024067
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCallableReferenceTarget.kt
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import org.jacoco.core.test.validation.targets.Stubs.nop
+
+/**
+ * Test target for callable references.
+ */
+object KotlinCallableReferenceTarget {
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+
+        /*
+        Since Kotlin 1.3.30
+        anonymous class generated for callable reference is marked as synthetic
+        https://youtrack.jetbrains.com/issue/KT-28453
+        */
+        nop(::main) // assertFullyCovered(0, 0)
+
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineTarget.kt
new file mode 100644
index 0000000..6a56570
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinCoroutineTarget.kt
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import kotlinx.coroutines.runBlocking
+import org.jacoco.core.test.validation.targets.Stubs.nop
+
+/**
+ * Test target for coroutines.
+ */
+object KotlinCoroutineTarget {
+
+    private suspend fun suspendingFunction() { // assertEmpty()
+        anotherSuspendingFunction() // assertFullyCovered()
+        nop() // assertFullyCovered()
+    } // assertFullyCovered()
+
+    private suspend fun anotherSuspendingFunction() {
+        nop() // assertFullyCovered()
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+
+        runBlocking { // assertFullyCovered()
+            val x = 42
+            nop(x) // assertFullyCovered()
+            suspendingFunction() // assertFullyCovered()
+            nop(x) // assertFullyCovered()
+        } // assertFullyCovered()
+
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDataClassTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDataClassTarget.kt
new file mode 100644
index 0000000..2af6fb0
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDataClassTarget.kt
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Fabian Mastenbroek - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import org.jacoco.core.test.validation.targets.Stubs.nop
+
+/**
+ * This test target is `data class`.
+ */
+object KotlinDataClassTarget {
+
+    data class DataClass( // assertFullyCovered()
+            val valNoRead: Int, // assertNotCovered()
+            val valRead: Int,  // assertFullyCovered()
+            var varNoReadNoWrite: Int, // assertNotCovered()
+            var varNoWrite: Int, // assertPartlyCovered()
+            var varNoRead: Int, // assertPartlyCovered()
+            var varReadWrite: Int  // assertFullyCovered()
+    ) // assertEmpty()
+
+    data class DataClassOverrideNotCovered(val v: Int) {
+        override fun toString(): String = "" // assertNotCovered()
+    }
+
+    data class DataClassOverrideCovered(val v: Int) {
+        override fun toString(): String = "" // assertFullyCovered()
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        val d = DataClass(0, 0, 0, 0, 0, 0)
+        nop(d.valRead)
+        nop(d.varNoWrite)
+        d.varNoRead = 1
+        nop(d.varReadWrite)
+        d.varReadWrite = 1
+
+        DataClassOverrideNotCovered(0)
+        DataClassOverrideCovered(0).toString()
+    }
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt
new file mode 100644
index 0000000..0a11d7d
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinDefaultArgumentsTarget.kt
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * Test target for functions with default arguments.
+ */
+object KotlinDefaultArgumentsTarget {
+
+    private fun f(a: String = "a", b: String = "b") { // assertFullyCovered(0, 0)
+    }
+
+    private fun branch(a: Boolean, b: String = if (a) "a" else "b") { // assertFullyCovered(0, 2)
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        f(a = "a")
+        f(b = "b")
+        /* next invocation doesn't use synthetic method: */
+        f("a", "b")
+
+        branch(false)
+        branch(true)
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinElvisOperatorTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinElvisOperatorTarget.kt
new file mode 100644
index 0000000..5457433
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinElvisOperatorTarget.kt
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * Test target for elvis operator.
+ */
+object KotlinElvisOperatorTarget {
+
+    private fun example(x: String?): String {
+        return x ?: "" // assertFullyCovered(0, 2)
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        example("")
+        example(null)
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineTarget.kt
new file mode 100644
index 0000000..e6344f5
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinInlineTarget.kt
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import org.jacoco.core.test.validation.targets.Stubs.nop
+import org.jacoco.core.test.validation.targets.Stubs.t
+
+/**
+ * Test target for `inline` functions.
+ */
+fun main(args: Array<String>) {
+    KotlinInlineTarget.main(args)
+}
+
+inline fun inlined_top_level() {
+    nop() // assertNotCovered()
+}
+
+object KotlinInlineTarget {
+
+    inline fun inlined() {
+        nop() // assertNotCovered()
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+
+        inlined_top_level() // assertFullyCovered()
+
+        inlined() // assertFullyCovered()
+
+        /* Following inlined method for some reasons doesn't appear in SMAP: */
+        assert(t()) // assertPartlyCovered(2, 2)
+
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinLateinitTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinLateinitTarget.kt
new file mode 100644
index 0000000..349a230
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinLateinitTarget.kt
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Fabian Mastenbroek - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+import org.jacoco.core.test.validation.targets.Stubs.nop
+
+/**
+ * This test target is `lateinit` property.
+ */
+object KotlinLateinitTarget {
+    private lateinit var x: String
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        x = ""
+        nop(x) // assertFullyCovered()
+    }
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinNotNullOperatorTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinNotNullOperatorTarget.kt
new file mode 100644
index 0000000..91f5420
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinNotNullOperatorTarget.kt
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * Test target for not-null assertion operator.
+ */
+object KotlinNotNullOperatorTarget {
+
+    private fun example(x: String?): Int {
+        return x!!.length // assertFullyCovered()
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        example("")
+        try {
+            example(null)
+        } catch (e: NullPointerException) {
+        }
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt
new file mode 100644
index 0000000..d29e5eb
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCallOperatorTarget.kt
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * Test target for safe call operator.
+ */
+object KotlinSafeCallOperatorTarget {
+
+    private fun example(x: String?): Int? {
+        return x?.length // assertFullyCovered(0, 2)
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        example("")
+        example(null)
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCastTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCastTarget.kt
new file mode 100644
index 0000000..ddcc7b0
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinSafeCastTarget.kt
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * Test target for "safe" cast operator.
+ */
+object KotlinSafeCastTarget {
+
+    private fun example(x: Any?): String? {
+        return x as? String // assertFullyCovered(0, 2)
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        example("")
+        example(1)
+    }
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinTopLevelFunctionTarget.kt
similarity index 61%
copy from org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java
copy to org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinTopLevelFunctionTarget.kt
index f7b9e0a..e9e5264 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinTopLevelFunctionTarget.kt
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,15 +9,10 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
+package org.jacoco.core.test.validation.kotlin.targets
 
 /**
- * This test target is an annotation with an initializer.
+ * This test target is top level function.
  */
-public @interface AnnotationInitializer {
-
-	Object CONST = new Object(); // $line-const$
-
-	int value() default 0; // $line-value$
-
-}
+fun main(args: Array<String>) {
+} // assertFullyCovered()
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinUnsafeCastOperatorTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinUnsafeCastOperatorTarget.kt
new file mode 100644
index 0000000..aa493d7
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinUnsafeCastOperatorTarget.kt
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * This test target is "unsafe" cast operator.
+ */
+object KotlinUnsafeCastOperatorTarget {
+
+    private fun nullable(): String? {
+        return ""
+    }
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        nullable() as String // assertFullyCovered()
+    }
+
+}
diff --git a/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt
new file mode 100644
index 0000000..00ea5e2
--- /dev/null
+++ b/org.jacoco.core.test.validation.kotlin/src/org/jacoco/core/test/validation/kotlin/targets/KotlinWhenExpressionTarget.kt
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.kotlin.targets
+
+/**
+ * This test target is `when` expression.
+ */
+object KotlinWhenExpressionTarget {
+
+    private sealed class Sealed {
+        object Sealed1 : Sealed()
+        object Sealed2 : Sealed()
+    }
+
+    private fun whenSealed(p: Sealed): Int = when (p) { // assertFullyCovered()
+        is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
+        is Sealed.Sealed2 -> 2 // assertFullyCovered()
+    } // assertFullyCovered()
+
+    @Suppress("REDUNDANT_ELSE_IN_WHEN")
+    private fun whenSealedRedundantElse(p: Sealed): Int = when (p) { // assertFullyCovered()
+        is Sealed.Sealed1 -> 1 // assertFullyCovered(0, 2)
+        is Sealed.Sealed2 -> 2 // assertFullyCovered(1, 1)
+        else -> throw NoWhenBranchMatchedException() // assertNotCovered()
+    } // assertFullyCovered()
+
+    private enum class Enum {
+        A, B
+    }
+
+    private fun whenEnum(p: Enum): Int = when (p) {  // assertFullyCovered(0, 2)
+        Enum.A -> 1 // assertFullyCovered()
+        Enum.B -> 2 // assertFullyCovered()
+    } // assertFullyCovered()
+
+    @Suppress("REDUNDANT_ELSE_IN_WHEN")
+    private fun whenEnumRedundantElse(p: Enum): Int = when (p) { // assertFullyCovered(1, 2)
+        Enum.A -> 1 // assertFullyCovered()
+        Enum.B -> 2 // assertFullyCovered()
+        else -> throw NoWhenBranchMatchedException() // assertNotCovered()
+    } // assertFullyCovered()
+
+    private fun whenString(p: String): Int = when (p) { // assertFullyCovered(0, 5)
+        "a" -> 1 // assertFullyCovered()
+        "b" -> 2 // assertFullyCovered()
+        "\u0000a" -> 3 // assertFullyCovered()
+        "\u0000b" -> 4 // assertFullyCovered()
+        else -> 5 // assertFullyCovered()
+    } // assertFullyCovered()
+
+    @JvmStatic
+    fun main(args: Array<String>) {
+        whenSealed(Sealed.Sealed1)
+        whenSealed(Sealed.Sealed2)
+
+        whenSealedRedundantElse(Sealed.Sealed1)
+        whenSealedRedundantElse(Sealed.Sealed2)
+
+        whenEnum(Enum.A)
+        whenEnum(Enum.B)
+
+        whenEnumRedundantElse(Enum.A)
+        whenEnumRedundantElse(Enum.B)
+
+        whenString("")
+        whenString("a")
+        whenString("b")
+        whenString("\u0000a")
+        whenString("\u0000b")
+    }
+
+}
diff --git a/org.jacoco.core.test.validation/.project b/org.jacoco.core.test.validation/.project
new file mode 100644
index 0000000..576c614
--- /dev/null
+++ b/org.jacoco.core.test.validation/.project
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.jacoco.core.test.validation</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+	<linkedResources>
+		<link>
+			<name>.settings</name>
+			<type>2</type>
+			<locationURI>PARENT-1-PROJECT_LOC/org.jacoco.core.test/.settings</locationURI>
+		</link>
+	</linkedResources>
+</projectDescription>
diff --git a/org.jacoco.core.test.validation/pom.xml b/org.jacoco.core.test.validation/pom.xml
new file mode 100644
index 0000000..7d9abf3
--- /dev/null
+++ b/org.jacoco.core.test.validation/pom.xml
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+   All rights reserved. This program and the accompanying materials
+   are made available under the terms of the Eclipse Public License v1.0
+   which accompanies this distribution, and is available at
+   http://www.eclipse.org/legal/epl-v10.html
+
+   Contributors:
+      Evgeny Mandrikov - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.jacoco</groupId>
+    <artifactId>org.jacoco.tests</artifactId>
+    <version>0.8.4</version>
+    <relativePath>../org.jacoco.tests</relativePath>
+  </parent>
+
+  <artifactId>org.jacoco.core.test.validation</artifactId>
+  <packaging>pom</packaging>
+
+  <name>JaCoCo :: Test :: Core :: Validation</name>
+
+  <modules>
+    <module>../org.jacoco.core.test.validation.java5</module>
+  </modules>
+
+  <properties>
+    <jacoco.skip>true</jacoco.skip>
+    <groovy.targetBytecode>${maven.compiler.target}</groovy.targetBytecode>
+  </properties>
+
+  <profiles>
+    <profile>
+      <id>java5-bytecode</id>
+      <activation>
+        <property>
+          <name>bytecode.version</name>
+          <value>5</value>
+        </property>
+      </activation>
+    </profile>
+
+    <profile>
+      <id>jdk5</id>
+      <activation>
+        <property>
+          <name>jdk.version</name>
+          <value>5</value>
+        </property>
+      </activation>
+    </profile>
+
+    <profile>
+      <id>java6-bytecode</id>
+      <activation>
+        <property>
+          <name>bytecode.version</name>
+          <value>6</value>
+        </property>
+      </activation>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>jdk6</id>
+      <activation>
+        <property>
+          <name>jdk.version</name>
+          <value>6</value>
+        </property>
+      </activation>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>java7-bytecode</id>
+      <activation>
+        <property>
+          <name>bytecode.version</name>
+          <value>7</value>
+        </property>
+      </activation>
+      <properties>
+        <groovy.targetBytecode>1.7</groovy.targetBytecode>
+      </properties>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+        <module>../org.jacoco.core.test.validation.java7</module>
+        <module>../org.jacoco.core.test.validation.groovy</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>jdk7</id>
+      <activation>
+        <property>
+          <name>jdk.version</name>
+          <value>7</value>
+        </property>
+      </activation>
+      <properties>
+        <groovy.targetBytecode>1.7</groovy.targetBytecode>
+      </properties>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+        <module>../org.jacoco.core.test.validation.java7</module>
+        <module>../org.jacoco.core.test.validation.groovy</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>java8-bytecode</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+        <property>
+          <name>bytecode.version</name>
+          <value>8</value>
+        </property>
+      </activation>
+      <properties>
+        <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
+        <groovy.targetBytecode>1.8</groovy.targetBytecode>
+      </properties>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+        <module>../org.jacoco.core.test.validation.java7</module>
+        <module>../org.jacoco.core.test.validation.java8</module>
+        <module>../org.jacoco.core.test.validation.groovy</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>java10-bytecode</id>
+      <activation>
+        <property>
+          <name>bytecode.version</name>
+          <value>10</value>
+        </property>
+      </activation>
+      <properties>
+        <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
+      </properties>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+        <module>../org.jacoco.core.test.validation.java7</module>
+        <module>../org.jacoco.core.test.validation.java8</module>
+        <module>../org.jacoco.core.test.validation.groovy</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>java11-bytecode</id>
+      <activation>
+        <property>
+          <name>bytecode.version</name>
+          <value>11</value>
+        </property>
+      </activation>
+      <properties>
+        <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
+      </properties>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+        <module>../org.jacoco.core.test.validation.java7</module>
+        <module>../org.jacoco.core.test.validation.java8</module>
+        <module>../org.jacoco.core.test.validation.groovy</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>java12-bytecode</id>
+      <activation>
+        <property>
+          <name>bytecode.version</name>
+          <value>12</value>
+        </property>
+      </activation>
+      <properties>
+        <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
+      </properties>
+      <modules>
+        <module>../org.jacoco.core.test.validation.kotlin</module>
+        <module>../org.jacoco.core.test.validation.java7</module>
+        <module>../org.jacoco.core.test.validation.java8</module>
+        <module>../org.jacoco.core.test.validation.groovy</module>
+      </modules>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/org.jacoco.core.test/pom.xml b/org.jacoco.core.test/pom.xml
index 4a6f5ad..843ebc8 100644
--- a/org.jacoco.core.test/pom.xml
+++ b/org.jacoco.core.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
@@ -33,111 +33,17 @@
       <artifactId>org.jacoco.core</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-analysis</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-util</artifactId>
+    </dependency>
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
   </dependencies>
 
-  <profiles>
-    <profile>
-      <id>java7-validation</id>
-      <activation>
-        <property>
-          <name>bytecode.version</name>
-          <value>1.7</value>
-        </property>
-      </activation>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>build-helper-maven-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>add-source</id>
-                <phase>generate-sources</phase>
-                <goals>
-                  <goal>add-source</goal>
-                </goals>
-                <configuration>
-                  <sources>
-                    <source>src-java7</source>
-                  </sources>
-                </configuration>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-    <profile>
-      <id>java8-validation</id>
-      <activation>
-        <property>
-          <name>bytecode.version</name>
-          <value>1.8</value>
-        </property>
-      </activation>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>build-helper-maven-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>add-source</id>
-                <phase>generate-sources</phase>
-                <goals>
-                  <goal>add-source</goal>
-                </goals>
-                <configuration>
-                  <sources>
-                    <source>src-java7</source>
-                    <source>src-java8</source>
-                  </sources>
-                </configuration>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-    <profile>
-      <id>java9-validation</id>
-      <activation>
-        <!-- for some reason activation should be presented here, even if already defined in parent -->
-        <property>
-          <name>bytecode.version</name>
-          <value>1.9</value>
-        </property>
-      </activation>
-      <properties>
-        <maven.compiler.target>1.9</maven.compiler.target>
-      </properties>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>build-helper-maven-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>add-source</id>
-                <phase>generate-sources</phase>
-                <goals>
-                  <goal>add-source</goal>
-                </goals>
-                <configuration>
-                  <sources>
-                    <source>src-java7</source>
-                    <source>src-java8</source>
-                  </sources>
-                </configuration>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
-
 </project>
diff --git a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/StringSwitchTest.java b/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/StringSwitchTest.java
deleted file mode 100644
index eefff0f..0000000
--- a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/StringSwitchTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.filter.targets.StringSwitch;
-import org.jacoco.core.test.validation.ValidationTestBase;
-import org.junit.Test;
-
-/**
- * Test of filtering of a bytecode that is generated for a String in switch
- * statement.
- */
-public class StringSwitchTest extends ValidationTestBase {
-
-	public StringSwitchTest() {
-		super("src-java7", StringSwitch.class);
-	}
-
-	/**
-	 * {@link StringSwitch#covered(String)}
-	 */
-	@Test
-	public void covered() {
-		if (isJDKCompiler) {
-			assertLine("covered.switch", ICounter.FULLY_COVERED, 0, 4);
-		} else {
-			assertLine("covered.switch", ICounter.PARTLY_COVERED, 2, 7);
-		}
-		assertLine("covered.case1", ICounter.FULLY_COVERED, 0, 0);
-		assertLine("covered.case2", ICounter.FULLY_COVERED, 0, 0);
-		assertLine("covered.case3", ICounter.FULLY_COVERED, 0, 0);
-		assertLine("covered.default", ICounter.FULLY_COVERED, 0, 0);
-	}
-
-	/**
-	 * {@link StringSwitch#notCovered(String)}
-	 */
-	@Test
-	public void notCovered() {
-		assertLine("notCovered", ICounter.NOT_COVERED, isJDKCompiler ? 4 : 9,
-				0);
-	}
-
-	/**
-	 * {@link StringSwitch#handwritten(String)}
-	 */
-	@Test
-	public void handwritten() {
-		assertLine("handwritten.firstSwitch", ICounter.FULLY_COVERED, 2, 1);
-		assertLine("handwritten.ignored", ICounter.FULLY_COVERED);
-		assertLine("handwritten.secondSwitch", ICounter.FULLY_COVERED, 3, 1);
-		assertLine("handwritten.case1", ICounter.FULLY_COVERED);
-		assertLine("handwritten.case2", ICounter.NOT_COVERED);
-	}
-
-}
diff --git a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/TryWithResourcesTest.java b/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/TryWithResourcesTest.java
deleted file mode 100644
index 3e4dbd8..0000000
--- a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/TryWithResourcesTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.filter.targets.TryWithResources;
-import org.jacoco.core.test.validation.ValidationTestBase;
-import org.junit.Test;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Test of filtering of a bytecode that is generated for a try-with-resources
- * statement.
- */
-public class TryWithResourcesTest extends ValidationTestBase {
-
-	public TryWithResourcesTest() {
-		super("src-java7", TryWithResources.class);
-	}
-
-	/**
-	 * {@link TryWithResources#test()}
-	 */
-	@Test
-	public void test() {
-		assertLine("test.before", ICounter.FULLY_COVERED);
-		// without filter next line covered partly:
-		assertLine("test.try", ICounter.FULLY_COVERED);
-		assertLine("test.open1", ICounter.FULLY_COVERED);
-		assertLine("test.open2", ICounter.FULLY_COVERED);
-		assertLine("test.open3", ICounter.FULLY_COVERED);
-		assertLine("test.body", ICounter.FULLY_COVERED);
-		// without filter next line has branches:
-		assertLine("test.close", ICounter.EMPTY);
-		assertLine("test.catch", ICounter.NOT_COVERED);
-		assertLine("test.finally", ICounter.FULLY_COVERED);
-	}
-
-	/**
-	 * {@link TryWithResources#test2()}
-	 */
-	@Test
-	public void test2() {
-		assertLine("test2.before", ICounter.FULLY_COVERED);
-		// without filter next line covered partly:
-		assertLine("test2.try", ICounter.FULLY_COVERED);
-		assertLine("test2.open1", ICounter.FULLY_COVERED);
-		assertLine("test2.open2", ICounter.FULLY_COVERED);
-		assertLine("test2.open3", ICounter.FULLY_COVERED);
-		assertLine("test2.body", ICounter.FULLY_COVERED);
-		// without filter next line has branches:
-		assertLine("test2.close", ICounter.EMPTY);
-		assertLine("test2.catch", ICounter.NOT_COVERED);
-		assertLine("test2.finally", ICounter.FULLY_COVERED);
-		assertLine("test2.after", ICounter.FULLY_COVERED);
-	}
-
-	/**
-	 * {@link TryWithResources#returnInBody()}
-	 */
-	@Test
-	public void returnInBody() {
-		// without filter next line covered partly:
-		assertLine("returnInBody.try", ICounter.FULLY_COVERED);
-		assertLine("returnInBody.open", ICounter.FULLY_COVERED);
-
-		// without filter next line has branches:
-		if (isJDKCompiler) {
-			// https://bugs.openjdk.java.net/browse/JDK-8134759
-			// javac 7 and 8 up to 8u92 are affected
-			final String jdkVersion = System.getProperty("java.version");
-			final Matcher m = Pattern.compile("1\\.8\\.0_(\\d++)(-ea)?")
-					.matcher(jdkVersion);
-			if (jdkVersion.startsWith("1.7.0_")
-					|| (m.matches() && Integer.parseInt(m.group(1)) < 92)) {
-				assertLine("returnInBody.close", ICounter.FULLY_COVERED, 0, 0);
-			} else {
-				assertLine("returnInBody.close", ICounter.EMPTY);
-			}
-		} else {
-			assertLine("returnInBody.close", ICounter.EMPTY);
-		}
-
-		assertLine("returnInBody.return", ICounter.FULLY_COVERED);
-	}
-
-	/**
-	 * {@link TryWithResources#nested()}
-	 */
-	@Test
-	public void nested() {
-		// without filter next line covered partly:
-		assertLine("nested.try1", ICounter.FULLY_COVERED);
-		assertLine("nested.open1", ICounter.FULLY_COVERED);
-		assertLine("nested.catch1", ICounter.NOT_COVERED);
-
-		// without filter next line covered partly:
-		assertLine("nested.try2", ICounter.FULLY_COVERED);
-		assertLine("nested.body", ICounter.FULLY_COVERED);
-		assertLine("nested.catch2", ICounter.NOT_COVERED);
-		assertLine("nested.finally2", ICounter.FULLY_COVERED);
-
-		// next lines not covered on exceptional path:
-		assertLine("nested.try3", ICounter.FULLY_COVERED, 0, 0);
-		assertLine("nested.open3", ICounter.FULLY_COVERED, 0, 0);
-		assertLine("nested.body3", ICounter.FULLY_COVERED, 0, 0);
-		assertLine("nested.catch3", ICounter.NOT_COVERED);
-		assertLine("nested.finally3", ICounter.FULLY_COVERED, 0, 0);
-
-		// without filter next lines have branches:
-		assertLine("nested.close3", ICounter.EMPTY);
-		assertLine("nested.close2", ICounter.EMPTY);
-		assertLine("nested.close1", ICounter.EMPTY);
-	}
-
-	/**
-	 * {@link TryWithResources#returnInCatch()}
-	 */
-	@Test
-	public void returnInCatch() {
-		// without filter next line covered partly:
-		assertLine("returnInCatch.try1", ICounter.FULLY_COVERED);
-		assertLine("returnInCatch.open", ICounter.FULLY_COVERED);
-		assertLine("returnInCatch.finally1", ICounter.PARTLY_COVERED, 1, 1);
-		// without filter next line has branches:
-		assertLine("returnInCatch.close", ICounter.EMPTY);
-
-		assertLine("returnInCatch.try2", ICounter.EMPTY);
-		assertLine("returnInCatch.finally2", ICounter.PARTLY_COVERED, 1, 1);
-	}
-
-	/*
-	 * Corner cases
-	 */
-
-	/**
-	 * {@link TryWithResources#handwritten()}
-	 */
-	@Test
-	public void handwritten() {
-		if (isJDKCompiler) {
-			assertLine("handwritten", /* partly when ECJ: */ICounter.EMPTY);
-		}
-	}
-
-	/**
-	 * {@link TryWithResources#empty()}
-	 */
-	@Test
-	public void empty() {
-		assertLine("empty.try", ICounter.FULLY_COVERED, 0, 0);
-		assertLine("empty.open", ICounter.FULLY_COVERED);
-		// empty when EJC:
-		if (isJDKCompiler) {
-			final String jdkVersion = System.getProperty("java.version");
-			if (jdkVersion.startsWith("9") || jdkVersion.startsWith("10")) {
-				assertLine("empty.close", ICounter.FULLY_COVERED, 0, 0);
-			} else {
-				// branches with javac 7 and 8
-				assertLine("empty.close", ICounter.PARTLY_COVERED);
-			}
-		}
-	}
-
-	/**
-	 * {@link TryWithResources#throwInBody()}
-	 */
-	@Test
-	public void throwInBody() {
-		// not filtered
-		assertLine("throwInBody.try", ICounter.NOT_COVERED);
-		assertLine("throwInBody.close", ICounter.NOT_COVERED);
-	}
-
-}
diff --git a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/targets/StringSwitch.java b/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/targets/StringSwitch.java
deleted file mode 100644
index c8b9a23..0000000
--- a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/targets/StringSwitch.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.nop;
-
-/**
- * This test target is a switch statement with a String.
- */
-public class StringSwitch {
-
-	private static void covered(Object s) {
-		switch (String.valueOf(s)) { // $line-covered.switch$
-		case "a":
-			nop("case a"); // $line-covered.case1$
-			break;
-		case "b":
-			nop("case b"); // $line-covered.case2$
-			break;
-		case "\0a":
-			nop("case \0a"); // $line-covered.case3$
-			break;
-		default:
-			nop("case default"); // $line-covered.default$
-			break;
-		}
-	}
-
-	private static void notCovered(Object s) {
-		switch (String.valueOf(s)) { // $line-notCovered$
-		case "a":
-			nop("case a");
-			break;
-		case "b":
-			nop("case b");
-			break;
-		case "\0a":
-			nop("case \0a");
-			break;
-		default:
-			nop("default");
-			break;
-		}
-	}
-
-	private static void handwritten(String s) {
-		int c = -1;
-		switch (s.hashCode()) { // $line-handwritten.firstSwitch$
-		case 97:
-			if ("a".equals(s)) { // $line-handwritten.ignored$
-				c = 0;
-			} else if ("\0a".equals(s)) {
-				c = 1;
-			}
-			break;
-		case 98:
-			if ("b".equals(s)) {
-				c = 2;
-			}
-			break;
-		}
-		switch (c) { // $line-handwritten.secondSwitch$
-		case 0:
-			nop("case a"); // $line-handwritten.case1$
-			break;
-		case 1:
-			nop("case \0a"); // $line-handwritten.case2$
-			break;
-		case 2:
-			nop("case b");
-			break;
-		default:
-			nop("default");
-			break;
-		}
-	}
-
-	public static void main(String[] args) {
-		covered("");
-		covered("a");
-		covered("b");
-		covered("\0a");
-
-		handwritten("a");
-	}
-
-}
diff --git a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/targets/TryWithResources.java b/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/targets/TryWithResources.java
deleted file mode 100644
index 3d3a30d..0000000
--- a/org.jacoco.core.test/src-java7/org/jacoco/core/test/filter/targets/TryWithResources.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.f;
-import static org.jacoco.core.test.validation.targets.Stubs.nop;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- * This test target is a try-with-resources statement.
- */
-public class TryWithResources {
-
-	private static class Resource implements Closeable {
-		@Override
-		public void close() {
-		}
-	}
-
-	/**
-	 * Closing performed using {@link org.objectweb.asm.Opcodes#INVOKEVIRTUAL}
-	 * or {@link org.objectweb.asm.Opcodes#INVOKEINTERFACE} depending on a class
-	 * of resource.
-	 */
-	private static Object test() throws Exception {
-		nop(); // $line-test.before$
-		try ( // $line-test.try$
-				Resource r1 = new Resource(); // $line-test.open1$
-				Closeable r2 = new Resource(); // $line-test.open2$
-				AutoCloseable r3 = new Resource() // $line-test.open3$
-		) {
-			return read(r1, r2, r3); // $line-test.body$
-		} // $line-test.close$
-		catch (Exception e) {
-			nop(); // $line-test.catch$
-			throw e;
-		} finally {
-			nop(); // $line-test.finally$
-		}
-	}
-
-	private static void test2() throws Exception {
-		nop(); // $line-test2.before$
-		try ( // $line-test2.try$
-				Resource r1 = new Resource(); // $line-test2.open1$
-				Closeable r2 = new Resource(); // $line-test2.open2$
-				AutoCloseable r3 = new Resource() // $line-test2.open3$
-		) {
-			read(r1, r2, r3); // $line-test2.body$
-		} // $line-test2.close$
-		catch (Exception e) {
-			nop(); // $line-test2.catch$
-		} finally {
-			nop(); // $line-test2.finally$
-		}
-		nop(); // $line-test2.after$
-	}
-
-	private static Object returnInBody() throws IOException {
-		try ( // $line-returnInBody.try$
-				Closeable r = new Resource() // $line-returnInBody.open$
-		) {
-			return read(r); // $line-returnInBody.return$
-		} // $line-returnInBody.close$
-	}
-
-	private static void nested() {
-		try ( // $line-nested.try1$
-				Resource r1 = new Resource() // $line-nested.open1$
-		) {
-
-			try ( // $line-nested.try2$
-					Resource r2 = new Resource() // $line-nested.open2$
-			) {
-				nop(r1.toString() + r2.toString()); // $line-nested.body$
-			} // $line-nested.close2$
-			catch (Exception e) {
-				nop(); // $line-nested.catch2$
-			} finally {
-				nop(); // $line-nested.finally2$
-			}
-
-		} // $line-nested.close1$
-		catch (Exception e) {
-			nop(); // $line-nested.catch1$
-		} finally {
-
-			try ( // $line-nested.try3$
-					Resource r2 = new Resource() // $line-nested.open3$
-			) {
-				nop(r2); // $line-nested.body3$
-			} // $line-nested.close3$
-			catch (Exception e) {
-				nop(); // $line-nested.catch3$
-			} finally {
-				nop(); // $line-nested.finally3$
-			}
-
-		}
-	}
-
-	/**
-	 * In this case bytecode will contain 3 copies of <code>finally</code>
-	 * block, each containing 2 branches, resulting in 6 branches in total. One
-	 * could think that this is artifact of try-with-resources, but the same
-	 * happens without it.
-	 */
-	private static Object returnInCatch() {
-		try ( // $line-returnInCatch.try1$
-				Resource r = new Resource() // $line-returnInCatch.open$
-		) {
-			read(r);
-		} // $line-returnInCatch.close$
-		catch (Exception e) {
-			return null;
-		} finally {
-			nop(!f()); // $line-returnInCatch.finally1$
-		}
-
-		try { // $line-returnInCatch.try2$
-			read(new Resource());
-		} catch (Exception e) {
-			return null;
-		} finally {
-			nop(!f()); // $line-returnInCatch.finally2$
-		}
-
-		return null;
-	}
-
-	private static Object read(Object r1, Object r2, Object r3) {
-		return r1.toString() + r2.toString() + r3.toString();
-	}
-
-	private static Object read(Object r1) {
-		return r1.toString();
-	}
-
-	public static void main(String[] args) throws Exception {
-		test();
-		test2();
-		returnInBody();
-		nested();
-
-		returnInCatch();
-
-		empty();
-		handwritten();
-	}
-
-	/*
-	 * Corner cases
-	 */
-
-	private static void empty() throws Exception {
-		try ( // $line-empty.try$
-				Closeable r = new Resource() // $line-empty.open$
-		) {
-		} // $line-empty.close$
-	}
-
-	private static void handwritten() throws IOException {
-		Closeable r = new Resource();
-		Throwable primaryExc = null;
-		try {
-			nop(r);
-		} catch (Throwable t) {
-			primaryExc = t;
-			throw t;
-		} finally {
-			if (r != null) { // $line-handwritten$
-				if (primaryExc != null) {
-					try {
-						r.close();
-					} catch (Throwable suppressedExc) {
-						primaryExc.addSuppressed(suppressedExc);
-					}
-				} else {
-					r.close();
-				}
-			}
-		}
-	}
-
-	private static void throwInBody() throws IOException {
-		try ( // $line-throwInBody.try$
-				Closeable r = new Resource()) {
-			nop(r);
-			throw new RuntimeException();
-		} // $line-throwInBody.close$
-	}
-
-}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/BadCycleInterfaceTest.java b/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/BadCycleInterfaceTest.java
deleted file mode 100644
index ae38ce5..0000000
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/BadCycleInterfaceTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.BadCycleInterface;
-import org.junit.Test;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Test of "bad cycles" with interfaces.
- */
-public class BadCycleInterfaceTest extends ValidationTestBase {
-
-	public BadCycleInterfaceTest() throws Exception {
-		super("src-java8", BadCycleInterface.class);
-	}
-
-	@Test
-	public void test() throws Exception {
-		final Matcher m = Pattern.compile("1\\.8\\.0_(\\d++)(-ea)?")
-				.matcher(System.getProperty("java.version"));
-		if (m.matches() && Integer.parseInt(m.group(1)) < 152) {
-			// Incorrect interpetation of JVMS 5.5 in JDK 8 causes a default
-			// method to be called before the static initializer of an interface
-			// (see JDK-8098557 and JDK-8164302):
-			assertLine("baseclinit", ICounter.FULLY_COVERED);
-			assertLine("childdefault", ICounter.FULLY_COVERED);
-
-			assertLogEvents("baseclinit", "childdefaultmethod", "childclinit",
-					"childstaticmethod");
-		} else {
-			// This shouldn't happen with JDK 9 (see also JDK-8043275)
-			// and starting with JDK 8u152 (see JDK-8167607):
-			assertLine("baseclinit", ICounter.EMPTY);
-			assertLine("childdefault", ICounter.NOT_COVERED);
-			assertLogEvents("childclinit", "childstaticmethod");
-		}
-		assertLine("childclinit", ICounter.FULLY_COVERED);
-		assertLine("childstatic", ICounter.FULLY_COVERED);
-	}
-
-}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/InterfaceDefaultMethodsTest.java b/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/InterfaceDefaultMethodsTest.java
deleted file mode 100644
index 5699851..0000000
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/InterfaceDefaultMethodsTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.InterfaceDefaultMethodsTarget;
-import org.junit.Test;
-
-/**
- * Tests of static initializer and default methods in interfaces.
- */
-public class InterfaceDefaultMethodsTest extends ValidationTestBase {
-
-	public InterfaceDefaultMethodsTest() {
-		super("src-java8", InterfaceDefaultMethodsTarget.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-		assertLine("clinit", ICounter.FULLY_COVERED);
-		assertLine("m1", ICounter.FULLY_COVERED);
-		assertLine("m2", ICounter.NOT_COVERED);
-	}
-
-}
diff --git a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/LambdaExpressionsTest.java b/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/LambdaExpressionsTest.java
deleted file mode 100644
index 2e8da87..0000000
--- a/org.jacoco.core.test/src-java8/org/jacoco/core/test/validation/LambdaExpressionsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.LambdaExpressionsTarget;
-import org.junit.Test;
-
-/**
- * Tests for different lambda expressions.
- */
-public class LambdaExpressionsTest extends ValidationTestBase {
-
-	public LambdaExpressionsTest() {
-		super("src-java8", LambdaExpressionsTarget.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		// Coverage of lambda bodies
-		assertLine("executedlambdabody", ICounter.FULLY_COVERED);
-		assertLine("notexecutedlambdabody", ICounter.NOT_COVERED);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/JaCoCoTest.java b/org.jacoco.core.test/src/org/jacoco/core/JaCoCoTest.java
index 759fab6..bb37e06 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/JaCoCoTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/JaCoCoTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java
index 9d3ce06..1e95a5d 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/AnalyzerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
  *******************************************************************************/
 package org.jacoco.core.analysis;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
@@ -42,6 +43,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
 
 /**
  * Unit tests for {@link Analyzer}.
@@ -74,6 +77,54 @@
 	}
 
 	@Test
+	public void should_ignore_module_info() throws Exception {
+		final ClassWriter cw = new ClassWriter(0);
+		cw.visit(Opcodes.V9, Opcodes.ACC_MODULE, "module-info", null, null,
+				null);
+		cw.visitModule("module", 0, null).visitEnd();
+		cw.visitEnd();
+		final byte[] bytes = cw.toByteArray();
+
+		analyzer.analyzeClass(bytes, "");
+
+		assertTrue(classes.isEmpty());
+	}
+
+	@Test
+	public void should_ignore_synthetic_classes() throws Exception {
+		final ClassWriter cw = new ClassWriter(0);
+		cw.visit(Opcodes.V1_5, Opcodes.ACC_SYNTHETIC, "Foo", null,
+				"java/lang/Object", null);
+		cw.visitEnd();
+		final byte[] bytes = cw.toByteArray();
+
+		analyzer.analyzeClass(bytes, "");
+
+		assertTrue(classes.isEmpty());
+	}
+
+	@Test
+	public void should_not_modify_class_bytes_to_support_next_version()
+			throws Exception {
+		final byte[] originalBytes = createClass(Opcodes.V12 + 1);
+		final byte[] bytes = new byte[originalBytes.length];
+		System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length);
+		final long expectedClassId = CRC64.classId(bytes);
+
+		analyzer.analyzeClass(bytes, "");
+
+		assertArrayEquals(originalBytes, bytes);
+		assertEquals(expectedClassId, classes.get("Foo").getId());
+	}
+
+	private static byte[] createClass(final int version) {
+		final ClassWriter cw = new ClassWriter(0);
+		cw.visit(version, 0, "Foo", null, "java/lang/Object", null);
+		cw.visitEnd();
+		return cw.toByteArray();
+	}
+
+	@Test
 	public void testAnalyzeClassFromStream() throws IOException {
 		analyzer.analyzeClass(TargetLoader.getClassData(AnalyzerTest.class),
 				"Test");
@@ -91,7 +142,6 @@
 
 	@Test
 	public void testAnalyzeClassIdMatch() throws IOException {
-		// class IDs are always calculated after downgrade of the version
 		final byte[] bytes = TargetLoader
 				.getClassDataAsBytes(AnalyzerTest.class);
 		executionData.get(Long.valueOf(CRC64.classId(bytes)),
diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/CounterComparatorTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/CounterComparatorTest.java
index a81ca24..0523abe 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/analysis/CounterComparatorTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/CounterComparatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java
index a4a3895..f29bb74 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,7 +13,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 
 import java.util.Arrays;
 import java.util.Collection;
@@ -106,13 +105,10 @@
 	}
 
 	@Test
-	public void testIgnoreClassesWithoutCode() {
-		final MethodCoverageImpl method = new MethodCoverageImpl("doit", "()V",
-				null);
-		addClass(123L, false, "Sample", null, method);
+	public void should_not_ignore_empty_classes() {
+		addClass(123L, false, "Empty", null);
 
-		final Collection<IClassCoverage> classes = coverageBuilder.getClasses();
-		assertTrue(classes.isEmpty());
+		assertEquals(1, coverageBuilder.getClasses().size());
 	}
 
 	@Test(expected = IllegalStateException.class)
diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageNodeImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageNodeImplTest.java
index 0ccab81..be1afdf 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageNodeImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageNodeImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/analysis/NodeComparatorTest.java b/org.jacoco.core.test/src/org/jacoco/core/analysis/NodeComparatorTest.java
index ec4928a..97c8b2f 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/analysis/NodeComparatorTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/analysis/NodeComparatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataReaderWriterTest.java b/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataReaderWriterTest.java
index a170022..f337994 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataReaderWriterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataReaderWriterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataStoreTest.java b/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataStoreTest.java
index c0fc7f8..a54544d 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataStoreTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataStoreTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataTest.java b/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataTest.java
index 89ed7b4..12773df 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/data/ExecutionDataTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/data/IncompatibleExecDataVersionExceptionTest.java b/org.jacoco.core.test/src/org/jacoco/core/data/IncompatibleExecDataVersionExceptionTest.java
index dbbe657..d4179e0 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/data/IncompatibleExecDataVersionExceptionTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/data/IncompatibleExecDataVersionExceptionTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoStoreTest.java b/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoStoreTest.java
index 3427da4..508d4d9 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoStoreTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoStoreTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoTest.java b/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoTest.java
index 48c37cd..568c4fa 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/data/SessionInfoTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java
new file mode 100644
index 0000000..9a9bd55
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.instr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.F_NEW;
+import static org.objectweb.asm.Opcodes.IFEQ;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.POP;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Opcodes.V10;
+import static org.objectweb.asm.Opcodes.V11;
+import static org.objectweb.asm.Opcodes.V12;
+import static org.objectweb.asm.Opcodes.V1_1;
+import static org.objectweb.asm.Opcodes.V1_2;
+import static org.objectweb.asm.Opcodes.V1_3;
+import static org.objectweb.asm.Opcodes.V1_4;
+import static org.objectweb.asm.Opcodes.V1_5;
+import static org.objectweb.asm.Opcodes.V1_6;
+import static org.objectweb.asm.Opcodes.V1_7;
+import static org.objectweb.asm.Opcodes.V1_8;
+import static org.objectweb.asm.Opcodes.V9;
+
+import java.io.IOException;
+
+import org.jacoco.core.internal.instr.CondyProbeArrayStrategy;
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.SystemPropertiesRuntime;
+import org.junit.Test;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * Test class inserted stackmap frames for different class file versions.
+ */
+public class ClassFileVersionsTest {
+
+	@Test
+	public void test_1_1() throws IOException {
+		testVersion(V1_1, false);
+	}
+
+	@Test
+	public void test_1_2() throws IOException {
+		testVersion(V1_2, false);
+	}
+
+	@Test
+	public void test_1_3() throws IOException {
+		testVersion(V1_3, false);
+	}
+
+	@Test
+	public void test_1_4() throws IOException {
+		testVersion(V1_4, false);
+	}
+
+	@Test
+	public void test_1_5() throws IOException {
+		testVersion(V1_5, false);
+	}
+
+	@Test
+	public void test_1_6() throws IOException {
+		testVersion(V1_6, true);
+	}
+
+	@Test
+	public void test_1_7() throws IOException {
+		testVersion(V1_7, true);
+	}
+
+	@Test
+	public void test_1_8() throws IOException {
+		testVersion(V1_8, true);
+	}
+
+	@Test
+	public void test_9() throws IOException {
+		testVersion(V9, true);
+	}
+
+	@Test
+	public void test_10() throws IOException {
+		testVersion(V10, true);
+	}
+
+	@Test
+	public void test_11() throws IOException {
+		testVersion(V11, true);
+	}
+
+	@Test
+	public void test_12() throws IOException {
+		testVersion(V12, true);
+	}
+
+	@Test
+	public void test_13() throws IOException {
+		testVersion(V12 + 1, true);
+	}
+
+	private void testVersion(int version, boolean frames) throws IOException {
+		final byte[] original = createClass(version, frames);
+
+		IRuntime runtime = new SystemPropertiesRuntime();
+		Instrumenter instrumenter = new Instrumenter(runtime);
+		byte[] instrumented = instrumenter.instrument(original, "TestTarget");
+
+		assertFrames(instrumented, frames);
+	}
+
+	private void assertFrames(byte[] source, final boolean expected) {
+		InstrSupport.classReaderFor(source)
+				.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION) {
+
+					@Override
+					public MethodVisitor visitMethod(int access, String name,
+							final String desc, String signature,
+							String[] exceptions) {
+						return new MethodVisitor(InstrSupport.ASM_API_VERSION) {
+							boolean frames = false;
+
+							@Override
+							public void visitFrame(int type, int nLocal,
+									Object[] local, int nStack,
+									Object[] stack) {
+								frames = true;
+							}
+
+							@Override
+							public void visitEnd() {
+								if (CondyProbeArrayStrategy.B_DESC
+										.equals(desc)) {
+									assertFalse(
+											"CondyProbeArrayStrategy does not need frames",
+											frames);
+								} else {
+									assertEquals(Boolean.valueOf(expected),
+											Boolean.valueOf(frames));
+								}
+							}
+						};
+					}
+				}, 0);
+	}
+
+	/**
+	 * Creates a class that requires a frame before the return statement. Also
+	 * for this class instrumentation should insert another frame.
+	 * 
+	 * <code><pre>
+	 * public class Sample {
+	 *   public Sample(boolean b){
+	 *     if(b){
+	 *       toString();
+	 *     }
+	 *     return;
+	 *   }
+	 * }
+	 * </pre></code>
+	 */
+	private byte[] createClass(int version, boolean frames) {
+
+		ClassWriter cw = new ClassWriter(0);
+		MethodVisitor mv;
+
+		cw.visit(version, ACC_PUBLIC + ACC_SUPER, "org/jacoco/test/Sample",
+				null, "java/lang/Object", null);
+
+		mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Z)V", null, null);
+		mv.visitCode();
+		mv.visitVarInsn(ALOAD, 0);
+		mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V",
+				false);
+		mv.visitVarInsn(ILOAD, 1);
+		Label l1 = new Label();
+		mv.visitJumpInsn(IFEQ, l1);
+		mv.visitVarInsn(ALOAD, 0);
+		mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString",
+				"()Ljava/lang/String;", false);
+		mv.visitInsn(POP);
+		mv.visitLabel(l1);
+		if (frames) {
+			mv.visitFrame(F_NEW, 2,
+					new Object[] { "org/jacoco/test/Sample", Opcodes.INTEGER },
+					0, new Object[] {});
+		}
+		mv.visitInsn(RETURN);
+		mv.visitMaxs(1, 2);
+		mv.visitEnd();
+
+		cw.visitEnd();
+
+		return cw.toByteArray();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java
index 9596047..d5104bc 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/instr/InstrumenterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
  *******************************************************************************/
 package org.jacoco.core.instr;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
@@ -34,12 +35,15 @@
 import java.util.zip.ZipOutputStream;
 
 import org.jacoco.core.analysis.AnalyzerTest;
-import org.jacoco.core.runtime.RuntimeData;
-import org.jacoco.core.runtime.SystemPropertiesRuntime;
+import org.jacoco.core.internal.data.CRC64;
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
 import org.jacoco.core.test.TargetLoader;
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
 
 /**
  * Unit tests for {@link Instrumenter}.
@@ -66,20 +70,50 @@
 
 	}
 
-	private SystemPropertiesRuntime runtime;
+	private static final class AccessorGenerator
+			implements IExecutionDataAccessorGenerator {
 
+		long classId;
+
+		public int generateDataAccessor(final long classId,
+				final String classname, final int probeCount,
+				final MethodVisitor mv) {
+			this.classId = classId;
+			InstrSupport.push(mv, probeCount);
+			mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BOOLEAN);
+			return 1;
+		}
+
+	}
+
+	private AccessorGenerator accessorGenerator;
 	private Instrumenter instrumenter;
 
 	@Before
 	public void setup() throws Exception {
-		runtime = new SystemPropertiesRuntime();
-		instrumenter = new Instrumenter(runtime);
-		runtime.startup(new RuntimeData());
+		accessorGenerator = new AccessorGenerator();
+		instrumenter = new Instrumenter(accessorGenerator);
 	}
 
-	@After
-	public void teardown() {
-		runtime.shutdown();
+	@Test
+	public void should_not_modify_class_bytes_to_support_next_version()
+			throws Exception {
+		final byte[] originalBytes = createClass(Opcodes.V12 + 1);
+		final byte[] bytes = new byte[originalBytes.length];
+		System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length);
+		final long expectedClassId = CRC64.classId(bytes);
+
+		instrumenter.instrument(bytes, "");
+
+		assertArrayEquals(originalBytes, bytes);
+		assertEquals(expectedClassId, accessorGenerator.classId);
+	}
+
+	private static byte[] createClass(final int version) {
+		final ClassWriter cw = new ClassWriter(0);
+		cw.visit(version, 0, "Foo", null, "java/lang/Object", null);
+		cw.visitEnd();
+		return cw.toByteArray();
 	}
 
 	@Test
diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/MethodRecorder.java b/org.jacoco.core.test/src/org/jacoco/core/instr/MethodRecorder.java
index 8dc22db..49a88be 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/instr/MethodRecorder.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/instr/MethodRecorder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ResizeInstructionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/ResizeInstructionsTest.java
similarity index 85%
rename from org.jacoco.core.test/src/org/jacoco/core/test/validation/ResizeInstructionsTest.java
rename to org.jacoco.core.test/src/org/jacoco/core/instr/ResizeInstructionsTest.java
index 9ba6f61..1a8137c 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ResizeInstructionsTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/instr/ResizeInstructionsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,13 +9,12 @@
  *    Evgeny Mandrikov - initial API and implementation
  *
  *******************************************************************************/
-package org.jacoco.core.test.validation;
+package org.jacoco.core.instr;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
-import org.jacoco.core.instr.Instrumenter;
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.jacoco.core.runtime.IRuntime;
 import org.jacoco.core.runtime.RuntimeData;
@@ -33,14 +32,17 @@
 
 public class ResizeInstructionsTest {
 
-	private final IRuntime runtime = new SystemPropertiesRuntime();
-	private final Instrumenter instrumenter = new Instrumenter(runtime);
+	private IRuntime runtime;
+	private Instrumenter instrumenter;
 
-	private boolean computedCommonSuperClass = false;
+	private boolean computedCommonSuperClass;
 
 	@Before
 	public void setup() throws Exception {
+		runtime = new SystemPropertiesRuntime();
+		instrumenter = new Instrumenter(runtime);
 		runtime.startup(new RuntimeData());
+		computedCommonSuperClass = false;
 	}
 
 	@After
@@ -57,11 +59,10 @@
 	 */
 	@Test
 	public void should_not_loose_InnerClasses_attribute() throws Exception {
-		// FIXME fails without COMPUTE_FRAMES because of
-		// https://gitlab.ow2.org/asm/asm/issues/317800
-		final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
-		final ClassReader cr = new ClassReader(
-				TargetLoader.getClassDataAsBytes(Inner.class));
+		byte[] source = TargetLoader.getClassDataAsBytes(Inner.class);
+
+		final ClassReader cr = InstrSupport.classReaderFor(source);
+		final ClassWriter cw = new ClassWriter(0);
 		cr.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION, cw) {
 			@Override
 			public void visitEnd() {
@@ -75,7 +76,9 @@
 				super.visitEnd();
 			}
 		}, 0);
-		final byte[] bytes = instrumenter.instrument(cw.toByteArray(), "");
+		source = cw.toByteArray();
+
+		final byte[] bytes = instrumenter.instrument(source, "");
 
 		final TargetLoader targetLoader = new TargetLoader();
 		final Class<?> outer = targetLoader.add(ResizeInstructionsTest.class,
@@ -149,7 +152,7 @@
 
 	/**
 	 * Adds code that triggers usage of
-	 * {@link org.objectweb.asm.MethodWriter#INSERTED_FRAMES} during
+	 * {@link org.objectweb.asm.MethodWriter#COMPUTE_INSERTED_FRAMES} during
 	 * instrumentation.
 	 */
 	private static void addCauseOfResizeInstructions(final MethodVisitor mv) {
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java
index a61d699..a631b52 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/ContentTypeDetectorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -115,6 +115,57 @@
 	}
 
 	@Test
+	public void should_detect_java_10() throws IOException {
+		initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x36);
+		assertEquals(ContentTypeDetector.CLASSFILE, detector.getType());
+		assertContent();
+	}
+
+	@Test
+	public void should_detect_java_11() throws IOException {
+		initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x37);
+		assertEquals(ContentTypeDetector.CLASSFILE, detector.getType());
+		assertContent();
+	}
+
+	@Test
+	public void should_detect_java_11_with_preview_features()
+			throws IOException {
+		initData(0xCA, 0xFE, 0xBA, 0xBE, 0xFF, 0xFF, 0x00, 0x37);
+		assertEquals(ContentTypeDetector.CLASSFILE, detector.getType());
+		assertContent();
+	}
+
+	@Test
+	public void should_detect_java_12() throws IOException {
+		initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x38);
+		assertEquals(ContentTypeDetector.CLASSFILE, detector.getType());
+		assertContent();
+	}
+
+	@Test
+	public void should_detect_java_12_with_preview_features()
+			throws IOException {
+		initData(0xCA, 0xFE, 0xBA, 0xBE, 0xFF, 0xFF, 0x00, 0x38);
+		assertEquals(ContentTypeDetector.CLASSFILE, detector.getType());
+		assertContent();
+	}
+
+	@Test
+	public void should_detect_java_13() throws IOException {
+		initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x39);
+		assertEquals(ContentTypeDetector.CLASSFILE, detector.getType());
+		assertContent();
+	}
+
+	@Test
+	public void should_detect_java_13_with_preview_features() throws IOException {
+		initData(0xCA, 0xFE, 0xBA, 0xBE, 0xFF, 0xFF, 0x00, 0x39);
+		assertEquals(ContentTypeDetector.CLASSFILE, detector.getType());
+		assertContent();
+	}
+
+	@Test
 	public void testMachObjectFile() throws IOException {
 		initData(0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x02);
 		assertEquals(ContentTypeDetector.UNKNOWN, detector.getType());
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/Pack200StreamsTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/Pack200StreamsTest.java
index f242c2f..ce5676c 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/Pack200StreamsTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/Pack200StreamsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/BundleCoverageImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/BundleCoverageImplTest.java
index 82ad63f..71d8e15 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/BundleCoverageImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/BundleCoverageImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java
index ec65035..372c602 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java
index b219a87..7a53abf 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -93,7 +93,7 @@
 		assertEquals(CounterImpl.COUNTER_0_0, node.getInstructionCounter());
 		assertEquals(CounterImpl.COUNTER_0_0, node.getBranchCounter());
 		assertEquals(CounterImpl.COUNTER_0_0, node.getMethodCounter());
-		assertEquals(CounterImpl.COUNTER_1_0, node.getClassCounter());
+		assertEquals(CounterImpl.COUNTER_0_0, node.getClassCounter());
 	}
 
 	@Test
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java
index 8e8f769..9e55820 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/CounterImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java
new file mode 100644
index 0000000..e7e167e
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link Instruction}.
+ */
+public class InstructionTest {
+
+	private Instruction instruction;
+
+	@Before
+	public void setup() {
+		instruction = new Instruction(123);
+	}
+
+	@Test
+	public void getLine_should_return_line_number() {
+		assertEquals(123, instruction.getLine());
+	}
+
+	@Test
+	public void new_instance_should_have_no_coverage_and_no_branches() {
+		assertEquals(CounterImpl.COUNTER_1_0,
+				instruction.getInstructionCounter());
+		assertEquals(CounterImpl.COUNTER_0_0, instruction.getBranchCounter());
+	}
+
+	@Test
+	public void addBranchWithInstruction_should_not_increment_branches_when_only_one_branch_is_added() {
+		instruction.addBranch(new Instruction(122), 0);
+
+		assertEquals(CounterImpl.COUNTER_0_0, instruction.getBranchCounter());
+	}
+
+	@Test
+	public void addBranchWithInstruction_should_increment_branches_when_two_branches_are_added() {
+		instruction.addBranch(new Instruction(122), 0);
+		instruction.addBranch(new Instruction(123), 1);
+
+		assertEquals(CounterImpl.getInstance(2, 0),
+				instruction.getBranchCounter());
+	}
+
+	@Test
+	public void addBranchWithInstruction_should_propagate_existing_coverage_status() {
+		final Instruction target = new Instruction(122);
+		target.addBranch(true, 0);
+
+		instruction.addBranch(target, 0);
+
+		assertEquals(CounterImpl.COUNTER_0_1,
+				instruction.getInstructionCounter());
+	}
+
+	@Test
+	public void addBranchWithProbe_should_increment_branches_when_covered() {
+		instruction.addBranch(true, 0);
+		instruction.addBranch(true, 1);
+
+		assertEquals(CounterImpl.getInstance(0, 1),
+				instruction.getInstructionCounter());
+		assertEquals(CounterImpl.getInstance(0, 2),
+				instruction.getBranchCounter());
+	}
+
+	@Test
+	public void addBranchWithProbe_should_increment_branches_when_not_covered() {
+		instruction.addBranch(false, 0);
+		instruction.addBranch(false, 1);
+
+		assertEquals(CounterImpl.getInstance(1, 0),
+				instruction.getInstructionCounter());
+		assertEquals(CounterImpl.getInstance(2, 0),
+				instruction.getBranchCounter());
+	}
+
+	@Test
+	public void addBranchWithProbe_should_increment_branches_when_partly_covered() {
+		instruction.addBranch(false, 0);
+		instruction.addBranch(true, 1);
+
+		assertEquals(CounterImpl.getInstance(0, 1),
+				instruction.getInstructionCounter());
+		assertEquals(CounterImpl.getInstance(1, 1),
+				instruction.getBranchCounter());
+	}
+
+	@Test
+	public void addBranchWithProbe_should_propagate_coverage_status_to_existing_predecessors() {
+		final Instruction i1 = new Instruction(124);
+		final Instruction i2 = new Instruction(125);
+		instruction.addBranch(i1, 3);
+		i1.addBranch(i2, 5);
+
+		i2.addBranch(true, 8);
+
+		assertEquals(CounterImpl.COUNTER_0_1,
+				instruction.getInstructionCounter());
+	}
+
+	@Test
+	public void addBranch_should_count_large_number_of_branches() {
+		for (int branch = 0; branch < 0x1000; branch++) {
+			instruction.addBranch(true, branch);
+		}
+
+		assertEquals(CounterImpl.getInstance(0, 0x1000),
+				instruction.getBranchCounter());
+	}
+
+	@Test
+	public void addBranch_should_propagate_coverage_status_over_very_long_sequence() {
+		Instruction next = instruction;
+		for (int i = 0; i < 0x10000; i++) {
+			final Instruction insn = new Instruction(i);
+			next.addBranch(insn, 0);
+			next = insn;
+		}
+		next.addBranch(true, 0);
+
+		assertEquals(CounterImpl.COUNTER_0_1,
+				instruction.getInstructionCounter());
+	}
+
+	@Test
+	public void merge_should_calculate_superset_of_covered_branches() {
+		final Instruction i1 = new Instruction(124);
+		i1.addBranch(false, 1);
+		i1.addBranch(false, 2);
+		i1.addBranch(true, 3);
+		i1.addBranch(true, 4);
+		final Instruction i2 = new Instruction(124);
+		i2.addBranch(false, 1);
+		i2.addBranch(true, 2);
+		i2.addBranch(false, 3);
+		i2.addBranch(true, 4);
+
+		instruction = i1.merge(i2);
+
+		assertEquals(CounterImpl.getInstance(1, 3),
+				instruction.getBranchCounter());
+	}
+
+	@Test
+	public void replaceBranches_should_calculate_coverage_on_new_branches() {
+		Instruction i1 = new Instruction(1);
+		Instruction i2 = new Instruction(2);
+		Instruction i3 = new Instruction(3);
+		i3.addBranch(true, 0);
+
+		instruction = instruction.replaceBranches(Arrays.asList(i1, i2, i3));
+
+		assertEquals(CounterImpl.getInstance(2, 1),
+				instruction.getBranchCounter());
+	}
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionsBuilderTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionsBuilderTest.java
new file mode 100644
index 0000000..b938caa
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionsBuilderTest.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.jacoco.core.analysis.ISourceFileCoverage;
+import org.jacoco.core.internal.flow.LabelInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnNode;
+
+/**
+ * Unit tests for {@link InstructionsBuilder}.
+ */
+public class InstructionsBuilderTest {
+
+	private InstructionsBuilder builder;
+
+	@Before
+	public void setup() {
+		builder = new InstructionsBuilder(new boolean[] { false, true });
+	}
+
+	@Test
+	public void current_line_number_should_be_applied_to_instructions() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+
+		builder.setCurrentLine(10);
+		InsnNode i2 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i2);
+		InsnNode i3 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i3);
+
+		builder.setCurrentLine(20);
+		InsnNode i4 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i4);
+
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(ISourceFileCoverage.UNKNOWN_LINE, map.get(i1).getLine());
+		assertEquals(10, map.get(i2).getLine());
+		assertEquals(10, map.get(i3).getLine());
+		assertEquals(20, map.get(i4).getLine());
+	}
+
+	@Test
+	public void null_probearray_should_not_mark_instruction_as_covered() {
+		builder = new InstructionsBuilder(null);
+
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+		builder.addProbe(5, 0);
+
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_1_0,
+				map.get(i1).getInstructionCounter());
+	}
+
+	@Test
+	public void unexecuted_probe_should_not_mark_instruction_as_covered() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+		builder.addProbe(0, 0);
+
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_1_0,
+				map.get(i1).getInstructionCounter());
+	}
+
+	@Test
+	public void executed_probe_should_mark_instruction_as_covered() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+		builder.addProbe(1, 0);
+
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_0_1,
+				map.get(i1).getInstructionCounter());
+	}
+
+	@Test
+	public void subsequent_instructions_should_be_linked_by_default() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+
+		InsnNode i2 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i2);
+
+		// mark i2 as covered
+		builder.addProbe(1, 0);
+
+		// coverage should be propagated to i1
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_0_1,
+				map.get(i1).getInstructionCounter());
+	}
+
+	@Test
+	public void subsequent_instructions_should_not_be_linked_when_noSuccessor_was_called() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+		builder.noSuccessor();
+
+		InsnNode i2 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i2);
+
+		// mark i2 as covered
+		builder.addProbe(1, 0);
+
+		// coverage should not be propagated to i1
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_1_0,
+				map.get(i1).getInstructionCounter());
+	}
+
+	@Test
+	public void subsequent_instructions_should_be_linked_after_label_marked_as_successor() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+
+		Label l = new Label();
+		LabelInfo.setSuccessor(l);
+		builder.addLabel(l);
+		InsnNode i2 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i2);
+
+		// mark i2 as covered
+		builder.addProbe(1, 0);
+
+		// coverage should be propagated to i1
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_0_1,
+				map.get(i1).getInstructionCounter());
+	}
+
+	@Test
+	public void subsequent_instructions_should_not_be_linked_after_label_not_marked_as_successor() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+
+		builder.addLabel(new Label());
+		InsnNode i2 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i2);
+
+		// mark i2 as covered
+		builder.addProbe(1, 0);
+
+		// coverage should not be propagated to i1
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_1_0,
+				map.get(i1).getInstructionCounter());
+	}
+
+	@Test
+	public void jumps_should_propagate_coverage_status() {
+		InsnNode i1 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i1);
+		Label l2 = new Label();
+		builder.addJump(l2, 0);
+
+		builder.addLabel(l2);
+		InsnNode i2 = new InsnNode(Opcodes.NOP);
+		builder.addInstruction(i2);
+
+		// mark i2 as covered
+		builder.addProbe(1, 0);
+
+		// coverage should be propagated to i1
+		Map<AbstractInsnNode, Instruction> map = builder.getInstructions();
+		assertEquals(CounterImpl.COUNTER_0_1,
+				map.get(i1).getInstructionCounter());
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java
index ffc3bfc..115c72e 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/LineImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java
index c312e60..01b29db 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,11 +14,15 @@
 import static org.junit.Assert.assertEquals;
 
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.jacoco.core.analysis.ILine;
 import org.jacoco.core.analysis.IMethodCoverage;
+import org.jacoco.core.internal.analysis.filter.FilterContextMock;
 import org.jacoco.core.internal.analysis.filter.Filters;
 import org.jacoco.core.internal.analysis.filter.IFilter;
+import org.jacoco.core.internal.analysis.filter.IFilterContext;
 import org.jacoco.core.internal.analysis.filter.IFilterOutput;
 import org.jacoco.core.internal.flow.IProbeIdGenerator;
 import org.jacoco.core.internal.flow.LabelFlowAnalyzer;
@@ -109,8 +113,8 @@
 
 	/** Filters the NOP instructions as ignored */
 	private static final IFilter NOP_FILTER = new IFilter() {
-		public void filter(final String className, final String superClassName,
-				final MethodNode methodNode, final IFilterOutput output) {
+		public void filter(final MethodNode methodNode,
+				final IFilterContext context, final IFilterOutput output) {
 			final AbstractInsnNode i1 = methodNode.instructions.get(2);
 			final AbstractInsnNode i2 = methodNode.instructions.get(3);
 			assertEquals(Opcodes.NOP, i1.getOpcode());
@@ -125,6 +129,9 @@
 		probes[0] = true;
 		runMethodAnalzer(NOP_FILTER);
 
+		assertEquals(1002, result.getFirstLine());
+		assertEquals(1002, result.getLastLine());
+
 		assertLine(1001, 0, 0, 0, 0);
 		assertLine(1002, 0, 1, 0, 0);
 	}
@@ -318,22 +325,24 @@
 	public void if_branch_merge_should_show_partial_branch_coverage_when_probe_for_first_branch_is_executed() {
 		createIfBranchMerge();
 		probes[0] = true;
+		probes[2] = true;
 		runMethodAnalzer();
 
 		assertLine(1001, 0, 2, 1, 1);
 		assertLine(1002, 1, 0, 0, 0);
-		assertLine(1003, 1, 0, 0, 0);
+		assertLine(1003, 0, 1, 0, 0);
 	}
 
 	@Test
 	public void if_branch_merge_should_show_partial_branch_coverage_when_probe_for_second_branch_is_executed() {
 		createIfBranchMerge();
 		probes[1] = true;
+		probes[2] = true;
 		runMethodAnalzer();
 
 		assertLine(1001, 0, 2, 1, 1);
 		assertLine(1002, 0, 1, 0, 0);
-		assertLine(1003, 1, 0, 0, 0);
+		assertLine(1003, 0, 1, 0, 0);
 	}
 
 	@Test
@@ -447,7 +456,7 @@
 		assertLine(1002, 0, 1, 0, 0);
 	}
 
-	// === Scenario: table switch ===
+	// === Scenario: table switch with and without replace filtering ===
 
 	private void createTableSwitch() {
 		final Label l0 = new Label();
@@ -492,6 +501,41 @@
 		assertEquals(4, nextProbeId);
 	}
 
+	private static final IFilter SWITCH_FILTER = new IFilter() {
+		public void filter(final MethodNode methodNode,
+				final IFilterContext context, final IFilterOutput output) {
+			final AbstractInsnNode i = methodNode.instructions.get(3);
+			assertEquals(Opcodes.TABLESWITCH, i.getOpcode());
+			final AbstractInsnNode t1 = methodNode.instructions.get(6);
+			assertEquals(Opcodes.BIPUSH, t1.getOpcode());
+			final AbstractInsnNode t2 = methodNode.instructions.get(13);
+			assertEquals(Opcodes.BIPUSH, t2.getOpcode());
+
+			final Set<AbstractInsnNode> newTargets = new HashSet<AbstractInsnNode>();
+			newTargets.add(t1);
+			newTargets.add(t2);
+			output.replaceBranches(i, newTargets);
+		}
+	};
+
+	@Test
+	public void table_switch_with_filter_should_show_2_branches_when_original_replaced() {
+		createTableSwitch();
+		runMethodAnalzer(SWITCH_FILTER);
+
+		assertLine(1001, 2, 0, 2, 0);
+	}
+
+	@Test
+	public void table_switch_with_filter_should_show_full_branch_coverage_when_new_targets_covered() {
+		createTableSwitch();
+		probes[0] = true;
+		probes[1] = true;
+		runMethodAnalzer(SWITCH_FILTER);
+
+		assertLine(1001, 0, 2, 0, 2);
+	}
+
 	@Test
 	public void table_switch_should_show_missed_when_no_probes_are_executed() {
 		createTableSwitch();
@@ -708,13 +752,12 @@
 	public void try_catch_should_show_exception_handler_missed_when_probe_is_not_executed() {
 		createTryCatchBlock();
 		probes[0] = true;
-		probes[1] = true;
-		probes[0] = true;
+		probes[2] = true;
 		runMethodAnalzer();
 
 		assertLine(1001, 0, 3, 0, 0);
-		assertLine(1002, 0, 1, 0, 0);
-		assertLine(1003, 1, 0, 0, 0);
+		assertLine(1002, 1, 0, 0, 0);
+		assertLine(1003, 0, 1, 0, 0);
 	}
 
 	@Test
@@ -777,8 +820,8 @@
 	}
 
 	private static final IFilter TRY_FINALLY_FILTER = new IFilter() {
-		public void filter(final String className, final String superClassName,
-				final MethodNode methodNode, final IFilterOutput output) {
+		public void filter(final MethodNode methodNode,
+				final IFilterContext context, final IFilterOutput output) {
 			final AbstractInsnNode i1 = methodNode.instructions.get(2);
 			final AbstractInsnNode i2 = methodNode.instructions.get(7);
 			assertEquals(Opcodes.IFEQ, i1.getOpcode());
@@ -845,14 +888,21 @@
 
 	private void runMethodAnalzer(IFilter filter) {
 		LabelFlowAnalyzer.markLabels(method);
-		final MethodAnalyzer analyzer = new MethodAnalyzer("Foo",
-				"java/lang/Object", "doit", "()V", null, probes, filter);
+		InstructionsBuilder builder = new InstructionsBuilder(probes);
+		final MethodAnalyzer analyzer = new MethodAnalyzer(builder);
+
 		final MethodProbesAdapter probesAdapter = new MethodProbesAdapter(
 				analyzer, this);
 		// note that CheckMethodAdapter verifies that this test does not violate
 		// contracts of ASM API
 		analyzer.accept(method, new CheckMethodAdapter(probesAdapter));
-		result = analyzer.getCoverage();
+
+		MethodCoverageImpl mc = new MethodCoverageImpl("doit", "V()", null);
+		MethodCoverageCalculator mcc = new MethodCoverageCalculator(
+				builder.getInstructions());
+		filter.filter(method, new FilterContextMock(), mcc);
+		mcc.calculate(mc);
+		result = mc;
 	}
 
 	private void assertLine(int nr, int insnMissed, int insnCovered,
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java
new file mode 100644
index 0000000..306bc79
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.jacoco.core.analysis.ISourceFileCoverage;
+import org.junit.Before;
+import org.junit.Test;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.InsnNode;
+
+/**
+ * Unit tests for {@link MethodCoverageCalculator}.
+ */
+public class MethodCoverageCalculatorTest {
+
+	private Map<AbstractInsnNode, Instruction> instructions;
+
+	// The purpose of this list is to link instruction nodes
+	private InsnList list;
+
+	private MethodCoverageImpl coverage;
+
+	@Before
+	public void setup() {
+		instructions = new HashMap<AbstractInsnNode, Instruction>();
+		coverage = new MethodCoverageImpl("run", "()V", null);
+		list = new InsnList();
+	}
+
+	@Test
+	public void should_report_instructions() {
+		addInsn(1, true);
+		addInsn(2, true);
+		addInsn(2, false);
+		addInsn(3, false);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 0, 0);
+		assertLine(2, 1, 1, 0, 0);
+		assertLine(3, 1, 0, 0, 0);
+	}
+
+	@Test
+	public void should_report_instructions_with_branches() {
+		addInsn(1, false, false);
+		addInsn(2, false, false, true);
+		addInsn(3, false, true, true);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.calculate(coverage);
+
+		assertLine(1, 1, 0, 2, 0);
+		assertLine(2, 0, 1, 2, 1);
+		assertLine(3, 0, 1, 1, 2);
+	}
+
+	@Test
+	public void should_ignore_single_instruction() {
+		addInsn(1, true);
+		InsnNode i1 = addInsn(1, false);
+		addInsn(2, true);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.ignore(i1, i1);
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 0, 0); // only one instruction not filtered
+		assertLine(2, 0, 1, 0, 0);
+	}
+
+	@Test
+	public void should_ignore_instruction_range() {
+		addInsn(1, true);
+		InsnNode i1 = addInsn(2, false);
+		addInsn(2, false);
+		addInsn(2, false);
+		addInsn(2, false);
+		InsnNode i2 = addInsn(2, false);
+		addInsn(3, true);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.ignore(i1, i2);
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 0, 0);
+		assertLine(2, 0, 0, 0, 0); // all instructions filtered in line 2
+		assertLine(3, 0, 1, 0, 0);
+	}
+
+	@Test
+	public void should_exclude_ignored_instructions_from_computation_of_first_and_last_lines() {
+		InsnNode i1 = addInsn(1, false);
+		addInsn(2, false);
+		InsnNode i3 = addInsn(3, false);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.ignore(i1, i1);
+		c.ignore(i3, i3);
+		c.calculate(coverage);
+
+		assertEquals(2, coverage.getFirstLine());
+		assertEquals(2, coverage.getLastLine());
+	}
+
+	@Test
+	public void should_merge_instructions() {
+		addInsn(1, true);
+		InsnNode i1 = addInsn(2, false, true);
+		InsnNode i2 = addInsn(2, true, false);
+		addInsn(3, true);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.merge(i1, i2);
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 0, 0);
+		assertLine(2, 0, 1, 0, 2); // one fully covered instruction left
+		assertLine(3, 0, 1, 0, 0);
+	}
+
+	@Test
+	public void should_merge_multiple_instructions() {
+		InsnNode i1 = addInsn(1, true, false, false);
+		InsnNode i2 = addInsn(1, false, true, false);
+		InsnNode i3 = addInsn(1, false, false, true);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.merge(i1, i2);
+		c.merge(i2, i3);
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 0, 3); // one fully covered instruction left
+	}
+
+	@Test
+	public void should_merge_instructions_redundant() {
+		addInsn(1, true);
+		InsnNode i1 = addInsn(2, false, true);
+		InsnNode i2 = addInsn(2, true, false);
+		addInsn(3, true);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.merge(i1, i2);
+		c.merge(i2, i1);
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 0, 0);
+		assertLine(2, 0, 1, 0, 2); // one fully covered instruction left
+		assertLine(3, 0, 1, 0, 0);
+	}
+
+	@Test
+	public void should_replace_branches() {
+		InsnNode i1 = addInsn(1);
+		InsnNode i2 = addInsn(2, true);
+		InsnNode i3 = addInsn(2, true);
+		InsnNode i4 = addInsn(2, false);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.replaceBranches(i1,
+				new HashSet<AbstractInsnNode>(Arrays.asList(i2, i3, i4)));
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 1, 2); // branches coverage status replaced
+		assertLine(2, 1, 2, 0, 0); // still in place
+	}
+
+	@Test
+	public void should_replace_branches_with_merged_instructions() {
+		InsnNode i1 = addInsn(1, false, false, false);
+		InsnNode i2 = addInsn(2, true);
+		InsnNode i3 = addInsn(2, false);
+		InsnNode i4 = addInsn(2, false);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.merge(i4, i3);
+		c.merge(i3, i2);
+		c.replaceBranches(i1,
+				new HashSet<AbstractInsnNode>(Arrays.asList(i2, i3, i4)));
+		c.calculate(coverage);
+
+		assertLine(1, 0, 1, 0, 3);
+	}
+
+	@Test
+	public void should_work_without_lines() {
+		addInsn(ISourceFileCoverage.UNKNOWN_LINE, false);
+		addInsn(ISourceFileCoverage.UNKNOWN_LINE, false);
+		addInsn(ISourceFileCoverage.UNKNOWN_LINE, true);
+
+		MethodCoverageCalculator c = new MethodCoverageCalculator(instructions);
+		c.calculate(coverage);
+
+		assertEquals(ISourceFileCoverage.UNKNOWN_LINE, coverage.getFirstLine());
+		assertEquals(ISourceFileCoverage.UNKNOWN_LINE, coverage.getLastLine());
+		assertEquals(CounterImpl.getInstance(2, 1),
+				coverage.getInstructionCounter());
+	}
+
+	private void assertLine(int idx, int mi, int ci, int mb, int cb) {
+		assertEquals("instructions", CounterImpl.getInstance(mi, ci),
+				coverage.getLine(idx).getInstructionCounter());
+		assertEquals("branches", CounterImpl.getInstance(mb, cb),
+				coverage.getLine(idx).getBranchCounter());
+	}
+
+	private InsnNode addInsn(int line, boolean... branches) {
+		Instruction i = new Instruction(line);
+		int idx = 0;
+		for (boolean covered : branches) {
+			i.addBranch(covered, idx++);
+		}
+		InsnNode node = new InsnNode(Opcodes.NOP);
+		list.add(node);
+		instructions.put(node, i);
+		return node;
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java
index fd04f44..5a100b0 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/PackageCoverageTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/PackageCoverageTest.java
index 76cf684..1d81a02 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/PackageCoverageTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/PackageCoverageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceFileCoverageImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceFileCoverageImplTest.java
index 69183e8..ed83eba 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceFileCoverageImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceFileCoverageImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java
index 7e9a423..2501042 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/SourceNodeImplTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/StringPoolTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/StringPoolTest.java
index 18ca05d..eca2460 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/StringPoolTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/StringPoolTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AbstractMatcherTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AbstractMatcherTest.java
new file mode 100644
index 0000000..f659632
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AbstractMatcherTest.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.VarInsnNode;
+
+/**
+ * Unit tests for {@link AbstractMatcher}.
+ */
+public class AbstractMatcherTest {
+
+	private final AbstractMatcher matcher = new AbstractMatcher() {
+	};
+
+	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+			"method_name", "()V", null, null);
+
+	@Test
+	public void skipNonOpcodes() {
+		m.visitFrame(Opcodes.F_FULL, 0, null, 0, null);
+		final Label label = new Label();
+		m.visitLabel(label);
+		m.visitLineNumber(42, label);
+		m.visitInsn(Opcodes.NOP);
+
+		// should skip all non opcodes
+		matcher.cursor = m.instructions.getFirst();
+		matcher.skipNonOpcodes();
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should not change cursor when it points on instruction with opcode
+		matcher.skipNonOpcodes();
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should not do anything when cursor is null
+		matcher.cursor = null;
+		matcher.skipNonOpcodes();
+	}
+
+	@Test
+	public void nextIs() {
+		m.visitInsn(Opcodes.NOP);
+		m.visitInsn(Opcodes.NOP);
+
+		// should set cursor to null when opcode mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIs(Opcodes.ATHROW);
+		assertNull(matcher.cursor);
+
+		// should set cursor to next instruction when match
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIs(Opcodes.NOP);
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should not do anything when cursor is null
+		matcher.cursor = null;
+		matcher.nextIs(Opcodes.NOP);
+	}
+
+	@Test
+	public void nextIsSwitch() {
+		// should set cursor to null when opcode mismatch
+		m.visitInsn(Opcodes.NOP);
+		m.visitInsn(Opcodes.NOP);
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsSwitch();
+		assertNull(matcher.cursor);
+
+		// should set cursor to next instruction when match
+		m.instructions.clear();
+		m.visitInsn(Opcodes.NOP);
+		m.visitTableSwitchInsn(0, 0, new Label());
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsSwitch();
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should set cursor to next instruction when match
+		m.instructions.clear();
+		m.visitInsn(Opcodes.NOP);
+		m.visitLookupSwitchInsn(new Label(), null, new Label[0]);
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsSwitch();
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should not do anything when cursor is null
+		matcher.cursor = null;
+		matcher.nextIsSwitch();
+	}
+
+	@Test
+	public void nextIsVar() {
+		m.visitInsn(Opcodes.NOP);
+		m.visitVarInsn(Opcodes.ILOAD, 42);
+
+		// should set cursor to null when opcode mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsVar(Opcodes.ALOAD, "name");
+		assertNull(matcher.cursor);
+
+		// should set cursor to next instruction when match
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsVar(Opcodes.ILOAD, "name");
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should set cursor to null when var mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.vars.put("name", new VarInsnNode(Opcodes.ILOAD, 13));
+		matcher.nextIsVar(Opcodes.ILOAD, "name");
+		assertNull(matcher.cursor);
+
+		// should set cursor to next instruction when match
+		matcher.cursor = m.instructions.getFirst();
+		matcher.vars.put("name", new VarInsnNode(Opcodes.ILOAD, 42));
+		matcher.nextIsVar(Opcodes.ILOAD, "name");
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should not do anything when cursor is null
+		matcher.cursor = null;
+		matcher.nextIsVar(Opcodes.ILOAD, "name");
+	}
+
+	@Test
+	public void nextIsInvoke() {
+		m.visitInsn(Opcodes.NOP);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "owner", "name", "()V", false);
+
+		// should set cursor to null when opcode mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsInvoke(Opcodes.INVOKESTATIC, "owner", "name", "()V");
+		assertNull(matcher.cursor);
+
+		// should set cursor to null when owner mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsInvoke(Opcodes.INVOKEVIRTUAL, "another_owner", "name",
+				"()V");
+		assertNull(matcher.cursor);
+
+		// should set cursor to null when name mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsInvoke(Opcodes.INVOKEVIRTUAL, "owner", "another_name",
+				"()V");
+		assertNull(matcher.cursor);
+
+		// should set cursor to null when descriptor mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsInvoke(Opcodes.INVOKEVIRTUAL, "owner", "name",
+				"(Lanother_descriptor;)V");
+		assertNull(matcher.cursor);
+
+		// should set cursor to next instruction when match
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsInvoke(Opcodes.INVOKEVIRTUAL, "owner", "name", "()V");
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should not do anything when cursor is null
+		matcher.cursor = null;
+		matcher.nextIsInvoke(Opcodes.INVOKEVIRTUAL, "owner", "name", "()V");
+	}
+
+	@Test
+	public void nextIsType() {
+		m.visitInsn(Opcodes.NOP);
+		m.visitTypeInsn(Opcodes.NEW, "descriptor");
+
+		// should set cursor to null when opcode mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsType(Opcodes.CHECKCAST, "descriptor");
+		assertNull(matcher.cursor);
+
+		// should set cursor to null when descriptor mismatch
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsType(Opcodes.NEW, "another_descriptor");
+		assertNull(matcher.cursor);
+
+		// should set cursor to next instruction when match
+		matcher.cursor = m.instructions.getFirst();
+		matcher.nextIsType(Opcodes.NEW, "descriptor");
+		assertSame(m.instructions.getLast(), matcher.cursor);
+
+		// should not do anything when cursor is null
+		matcher.cursor = null;
+		matcher.nextIsType(Opcodes.NEW, "descriptor");
+	}
+
+	@Test
+	public void firstIsALoad0() {
+		// should set cursor to null when opcode mismatch
+		m.visitInsn(Opcodes.NOP);
+		matcher.firstIsALoad0(m);
+		assertNull(matcher.cursor);
+
+		// should set cursor to null when var mismatch
+		m.instructions.clear();
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		matcher.firstIsALoad0(m);
+		assertNull(matcher.cursor);
+
+		// should set cursor to first instruction when match
+		m.instructions.clear();
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		matcher.firstIsALoad0(m);
+		assertSame(m.instructions.getLast(), matcher.cursor);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilterTest.java
new file mode 100644
index 0000000..b8a0331
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilterTest.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link AnnotationGeneratedFilter}.
+ */
+public class AnnotationGeneratedFilterTest extends FilterTestBase {
+
+	private final IFilter filter = new AnnotationGeneratedFilter();
+
+	@Test
+	public void should_filter_methods_annotated_with_runtime_visible_org_groovy_transform_Generated() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitAnnotation("Lgroovy/transform/Generated;", true);
+
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+
+		filter.filter(m, context, output);
+
+		assertMethodIgnored(m);
+	}
+
+	@Test
+	public void should_filter_methods_annotated_with_runtime_invisible_lombok_Generated() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitAnnotation("Llombok/Generated;", false);
+
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+
+		filter.filter(m, context, output);
+
+		assertMethodIgnored(m);
+	}
+
+	@Test
+	public void should_filter_classes_annotated_with_runtime_visible_org_immutables_value_Generated() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+
+		context.classAnnotations.add("Lorg/immutables/value/Generated;");
+
+		filter.filter(m, context, output);
+
+		assertMethodIgnored(m);
+	}
+
+	@Test
+	public void should_filter_classes_annotated_with_runtime_visible_org_apache_avro_specific_AvroGenerated() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"readExternal", "()V", null, null);
+
+		m.visitInsn(Opcodes.NOP);
+
+		context.classAnnotations
+				.add("Lorg/apache/avro/specific/AvroGenerated;");
+
+		filter.filter(m, context, output);
+
+		assertMethodIgnored(m);
+	}
+
+	@Test
+	public void should_filter_when_annotation_is_inner() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+
+		context.classAnnotations.add("Lorg/example/Class$Generated;");
+
+		filter.filter(m, context, output);
+
+		assertMethodIgnored(m);
+	}
+
+	@Test
+	public void should_not_filter_when_no_annotations() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void should_not_filter_when_other_annotations() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitAnnotation("LOtherAnnotation;", true);
+
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+
+		context.classAnnotations.add("LOtherAnnotation;");
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilterTest.java
new file mode 100644
index 0000000..32bc9df
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilterTest.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link EnumEmptyConstructorFilter}.
+ */
+public class EnumEmptyConstructorFilterTest extends FilterTestBase {
+
+	private final EnumEmptyConstructorFilter filter = new EnumEmptyConstructorFilter();
+
+	@Test
+	public void should_filter() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_PRIVATE, "<init>", "(Ljava/lang/String;I)V", null,
+				null);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitVarInsn(Opcodes.ILOAD, 2);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Enum", "<init>",
+				"(Ljava/lang/String;I)V", false);
+		m.visitInsn(Opcodes.RETURN);
+		context.superClassName = "java/lang/Enum";
+
+		filter.filter(m, context, output);
+
+		assertIgnored(new Range(m.instructions.getFirst(), m.instructions.getLast()));
+	}
+
+	/**
+	 * <code><pre>
+	 * enum E {
+	 *   ;
+	 *   private E() {
+	 *     ...
+	 *   }
+	 * }
+	 * </pre></code>
+	 */
+	@Test
+	public void should_not_filter_non_empty_constructor() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_PRIVATE, "<init>", "(Ljava/lang/String;I)V", null,
+				null);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitVarInsn(Opcodes.ILOAD, 2);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Enum", "<init>",
+				"(Ljava/lang/String;I)V", false);
+		m.visitInsn(Opcodes.NOP);
+		m.visitInsn(Opcodes.RETURN);
+		context.superClassName = "java/lang/Enum";
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	/**
+	 * <code><pre>
+	 * enum E {
+	 *   ;
+	 *   private E(long p) {
+	 *   }
+	 * }
+	 * </pre></code>
+	 */
+	@Test
+	public void should_not_filter_constructor_with_additional_parameters() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_PRIVATE, "<init>", "(Ljava/lang/String;IJ)V", null,
+				null);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitVarInsn(Opcodes.ILOAD, 2);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Enum", "<init>",
+				"(Ljava/lang/String;I)V", false);
+		m.visitInsn(Opcodes.RETURN);
+		context.superClassName = "java/lang/Enum";
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	/**
+	 * <code><pre>
+	 * enum E {
+	 *   ;
+	 *   private void method(String p1, int p2) {
+	 *   }
+	 * }
+	 * </pre></code>
+	 */
+	@Test
+	public void should_not_filter_non_constructor() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_PRIVATE, "method", "(Ljava/lang/String;I)V", null,
+				null);
+		m.visitInsn(Opcodes.NOP);
+		context.superClassName = "java/lang/Enum";
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void should_not_filter_non_Enum() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_PRIVATE, "<init>", "(Ljava/lang/String;I)V", null,
+				null);
+		m.visitInsn(Opcodes.NOP);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java
index 9d7fb2c..23f69f4 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/EnumFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,33 +11,28 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Test;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
-public class EnumFilterTest implements IFilterOutput {
+/**
+ * Unit tests for {@link EnumFilter}.
+ */
+public class EnumFilterTest extends FilterTestBase {
 
 	private final EnumFilter filter = new EnumFilter();
 
-	private AbstractInsnNode fromInclusive;
-	private AbstractInsnNode toInclusive;
-
 	@Test
 	public void testValues() {
 		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
 				"values", "()[LFoo;", null, null);
 		m.visitInsn(Opcodes.NOP);
+		context.superClassName = "java/lang/Enum";
 
-		filter.filter("Foo", "java/lang/Enum", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(m.instructions.getFirst(), fromInclusive);
-		assertEquals(m.instructions.getLast(), toInclusive);
+		assertMethodIgnored(m);
 	}
 
 	@Test
@@ -46,10 +41,9 @@
 				"values", "()V", null, null);
 		m.visitInsn(Opcodes.NOP);
 
-		filter.filter("Foo", "java/lang/Enum", m, this);
+		filter.filter(m, context, output);
 
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
+		assertIgnored();
 	}
 
 	@Test
@@ -57,11 +51,11 @@
 		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
 				"valueOf", "(Ljava/lang/String;)LFoo;", null, null);
 		m.visitInsn(Opcodes.NOP);
+		context.superClassName = "java/lang/Enum";
 
-		filter.filter("Foo", "java/lang/Enum", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(m.instructions.getFirst(), fromInclusive);
-		assertEquals(m.instructions.getLast(), toInclusive);
+		assertMethodIgnored(m);
 	}
 
 	@Test
@@ -69,11 +63,11 @@
 		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
 				"valueOf", "()V", null, null);
 		m.visitInsn(Opcodes.NOP);
+		context.superClassName = "java/lang/Enum";
 
-		filter.filter("Foo", "java/lang/Enum", m, this);
+		filter.filter(m, context, output);
 
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
+		assertIgnored();
 	}
 
 	@Test
@@ -82,21 +76,9 @@
 				"values", "()[LFoo;", null, null);
 		m.visitInsn(Opcodes.NOP);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
-	}
-
-	public void ignore(final AbstractInsnNode fromInclusive,
-			final AbstractInsnNode toInclusive) {
-		assertNull(this.fromInclusive);
-		this.fromInclusive = fromInclusive;
-		this.toInclusive = toInclusive;
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
+		assertIgnored();
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterContextMock.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterContextMock.java
new file mode 100644
index 0000000..a6c881d
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterContextMock.java
@@ -0,0 +1,48 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ *******************************************************************************/

+package org.jacoco.core.internal.analysis.filter;

+

+import java.util.HashSet;

+import java.util.Set;

+

+/**

+ * {@link IFilterContext} mock for unit tests.

+ */

+public class FilterContextMock implements IFilterContext {

+

+	public String className = "Foo";

+	public String superClassName = "java/lang/Object";

+	public Set<String> classAnnotations = new HashSet<String>();

+	public String sourceFileName = "Foo.java";

+	public String sourceDebugExtension;

+

+	public String getClassName() {

+		return className;

+	}

+

+	public String getSuperClassName() {

+		return superClassName;

+	}

+

+	public Set<String> getClassAnnotations() {

+		return classAnnotations;

+	}

+

+	public String getSourceFileName() {

+		return sourceFileName;

+	}

+

+	public String getSourceDebugExtension() {

+		return sourceDebugExtension;

+	}

+

+}

diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java
new file mode 100644
index 0000000..2378bee
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Base class for tests of {@link IFilter} implementations.
+ */
+public abstract class FilterTestBase {
+
+	protected final FilterContextMock context = new FilterContextMock();
+
+	private final List<Range> ignoredRanges = new ArrayList<Range>();
+
+	private final Map<AbstractInsnNode, Set<AbstractInsnNode>> replacedBranches = new HashMap<AbstractInsnNode, Set<AbstractInsnNode>>();
+
+	protected final IFilterOutput output = new IFilterOutput() {
+		public void ignore(final AbstractInsnNode fromInclusive,
+				final AbstractInsnNode toInclusive) {
+			final Range range = new Range();
+			range.fromInclusive = fromInclusive;
+			range.toInclusive = toInclusive;
+			ignoredRanges.add(range);
+		}
+
+		public void merge(final AbstractInsnNode i1,
+				final AbstractInsnNode i2) {
+			fail();
+		}
+
+		public void replaceBranches(final AbstractInsnNode source,
+				final Set<AbstractInsnNode> newTargets) {
+			replacedBranches.put(source, newTargets);
+		}
+	};
+
+	final void assertIgnored(Range... ranges) {
+		assertArrayEquals(ranges, ignoredRanges.toArray(new Range[0]));
+	}
+
+	final void assertMethodIgnored(final MethodNode m) {
+		assertIgnored(
+				new Range(m.instructions.getFirst(), m.instructions.getLast()));
+	}
+
+	final void assertNoReplacedBranches() {
+		assertTrue(replacedBranches.isEmpty());
+	}
+
+	final void assertReplacedBranches(final AbstractInsnNode source,
+			final Set<AbstractInsnNode> newTargets) {
+		assertEquals(Collections.singletonMap(source, newTargets),
+				replacedBranches);
+	}
+
+	static class Range {
+		AbstractInsnNode fromInclusive;
+		AbstractInsnNode toInclusive;
+
+		Range() {
+		}
+
+		Range(AbstractInsnNode fromInclusive, AbstractInsnNode toInclusive) {
+			this.fromInclusive = fromInclusive;
+			this.toInclusive = toInclusive;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (obj.getClass() == Range.class) {
+				final Range other = (Range) obj;
+				return this.fromInclusive.equals(other.fromInclusive)
+						&& this.toInclusive.equals(other.toInclusive);
+			}
+			return false;
+		}
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java
index 5e0ed6c..6a9cf67 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,9 @@
 import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
+/**
+ * Unit tests for {@link FinallyFilter}.
+ */
 public class FinallyFilterTest implements IFilterOutput {
 
 	private final IFilter filter = new FinallyFilter();
@@ -383,7 +386,7 @@
 	}
 
 	private void execute() {
-		filter.filter("", "", m, this);
+		filter.filter(m, new FilterContextMock(), this);
 		assertEquals("ignored", toIndexes(expectedIgnored),
 				toIndexes(actualIgnored));
 		assertEquals("merged", toIndexes(expectedMerged),
@@ -418,4 +421,9 @@
 		}
 	}
 
+	public void replaceBranches(final AbstractInsnNode source,
+			final Set<AbstractInsnNode> newTargets) {
+		fail();
+	}
+
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilterTest.java
deleted file mode 100644
index 6cf0feb..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilterTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.internal.analysis.filter;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import org.jacoco.core.internal.instr.InstrSupport;
-import org.junit.Test;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
-import org.objectweb.asm.tree.MethodNode;
-
-public class GroovyGeneratedFilterTest implements IFilterOutput {
-
-	private final IFilter filter = new GroovyGeneratedFilter();
-
-	private AbstractInsnNode fromInclusive;
-	private AbstractInsnNode toInclusive;
-
-	@Test
-	public void testNoAnnotations() {
-		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
-				"hashCode", "()I", null, null);
-
-		m.visitInsn(Opcodes.ICONST_0);
-		m.visitInsn(Opcodes.IRETURN);
-
-		filter.filter("Foo", "java/lang/Object", m, this);
-
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
-	}
-
-	@Test
-	public void testOtherAnnotation() {
-		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
-				"hashCode", "()I", null, null);
-		m.visitAnnotation("Lother/Annotation;", true);
-
-		m.visitInsn(Opcodes.ICONST_0);
-		m.visitInsn(Opcodes.IRETURN);
-
-		filter.filter("Foo", "java/lang/Object", m, this);
-
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
-	}
-
-	@Test
-	public void testGroovyGeneratedAnnotation() {
-		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
-				"hashCode", "()I", null, null);
-		m.visitAnnotation("Lgroovy/transform/Generated;", true);
-
-		m.visitInsn(Opcodes.ICONST_0);
-		m.visitInsn(Opcodes.IRETURN);
-
-		filter.filter("Foo", "java/lang/Object", m, this);
-
-		assertEquals(m.instructions.getFirst(), fromInclusive);
-		assertEquals(m.instructions.getLast(), toInclusive);
-	}
-
-	public void ignore(final AbstractInsnNode fromInclusive,
-			final AbstractInsnNode toInclusive) {
-		assertNull(this.fromInclusive);
-		this.fromInclusive = fromInclusive;
-		this.toInclusive = toInclusive;
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java
new file mode 100644
index 0000000..127ae30
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java
@@ -0,0 +1,376 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit test for {@link KotlinCoroutineFilter}.
+ */
+public class KotlinCoroutineFilterTest extends FilterTestBase {
+
+	private final IFilter filter = new KotlinCoroutineFilter();
+
+	@Test
+	public void should_filter_suspending_lambdas_generated_by_Kotlin_1_3_30() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"invokeSuspend", "(Ljava/lang/Object;)Ljava/lang/Object;", null,
+				null);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		m.visitLabel(new Label());
+		final Range range1 = new Range();
+		range1.fromInclusive = m.instructions.getLast();
+		m.visitMethodInsn(Opcodes.INVOKESTATIC,
+				"kotlin/coroutines/intrinsics/IntrinsicsKt",
+				"getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);
+		m.visitVarInsn(Opcodes.ASTORE, 4);
+
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		// line of "runBlocking"
+		m.visitFieldInsn(Opcodes.GETFIELD, "Target", "label", "I");
+		final Label dflt = new Label();
+		final Label state0 = new Label();
+		final Label state1 = new Label();
+		m.visitTableSwitchInsn(0, 1, dflt, state0, state1);
+
+		m.visitLabel(state0);
+
+		{
+			m.visitVarInsn(Opcodes.ALOAD, 1);
+			m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt",
+					"throwOnFailure", "(Ljava/lang/Object;)V", false);
+			range1.toInclusive = m.instructions.getLast();
+		}
+
+		// line before "suspendingFunction"
+		m.visitInsn(Opcodes.NOP);
+
+		// line of "suspendingFunction"
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction",
+				"(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false);
+
+		m.visitInsn(Opcodes.DUP);
+		final Range range2 = new Range();
+		range2.fromInclusive = m.instructions.getLast();
+		m.visitVarInsn(Opcodes.ALOAD, 4);
+		final Label continuationLabelAfterLoadedResult = new Label();
+		m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationLabelAfterLoadedResult);
+		// line of "runBlocking"
+		m.visitVarInsn(Opcodes.ALOAD, 4);
+		m.visitInsn(Opcodes.ARETURN);
+
+		m.visitLabel(state1);
+
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitFieldInsn(Opcodes.GETFIELD, "Target", "I$0", "I");
+		m.visitVarInsn(Opcodes.ISTORE, 3);
+
+		{
+			m.visitVarInsn(Opcodes.ALOAD, 1);
+			m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt",
+					"throwOnFailure", "(Ljava/lang/Object;)V", false);
+		}
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		range2.toInclusive = m.instructions.getLast();
+		m.visitLabel(continuationLabelAfterLoadedResult);
+
+		// line after "suspendingFunction"
+		m.visitInsn(Opcodes.NOP);
+		m.visitInsn(Opcodes.ARETURN);
+
+		m.visitLabel(dflt);
+		final Range range0 = new Range();
+		range0.fromInclusive = m.instructions.getLast();
+		m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
+		m.visitInsn(Opcodes.DUP);
+		m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+				"java/lang/IllegalStateException", "<init>",
+				"(Ljava/lang/String;)V", false);
+		m.visitInsn(Opcodes.ATHROW);
+		range0.toInclusive = m.instructions.getLast();
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range0, range1, range2);
+	}
+
+	/**
+	 * <pre>
+	 *     runBlocking {
+	 *         val x = 42
+	 *         nop(x)
+	 *         suspendingFunction()
+	 *         nop(x)
+	 *     }
+	 * </pre>
+	 */
+	@Test
+	public void should_filter_suspending_lambdas() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"invokeSuspend", "(Ljava/lang/Object;)Ljava/lang/Object;", null,
+				null);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		m.visitLabel(new Label());
+		final Range range1 = new Range();
+		range1.fromInclusive = m.instructions.getLast();
+		m.visitMethodInsn(Opcodes.INVOKESTATIC,
+				"kotlin/coroutines/intrinsics/IntrinsicsKt",
+				"getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);
+		m.visitVarInsn(Opcodes.ASTORE, 4);
+
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		// line of "runBlocking"
+		m.visitFieldInsn(Opcodes.GETFIELD, "Target", "label", "I");
+		final Label dflt = new Label();
+		final Label state0 = new Label();
+		final Label state1 = new Label();
+		m.visitTableSwitchInsn(0, 1, dflt, state0, state1);
+
+		m.visitLabel(state0);
+
+		{
+			m.visitVarInsn(Opcodes.ALOAD, 1);
+			m.visitInsn(Opcodes.DUP);
+			m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
+			Label label = new Label();
+			m.visitJumpInsn(Opcodes.IFEQ, label);
+			m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
+			m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure",
+					"exception", "Ljava/lang/Throwable");
+			m.visitInsn(Opcodes.ATHROW);
+			m.visitInsn(Opcodes.POP);
+			range1.toInclusive = m.instructions.getLast();
+			m.visitLabel(label);
+		}
+
+		// line before "suspendingFunction"
+		m.visitInsn(Opcodes.NOP);
+
+		// line of "suspendingFunction"
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction",
+				"(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false);
+
+		m.visitInsn(Opcodes.DUP);
+		final Range range2 = new Range();
+		range2.fromInclusive = m.instructions.getLast();
+		m.visitVarInsn(Opcodes.ALOAD, 4);
+		final Label continuationLabelAfterLoadedResult = new Label();
+		m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationLabelAfterLoadedResult);
+		// line of "runBlocking"
+		m.visitVarInsn(Opcodes.ALOAD, 4);
+		m.visitInsn(Opcodes.ARETURN);
+
+		m.visitLabel(state1);
+
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitFieldInsn(Opcodes.GETFIELD, "Target", "I$0", "I");
+		m.visitVarInsn(Opcodes.ISTORE, 3);
+
+		{
+			m.visitVarInsn(Opcodes.ALOAD, 1);
+			m.visitInsn(Opcodes.DUP);
+			m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
+			final Label label = new Label();
+			m.visitJumpInsn(Opcodes.IFEQ, label);
+			m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
+			m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure",
+					"exception", "Ljava/lang/Throwable");
+			m.visitInsn(Opcodes.ATHROW);
+			m.visitInsn(Opcodes.POP);
+			m.visitLabel(label);
+		}
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		range2.toInclusive = m.instructions.getLast();
+		m.visitLabel(continuationLabelAfterLoadedResult);
+
+		// line after "suspendingFunction"
+		m.visitInsn(Opcodes.NOP);
+		m.visitInsn(Opcodes.ARETURN);
+
+		m.visitLabel(dflt);
+		final Range range0 = new Range();
+		range0.fromInclusive = m.instructions.getLast();
+		m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
+		m.visitInsn(Opcodes.DUP);
+		m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+				"java/lang/IllegalStateException", "<init>",
+				"(Ljava/lang/String;)V", false);
+		m.visitInsn(Opcodes.ATHROW);
+		range0.toInclusive = m.instructions.getLast();
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range0, range1, range2);
+	}
+
+	/**
+	 * <pre>
+	 *     suspend fun example() {
+	 *         suspendingFunction()
+	 *         nop()
+	 *     }
+	 * </pre>
+	 */
+	@Test
+	public void should_filter_suspending_functions() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_STATIC, "example",
+				"(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null,
+				null);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		final int continuationArgumentIndex = 0;
+		final int continuationIndex = 2;
+
+		m.visitVarInsn(Opcodes.ALOAD, continuationArgumentIndex);
+		final Range range1 = new Range();
+		range1.fromInclusive = m.instructions.getLast();
+		m.visitTypeInsn(Opcodes.INSTANCEOF, "ExampleKt$example$1");
+		final Label createStateInstance = new Label();
+		m.visitJumpInsn(Opcodes.IFEQ, createStateInstance);
+
+		m.visitVarInsn(Opcodes.ALOAD, continuationArgumentIndex);
+		m.visitTypeInsn(Opcodes.CHECKCAST, "ExampleKt$example$1");
+		m.visitVarInsn(Opcodes.ASTORE, continuationIndex);
+
+		m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
+		m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I");
+
+		m.visitLdcInsn(Integer.valueOf(Integer.MIN_VALUE));
+		m.visitInsn(Opcodes.IAND);
+		m.visitJumpInsn(Opcodes.IFEQ, createStateInstance);
+
+		m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
+		m.visitInsn(Opcodes.DUP);
+		m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I");
+
+		m.visitLdcInsn(Integer.valueOf(Integer.MIN_VALUE));
+		m.visitInsn(Opcodes.ISUB);
+		m.visitFieldInsn(Opcodes.PUTFIELD, "ExampleKt$example$1", "label", "I");
+
+		final Label afterCoroutineStateCreated = new Label();
+		m.visitJumpInsn(Opcodes.GOTO, afterCoroutineStateCreated);
+
+		m.visitLabel(createStateInstance);
+
+		m.visitTypeInsn(Opcodes.NEW, "ExampleKt$example$1");
+		m.visitInsn(Opcodes.DUP);
+		m.visitVarInsn(Opcodes.ALOAD, continuationArgumentIndex);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL, "ExampleKt$example$1",
+				"<init>", "(Lkotlin/coroutines/Continuation;)V", false);
+
+		m.visitVarInsn(Opcodes.ASTORE, continuationIndex);
+
+		m.visitLabel(afterCoroutineStateCreated);
+
+		m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
+		m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "result",
+				"Ljava/lang/Object;");
+		m.visitVarInsn(Opcodes.ASTORE, 1);
+
+		m.visitMethodInsn(Opcodes.INVOKESTATIC,
+				"kotlin/coroutines/intrinsics/IntrinsicsKt",
+				"getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);
+
+		// line of "fun"
+		m.visitVarInsn(Opcodes.ASTORE, 3);
+
+		m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
+		m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I");
+		final Label dflt = new Label();
+		final Label state0 = new Label();
+		final Label state1 = new Label();
+		m.visitTableSwitchInsn(0, 1, dflt, state0, state1);
+
+		m.visitLabel(state0);
+
+		{
+			m.visitVarInsn(Opcodes.ALOAD, 1);
+			m.visitInsn(Opcodes.DUP);
+			m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
+			Label label = new Label();
+			m.visitJumpInsn(Opcodes.IFEQ, label);
+			m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
+			m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure",
+					"exception", "Ljava/lang/Throwable");
+			m.visitInsn(Opcodes.ATHROW);
+			m.visitInsn(Opcodes.POP);
+			range1.toInclusive = m.instructions.getLast();
+			m.visitLabel(label);
+		}
+
+		// line of "suspendingFunction"
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction",
+				"(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false);
+
+		m.visitInsn(Opcodes.DUP);
+		final Range range2 = new Range();
+		range2.fromInclusive = m.instructions.getLast();
+		m.visitVarInsn(Opcodes.ALOAD, 3);
+		final Label continuationLabelAfterLoadedResult = new Label();
+		m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationLabelAfterLoadedResult);
+		// line of "fun"
+		m.visitVarInsn(Opcodes.ALOAD, 3);
+		m.visitInsn(Opcodes.ARETURN);
+
+		m.visitLabel(state1);
+
+		{
+			m.visitVarInsn(Opcodes.ALOAD, 1);
+			m.visitInsn(Opcodes.DUP);
+			m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
+			final Label label = new Label();
+			m.visitJumpInsn(Opcodes.IFEQ, label);
+			m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
+			m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure",
+					"exception", "Ljava/lang/Throwable");
+			m.visitInsn(Opcodes.ATHROW);
+			m.visitInsn(Opcodes.POP);
+			m.visitLabel(label);
+		}
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		range2.toInclusive = m.instructions.getLast();
+		m.visitLabel(continuationLabelAfterLoadedResult);
+
+		// line after "suspendingFunction"
+		m.visitInsn(Opcodes.NOP);
+		m.visitInsn(Opcodes.ARETURN);
+
+		m.visitLabel(dflt);
+		final Range range0 = new Range();
+		range0.fromInclusive = m.instructions.getLast();
+		m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
+		m.visitInsn(Opcodes.DUP);
+		m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+				"java/lang/IllegalStateException", "<init>",
+				"(Ljava/lang/String;)V", false);
+		m.visitInsn(Opcodes.ATHROW);
+		range0.toInclusive = m.instructions.getLast();
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range0, range1, range2);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java
new file mode 100644
index 0000000..8dfa765
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilterTest.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit test for {@link KotlinDefaultArgumentsFilter}.
+ */
+public class KotlinDefaultArgumentsFilterTest extends FilterTestBase {
+
+	private final IFilter filter = new KotlinDefaultArgumentsFilter();
+
+	private static MethodNode createMethod(final int access, final String name,
+			final String descriptor) {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				access, name, descriptor, null, null);
+
+		m.visitVarInsn(Opcodes.ILOAD, 2);
+		m.visitInsn(Opcodes.ICONST_1);
+		m.visitInsn(Opcodes.IAND);
+		final Label label = new Label();
+		m.visitJumpInsn(Opcodes.IFEQ, label);
+		// default argument
+		m.visitLdcInsn(Integer.valueOf(42));
+		m.visitVarInsn(Opcodes.ISTORE, 1);
+		m.visitLabel(label);
+
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitVarInsn(Opcodes.ILOAD, 1);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL, "Target", "origin", "(I)V",
+				false);
+		m.visitInsn(Opcodes.RETURN);
+
+		return m;
+	}
+
+	@Test
+	public void should_filter() {
+		final MethodNode m = createMethod(Opcodes.ACC_SYNTHETIC,
+				"origin$default", "(LTarget;IILjava/lang/Object;)V");
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3)));
+	}
+
+	@Test
+	public void should_not_filter_when_not_kotlin() {
+		final MethodNode m = createMethod(Opcodes.ACC_SYNTHETIC,
+				"not_kotlin_synthetic$default",
+				"(LTarget;IILjava/lang/Object;)V");
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void should_not_filter_when_suffix_absent() {
+		final MethodNode m = createMethod(Opcodes.ACC_SYNTHETIC,
+				"synthetic_without_suffix", "(LTarget;IILjava/lang/Object;)V");
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void should_not_filter_when_not_synthetic() {
+		final MethodNode m = createMethod(0, "not_synthetic$default",
+				"(LTarget;IILjava/lang/Object;)V");
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java
new file mode 100644
index 0000000..8a6e835
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilterTest.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Nikolay Krasko - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link KotlinGeneratedFilter}.
+ */
+public class KotlinGeneratedFilterTest extends FilterTestBase {
+
+	private final IFilter filter = new KotlinGeneratedFilter();
+
+	@Test
+	public void testNoLinesForKotlinWithDebug() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		filter.filter(m, context, output);
+
+		assertMethodIgnored(m);
+	}
+
+	@Test
+	public void testWithLinesForKotlinWithDebug() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitAnnotation("Lother/Annotation;", false);
+		m.visitLineNumber(12, new Label());
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void testNoLinesNonKotlinWithDebug() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void testNoLinesForKotlinNoDebug() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+		context.sourceFileName = null;
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void testWithLinesForKotlinNoDebug() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"hashCode", "()I", null, null);
+		m.visitInsn(Opcodes.ICONST_0);
+		m.visitInsn(Opcodes.IRETURN);
+		m.visitLineNumber(12, new Label());
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+		context.sourceFileName = null;
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilterTest.java
new file mode 100644
index 0000000..fe3b955
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilterTest.java
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link KotlinInlineFilter}.
+ */
+public class KotlinInlineFilterTest extends FilterTestBase {
+
+	private final KotlinInlineFilter filter = new KotlinInlineFilter();
+
+	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+			"callsite", "()V", null, null);
+
+	@Test
+	public void should_filter() {
+		context.sourceFileName = "callsite.kt";
+		context.sourceDebugExtension = "" //
+				+ "SMAP\n" //
+				+ "callsite.kt\n" // OutputFileName=callsite.kt
+				+ "Kotlin\n" // DefaultStratumId=Kotlin
+				+ "*S Kotlin\n" // StratumID=Kotlin
+				+ "*F\n" // FileSection
+				+ "+ 1 callsite.kt\n" // FileID=1,FileName=callsite.kt
+				+ "CallsiteKt\n" //
+				+ "+ 2 a.kt\n" // FileID=2,FileName=a.kt
+				+ "AKt\n" //
+				+ "+ 3 b.kt\n" // FileID=3,FileName=b.kt
+				+ "BKt\n" //
+				+ "*L\n" // LineSection
+				+ "1#1,8:1\n" // InputStartLine=1,LineFileID=1,RepeatCount=8,OutputStartLine=1
+				+ "2#2,2:9\n" // InputStartLine=2,LineFileID=2,RepeatCount=2,OutputStartLine=9
+				+ "2#3,2:11\n" // InputStartLine=2,LineFileID=3,RepeatCount=2,OutputStartLine=11
+				+ "*E\n"; // EndSection
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		m.visitLineNumber(2, new Label());
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitLineNumber(9, new Label());
+		shouldIgnorePrevious(m);
+		m.visitMethodInsn(Opcodes.INVOKESTATIC, "Stubs", "nop", "()V", false);
+		shouldIgnorePrevious(m);
+		m.visitLineNumber(10, new Label());
+		shouldIgnorePrevious(m);
+		m.visitInsn(Opcodes.NOP);
+		shouldIgnorePrevious(m);
+
+		m.visitLineNumber(3, new Label());
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitLineNumber(11, new Label());
+		shouldIgnorePrevious(m);
+		m.visitMethodInsn(Opcodes.INVOKESTATIC, "Stubs", "nop", "()V", false);
+		shouldIgnorePrevious(m);
+		m.visitLineNumber(12, new Label());
+		shouldIgnorePrevious(m);
+		m.visitInsn(Opcodes.NOP);
+		shouldIgnorePrevious(m);
+
+		m.visitLineNumber(4, new Label());
+		m.visitInsn(Opcodes.RETURN);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(expectedRanges.toArray(new Range[0]));
+
+		// should not reparse:
+		context.sourceDebugExtension = "";
+		filter.filter(m, context, output);
+	}
+
+	/**
+	 * <pre>
+	 *     inline fun inlined_top_level() {
+	 *       Stubs.nop()
+	 *     }
+	 *
+	 *     class Callsite {
+	 *       fun inlined() {
+	 *           Stubs.nop()
+	 *       }
+	 *
+	 *       fun callsite {
+	 *         inlined_top_level()
+	 *         inlined()
+	 *       }
+	 *     }
+	 * </pre>
+	 */
+	@Test
+	public void should_filter_when_in_same_file() {
+		context.sourceFileName = "example.kt";
+		context.sourceDebugExtension = "" //
+				+ "SMAP\n" //
+				+ "example.kt\n" // OutputFileName=example.kt
+				+ "Kotlin\n" // DefaultStratumId=Kotlin
+				+ "*S Kotlin\n" // StratumID=Kotlin
+				+ "*F\n" // FileSection
+				+ "+ 1 example.kt\n" // FileID=1,FileName=example.kt
+				+ "Callsite\n" //
+				+ "+ 2 example.kt\n" // FileID=2,FileName=example.kt
+				+ "ExampleKt\n" //
+				+ "*L\n" // LineSection
+				+ "1#1,15:1\n" // InputStartLine=1,LineFileID=1,RepeatCount=10,OutputStartLine=1
+				+ "7#1,2:18\n" // InputStartLine=7,LineFileID=1,RepeatCount=2,OutputStartLine=18
+				+ "2#2,2:16\n" // InputStartLine=2,LineFileID=2,RepeatCount=2,OutputStartLine=16
+				+ "*E\n"; // EndSection
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		m.visitLineNumber(11, new Label());
+		m.visitInsn(Opcodes.NOP);
+		m.visitLineNumber(16, new Label());
+		shouldIgnorePrevious(m);
+		m.visitMethodInsn(Opcodes.INVOKESTATIC, "Stubs", "nop", "()V", false);
+		shouldIgnorePrevious(m);
+		m.visitLineNumber(17, new Label());
+		shouldIgnorePrevious(m);
+		m.visitInsn(Opcodes.NOP);
+		shouldIgnorePrevious(m);
+
+		m.visitLineNumber(12, new Label());
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitVarInsn(Opcodes.ASTORE, 1);
+		m.visitLineNumber(18, new Label());
+		shouldIgnorePrevious(m);
+		m.visitMethodInsn(Opcodes.INVOKESTATIC, "Stubs", "nop", "()V", false);
+		shouldIgnorePrevious(m);
+		m.visitLineNumber(19, new Label());
+		shouldIgnorePrevious(m);
+		m.visitInsn(Opcodes.NOP);
+		shouldIgnorePrevious(m);
+
+		m.visitLineNumber(13, new Label());
+		m.visitInsn(Opcodes.RETURN);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(expectedRanges.toArray(new Range[0]));
+	}
+
+	@Test
+	public void should_not_parse_SourceDebugExtension_attribute_when_no_kotlin_metadata_annotation() {
+		context.sourceDebugExtension = "SMAP";
+
+		m.visitLineNumber(1, new Label());
+		m.visitInsn(Opcodes.RETURN);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void should_not_filter_when_no_SourceDebugExtension_attribute() {
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		m.visitLineNumber(1, new Label());
+		m.visitInsn(Opcodes.RETURN);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+	}
+
+	@Test
+	public void should_throw_exception_when_SMAP_incomplete() {
+		context.sourceDebugExtension = "" //
+				+ "SMAP\n";
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		try {
+			filter.filter(m, context, output);
+			fail("exception expected");
+		} catch (final IllegalStateException e) {
+			assertEquals("Unexpected SMAP line: null", e.getMessage());
+		}
+	}
+
+	@Test
+	public void should_throw_exception_when_unexpected_FileInfo() {
+		context.sourceFileName = "callsite.kt";
+		context.sourceDebugExtension = "" //
+				+ "SMAP\n" //
+				+ "callsite.kt\n" //
+				+ "Kotlin\n" //
+				+ "*S Kotlin\n" //
+				+ "*F\n" //
+				+ "xxx";
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		try {
+			filter.filter(m, context, output);
+			fail("exception expected");
+		} catch (final IllegalStateException e) {
+			assertEquals("Unexpected SMAP line: xxx", e.getMessage());
+		}
+	}
+
+	@Test
+	public void should_throw_exception_when_no_SourceFileId_for_SourceFile() {
+		context.sourceFileName = "example.kt";
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+		context.sourceDebugExtension = "" //
+				+ "SMAP\n" //
+				+ "example.kt\n" //
+				+ "Kotlin\n" //
+				+ "*S Kotlin\n" //
+				+ "*F\n" //
+				+ "+ 1 another.kt\n" //
+				+ "AnotherKt\n" //
+				+ "*L\n" //
+				+ "*E\n";
+
+		try {
+			filter.filter(m, context, output);
+			fail("exception expected");
+		} catch (final IllegalStateException e) {
+			assertEquals("Unexpected SMAP FileSection", e.getMessage());
+		}
+	}
+
+	@Test
+	public void should_throw_exception_when_unexpected_LineInfo() {
+		context.sourceFileName = "callsite.kt";
+		context.sourceDebugExtension = "" //
+				+ "SMAP\n" //
+				+ "callsite.kt\n" //
+				+ "Kotlin\n" //
+				+ "*S Kotlin\n" //
+				+ "*F\n" //
+				+ "+ 1 callsite.kt\n" //
+				+ "Callsite\n" //
+				+ "*L\n" //
+				+ "xxx";
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+		try {
+			filter.filter(m, context, output);
+			fail("exception expected");
+		} catch (final IllegalStateException e) {
+			assertEquals("Unexpected SMAP line: xxx", e.getMessage());
+		}
+	}
+
+	private final List<Range> expectedRanges = new ArrayList<Range>();
+
+	private void shouldIgnorePrevious(final MethodNode m) {
+		expectedRanges.add(
+				new Range(m.instructions.getLast(), m.instructions.getLast()));
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
new file mode 100644
index 0000000..c9e34ba
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Fabian Mastenbroek - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link KotlinLateinitFilter}.
+ */
+public class KotlinLateinitFilterTest extends FilterTestBase {
+
+	private final KotlinLateinitFilter filter = new KotlinLateinitFilter();
+
+	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+			"name", "()V", null, null);
+
+	@Test
+	public void testLateinitBranchIsFiltered() {
+		final Label l1 = new Label();
+		final Label l2 = new Label();
+
+		m.visitLabel(l1);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitFieldInsn(Opcodes.GETFIELD,
+				"com/better/alarm/background/VibrationService", "wakeLock",
+				"Landroid/os/PowerManager$WakeLock;");
+		m.visitInsn(Opcodes.DUP);
+		m.visitJumpInsn(Opcodes.IFNONNULL, l2);
+
+		final AbstractInsnNode expectedFrom = m.instructions.getLast();
+
+		m.visitLdcInsn("wakelock");
+		m.visitMethodInsn(Opcodes.INVOKESTATIC,
+				"kotlin/jvm/internal/Intrinsics",
+				"throwUninitializedPropertyAccessException",
+				"(Ljava/lang/String;)V", false);
+		final AbstractInsnNode expectedTo = m.instructions.getLast();
+		m.visitLabel(l2);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+				"android/os/PowerManager$WakeLock", "acquire", "", false);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(new Range(expectedFrom, expectedTo));
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilterTest.java
new file mode 100644
index 0000000..0d08ae3
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilterTest.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link KotlinNotNullOperatorFilter}.
+ */
+public class KotlinNotNullOperatorFilterTest extends FilterTestBase {
+
+	private final KotlinNotNullOperatorFilter filter = new KotlinNotNullOperatorFilter();
+
+	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+			"example", "()V", null, null);
+
+	/**
+	 * <pre>
+	 *     return x!!.length
+	 * </pre>
+	 */
+	@Test
+	public void should_filter() {
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitInsn(Opcodes.DUP);
+
+		final Range range = new Range();
+		final Label label = new Label();
+		m.visitJumpInsn(Opcodes.IFNONNULL, label);
+		range.fromInclusive = m.instructions.getLast();
+		// no line number here and hence no probe
+		m.visitMethodInsn(Opcodes.INVOKESTATIC,
+				"kotlin/jvm/internal/Intrinsics", "throwNpe", "()V", false);
+		range.toInclusive = m.instructions.getLast();
+
+		m.visitLabel(label);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length",
+				"()I", false);
+		m.visitInsn(Opcodes.IRETURN);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java
new file mode 100644
index 0000000..9fc3b3d
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link KotlinUnsafeCastOperatorFilter}.
+ */
+public class KotlinUnsafeCastOperatorFilterTest extends FilterTestBase {
+
+	private final KotlinUnsafeCastOperatorFilter filter = new KotlinUnsafeCastOperatorFilter();
+
+	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+			"name", "()V", null, null);
+
+	@Test
+	public void should_filter() {
+		final Label label = new Label();
+
+		m.visitInsn(Opcodes.DUP);
+		m.visitJumpInsn(Opcodes.IFNONNULL, label);
+		final AbstractInsnNode expectedFrom = m.instructions.getLast();
+		m.visitTypeInsn(Opcodes.NEW, "kotlin/TypeCastException");
+		m.visitInsn(Opcodes.DUP);
+		m.visitLdcInsn("null cannot be cast to non-null type kotlin.String");
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL, "kotlin/TypeCastException",
+				"<init>", "(Ljava/lang/String;)V", false);
+		m.visitInsn(Opcodes.ATHROW);
+		final AbstractInsnNode expectedTo = m.instructions.getLast();
+		m.visitLabel(label);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(new Range(expectedFrom, expectedTo));
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilterTest.java
new file mode 100644
index 0000000..04d40a0
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilterTest.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link KotlinWhenFilter}.
+ */
+public class KotlinWhenFilterTest extends FilterTestBase {
+
+	private final KotlinWhenFilter filter = new KotlinWhenFilter();
+
+	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+			"name", "()V", null, null);
+
+	@Test
+	public void should_filter_implicit_else() {
+		final Label label = new Label();
+
+		final Range range1 = new Range();
+
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitJumpInsn(Opcodes.IFEQ, label);
+		range1.fromInclusive = m.instructions.getLast();
+		range1.toInclusive = m.instructions.getLast();
+
+		m.visitInsn(Opcodes.NOP);
+
+		final Range range2 = new Range();
+		m.visitLabel(label);
+		range2.fromInclusive = m.instructions.getLast();
+		m.visitTypeInsn(Opcodes.NEW, "kotlin/NoWhenBranchMatchedException");
+		m.visitInsn(Opcodes.DUP);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+				"kotlin/NoWhenBranchMatchedException", "<init>", "()V", false);
+		m.visitInsn(Opcodes.ATHROW);
+		range2.toInclusive = m.instructions.getLast();
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range1, range2);
+		assertNoReplacedBranches();
+	}
+
+	@Test
+	public void should_not_filter_explicit_else() {
+		final Label label = new Label();
+
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitJumpInsn(Opcodes.IFEQ, label);
+
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitLabel(label);
+		m.visitTypeInsn(Opcodes.NEW, "kotlin/NoWhenBranchMatchedException");
+		m.visitInsn(Opcodes.DUP);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+				"kotlin/NoWhenBranchMatchedException", "<init>", "()V", false);
+		m.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Throwable");
+		m.visitInsn(Opcodes.ATHROW);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
+		assertNoReplacedBranches();
+	}
+
+	@Test
+	public void should_filter_implicit_default() {
+		final Label case1 = new Label();
+		final Label caseDefault = new Label();
+		final Label after = new Label();
+
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitTableSwitchInsn(0, 0, caseDefault, case1);
+		final AbstractInsnNode switchNode = m.instructions.getLast();
+		final Set<AbstractInsnNode> newTargets = new HashSet<AbstractInsnNode>();
+
+		m.visitLabel(case1);
+		m.visitInsn(Opcodes.ICONST_1);
+		newTargets.add(m.instructions.getLast());
+		m.visitJumpInsn(Opcodes.GOTO, after);
+
+		final Range range1 = new Range();
+		m.visitLabel(caseDefault);
+		range1.fromInclusive = m.instructions.getLast();
+		m.visitTypeInsn(Opcodes.NEW, "kotlin/NoWhenBranchMatchedException");
+		m.visitInsn(Opcodes.DUP);
+		m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+				"kotlin/NoWhenBranchMatchedException", "<init>", "()V", false);
+		m.visitInsn(Opcodes.ATHROW);
+		range1.toInclusive = m.instructions.getLast();
+
+		m.visitLabel(after);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range1);
+		assertReplacedBranches(switchNode, newTargets);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java
new file mode 100644
index 0000000..df42803
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilterTest.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link KotlinWhenStringFilter}.
+ */
+public class KotlinWhenStringFilterTest extends FilterTestBase {
+
+	private final IFilter filter = new KotlinWhenStringFilter();
+
+	@Test
+	public void should_filter() {
+		final Set<AbstractInsnNode> expectedNewTargets = new HashSet<AbstractInsnNode>();
+
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"name", "()V", null, null);
+
+		final Label h1 = new Label();
+		final Label sameHash = new Label();
+		final Label h2 = new Label();
+		final Label case1 = new Label();
+		final Label case2 = new Label();
+		final Label case3 = new Label();
+		final Label defaultCase = new Label();
+
+		// filter should not remember this unrelated slot
+		m.visitLdcInsn("");
+		m.visitVarInsn(Opcodes.ASTORE, 1);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+
+		// switch (...)
+		m.visitVarInsn(Opcodes.ASTORE, 2);
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
+				"()I", false);
+		m.visitTableSwitchInsn(97, 98, defaultCase, h1, h2);
+
+		// case "a"
+		m.visitLabel(h1);
+		final AbstractInsnNode expectedFromInclusive = m.instructions.getLast();
+
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitLdcInsn("a");
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+				"(Ljava/lang/Object;)Z", false);
+		m.visitJumpInsn(Opcodes.IFEQ, sameHash);
+		m.visitJumpInsn(Opcodes.GOTO, case1);
+
+		// case "\u0000a"
+		m.visitLabel(sameHash);
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitLdcInsn("\u0000a");
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+				"(Ljava/lang/Object;)Z", false);
+		m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
+		m.visitJumpInsn(Opcodes.GOTO, case2);
+
+		// case "b"
+		m.visitLabel(h2);
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitLdcInsn("\u0000a");
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+				"(Ljava/lang/Object;)Z", false);
+		m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
+		m.visitJumpInsn(Opcodes.GOTO, case3);
+		final AbstractInsnNode expectedToInclusive = m.instructions.getLast();
+
+		m.visitLabel(case1);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+		m.visitLabel(case2);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+		m.visitLabel(case3);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+		m.visitLabel(defaultCase);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+
+		filter.filter(m, context, output);
+
+		assertReplacedBranches(expectedFromInclusive.getPrevious(),
+				expectedNewTargets);
+		assertIgnored(new Range(expectedFromInclusive, expectedToInclusive));
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java
deleted file mode 100644
index 3e2b497..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilterTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.internal.analysis.filter;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import org.jacoco.core.internal.instr.InstrSupport;
-import org.junit.Test;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
-import org.objectweb.asm.tree.MethodNode;
-
-public class LombokGeneratedFilterTest implements IFilterOutput {
-
-	private final IFilter filter = new LombokGeneratedFilter();
-
-	private AbstractInsnNode fromInclusive;
-	private AbstractInsnNode toInclusive;
-
-	@Test
-	public void testNoAnnotations() {
-		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
-				"hashCode", "()I", null, null);
-
-		m.visitInsn(Opcodes.ICONST_0);
-		m.visitInsn(Opcodes.IRETURN);
-
-		filter.filter("Foo", "java/lang/Object", m, this);
-
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
-	}
-
-	@Test
-	public void testOtherAnnotation() {
-		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
-				"hashCode", "()I", null, null);
-		m.visitAnnotation("Lother/Annotation;", false);
-
-		m.visitInsn(Opcodes.ICONST_0);
-		m.visitInsn(Opcodes.IRETURN);
-
-		filter.filter("Foo", "java/lang/Object", m, this);
-
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
-	}
-
-	@Test
-	public void testLombokGeneratedAnnotation() {
-		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
-				"hashCode", "()I", null, null);
-		m.visitAnnotation("Llombok/Generated;", false);
-
-		m.visitInsn(Opcodes.ICONST_0);
-		m.visitInsn(Opcodes.IRETURN);
-
-		filter.filter("Foo", "java/lang/Object", m, this);
-
-		assertEquals(m.instructions.getFirst(), fromInclusive);
-		assertEquals(m.instructions.getLast(), toInclusive);
-	}
-
-	public void ignore(final AbstractInsnNode fromInclusive,
-			final AbstractInsnNode toInclusive) {
-		assertNull(this.fromInclusive);
-		this.fromInclusive = fromInclusive;
-		this.toInclusive = toInclusive;
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java
index 24c6760..ac42e64 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,22 +11,18 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Test;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
-public class PrivateEmptyNoArgConstructorFilterTest implements IFilterOutput {
+/**
+ * Unit tests for {@link PrivateEmptyNoArgConstructorFilter}.
+ */
+public class PrivateEmptyNoArgConstructorFilterTest extends FilterTestBase {
 
 	private final IFilter filter = new PrivateEmptyNoArgConstructorFilter();
 
-	private AbstractInsnNode fromInclusive;
-	private AbstractInsnNode toInclusive;
-
 	@Test
 	public void test() {
 		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
@@ -37,20 +33,9 @@
 				"()V", false);
 		m.visitInsn(Opcodes.RETURN);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(m.instructions.getFirst(), fromInclusive);
-		assertEquals(m.instructions.getLast(), toInclusive);
-	}
-
-	public void ignore(final AbstractInsnNode fromInclusive,
-			final AbstractInsnNode toInclusive) {
-		this.fromInclusive = fromInclusive;
-		this.toInclusive = toInclusive;
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
+		assertMethodIgnored(m);
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilterTest.java
new file mode 100644
index 0000000..3f72618
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilterTest.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link StringSwitchEcjFilter}.
+ */
+public class StringSwitchEcjFilterTest extends FilterTestBase {
+
+	private final IFilter filter = new StringSwitchEcjFilter();
+
+	@Test
+	public void should_filter() {
+		final Set<AbstractInsnNode> expectedNewTargets = new HashSet<AbstractInsnNode>();
+
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"name", "()V", null, null);
+
+		final Label case1 = new Label();
+		final Label case2 = new Label();
+		final Label case3 = new Label();
+		final Label caseDefault = new Label();
+		final Label h1 = new Label();
+		final Label h2 = new Label();
+
+		// filter should not remember this unrelated slot
+		m.visitLdcInsn("");
+		m.visitVarInsn(Opcodes.ASTORE, 1);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+
+		// switch (...)
+		m.visitInsn(Opcodes.DUP);
+		m.visitVarInsn(Opcodes.ASTORE, 2);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
+				"()I", false);
+		m.visitTableSwitchInsn(97, 98, caseDefault, h1, h2);
+		final AbstractInsnNode switchNode = m.instructions.getLast();
+
+		m.visitLabel(h1);
+
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitLdcInsn("a");
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+				"(Ljava/lang/Object;)Z", false);
+		// if equal "a", then goto its case
+		m.visitJumpInsn(Opcodes.IFNE, case1);
+
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitLdcInsn("\0a");
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+				"(Ljava/lang/Object;)Z", false);
+		// if equal "\0a", then goto its case
+		m.visitJumpInsn(Opcodes.IFNE, case2);
+
+		// goto default case
+		m.visitJumpInsn(Opcodes.GOTO, caseDefault);
+
+		m.visitLabel(h2);
+
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitLdcInsn("b");
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+				"(Ljava/lang/Object;)Z", false);
+		// if equal "b", then goto its case
+		m.visitJumpInsn(Opcodes.IFNE, case3);
+
+		// goto default case
+		m.visitJumpInsn(Opcodes.GOTO, caseDefault);
+		final AbstractInsnNode expectedToInclusive = m.instructions.getLast();
+
+		m.visitLabel(case1);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+		m.visitLabel(case2);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+		m.visitLabel(case3);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+		m.visitLabel(caseDefault);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+
+		filter.filter(m, context, output);
+
+		assertReplacedBranches(switchNode, expectedNewTargets);
+		assertIgnored(new Range(switchNode.getNext(), expectedToInclusive));
+	}
+
+	@Test
+	public void should_filter_when_default_is_first() {
+		final Set<AbstractInsnNode> expectedNewTargets = new HashSet<AbstractInsnNode>();
+
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+				"name", "()V", null, null);
+
+		final Label case1 = new Label();
+		final Label caseDefault = new Label();
+		final Label h1 = new Label();
+
+		// filter should not remember this unrelated slot
+		m.visitLdcInsn("");
+		m.visitVarInsn(Opcodes.ASTORE, 1);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+
+		// switch (...)
+		m.visitInsn(Opcodes.DUP);
+		m.visitVarInsn(Opcodes.ASTORE, 2);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
+				"()I", false);
+		m.visitLookupSwitchInsn(caseDefault, new int[] { 97 },
+				new Label[] { h1 });
+		final AbstractInsnNode switchNode = m.instructions.getLast();
+
+		m.visitLabel(h1);
+
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitLdcInsn("a");
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals",
+				"(Ljava/lang/Object;)Z", false);
+		// if equal "a", then goto its case
+		m.visitJumpInsn(Opcodes.IFNE, case1);
+
+		final AbstractInsnNode expectedToInclusive = m.instructions.getLast();
+
+		m.visitLabel(caseDefault);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+		m.visitLabel(case1);
+		m.visitInsn(Opcodes.RETURN);
+		expectedNewTargets.add(m.instructions.getLast());
+
+		filter.filter(m, context, output);
+
+		assertReplacedBranches(switchNode, expectedNewTargets);
+		assertIgnored(new Range(switchNode.getNext(), expectedToInclusive));
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java
index 2dd9359..592c699 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,10 +11,6 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Test;
 import org.objectweb.asm.Label;
@@ -22,23 +18,24 @@
 import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
-public class StringSwitchJavacFilterTest implements IFilterOutput {
+/**
+ * Unit tests for {@link StringSwitchJavacFilter}.
+ */
+public class StringSwitchJavacFilterTest extends FilterTestBase {
 
 	private final IFilter filter = new StringSwitchJavacFilter();
 
 	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
 			"name", "()V", null, null);
 
-	private AbstractInsnNode fromInclusive;
-	private AbstractInsnNode toInclusive;
+	private AbstractInsnNode expectedFromInclusive;
+	private AbstractInsnNode expectedToInclusive;
 
-	@Test
-	public void should_filter_code_generated_by_javac() {
+	private void createFirstSwitch() {
 		final Label h1 = new Label();
 		final Label h1_2 = new Label();
 		final Label h2 = new Label();
 		final Label secondSwitch = new Label();
-		final Label cases = new Label();
 
 		m.visitInsn(Opcodes.ICONST_M1);
 		m.visitVarInsn(Opcodes.ISTORE, 2);
@@ -48,7 +45,7 @@
 				"()I", false);
 		m.visitLookupSwitchInsn(secondSwitch, new int[] { 97, 98 },
 				new Label[] { h1, h2 });
-		final AbstractInsnNode fromInclusive = m.instructions.getLast();
+		expectedFromInclusive = m.instructions.getLast();
 
 		m.visitLabel(h1);
 		m.visitVarInsn(Opcodes.ALOAD, 1);
@@ -87,15 +84,34 @@
 		m.visitVarInsn(Opcodes.ISTORE, 2);
 
 		m.visitLabel(secondSwitch);
-		final AbstractInsnNode toInclusive = m.instructions.getLast();
+		expectedToInclusive = m.instructions.getLast();
 		m.visitVarInsn(Opcodes.ILOAD, 2);
+	}
+
+	@Test
+	public void should_filter_code_generated_by_javac() {
+		createFirstSwitch();
+
+		final Label cases = new Label();
 		m.visitTableSwitchInsn(0, 2, cases);
 		m.visitLabel(cases);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(fromInclusive, this.fromInclusive);
-		assertEquals(toInclusive, this.toInclusive);
+		assertIgnored(new Range(expectedFromInclusive, expectedToInclusive));
+	}
+
+	@Test
+	public void should_filter_when_javac_generates_lookupswitch() {
+		createFirstSwitch();
+
+		final Label cases = new Label();
+		m.visitLookupSwitchInsn(cases, null, new Label[] {});
+		m.visitLabel(cases);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(new Range(expectedFromInclusive, expectedToInclusive));
 	}
 
 	@Test
@@ -140,21 +156,9 @@
 
 		m.visitLabel(cases);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertNull(this.fromInclusive);
-		assertNull(this.toInclusive);
-	}
-
-	public void ignore(final AbstractInsnNode fromInclusive,
-			final AbstractInsnNode toInclusive) {
-		assertNull(this.fromInclusive);
-		this.fromInclusive = fromInclusive;
-		this.toInclusive = toInclusive;
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
+		assertIgnored();
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java
index 5e2b437..a40b234 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,28 +11,23 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Test;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.LabelNode;
 import org.objectweb.asm.tree.MethodNode;
 
-public class SynchronizedFilterTest implements IFilterOutput {
+/**
+ * Unit tests for {@link SynchronizedFilter}.
+ */
+public class SynchronizedFilterTest extends FilterTestBase {
 
 	private final SynchronizedFilter filter = new SynchronizedFilter();
 
 	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
 			"name", "()V", null, null);
 
-	private AbstractInsnNode fromInclusive;
-	private AbstractInsnNode toInclusive;
-
 	@Test
 	public void javac() {
 		final Label start = new Label();
@@ -64,9 +59,10 @@
 		m.visitLabel(exit);
 		m.visitInsn(Opcodes.RETURN);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
-		assertEquals(handler.info, fromInclusive);
-		assertEquals(((LabelNode) exit.info).getPrevious(), toInclusive);
+		filter.filter(m, context, output);
+
+		assertIgnored(new Range((LabelNode) handler.info,
+				((LabelNode) exit.info).getPrevious()));
 	}
 
 	/**
@@ -117,8 +113,9 @@
 		m.visitLabel(exit);
 		m.visitInsn(Opcodes.RETURN);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
-		assertNull(fromInclusive);
+		filter.filter(m, context, output);
+
+		assertIgnored();
 	}
 
 	@Test
@@ -152,20 +149,10 @@
 		m.visitLabel(exit);
 		m.visitInsn(Opcodes.RETURN);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
-		assertEquals(handler.info, fromInclusive);
-		assertEquals(((LabelNode) exit.info).getPrevious(), toInclusive);
-	}
+		filter.filter(m, context, output);
 
-	public void ignore(AbstractInsnNode fromInclusive,
-			AbstractInsnNode toInclusive) {
-		assertNull(this.fromInclusive);
-		this.fromInclusive = fromInclusive;
-		this.toInclusive = toInclusive;
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
+		assertIgnored(new Range((LabelNode) handler.info,
+			((LabelNode) exit.info).getPrevious()));
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java
index 06344d5..5bbae98 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SyntheticFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,33 +11,27 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Test;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
-public class SyntheticFilterTest implements IFilterOutput {
+/**
+ * Unit tests for {@link SyntheticFilter}.
+ */
+public class SyntheticFilterTest extends FilterTestBase {
 
 	private final SyntheticFilter filter = new SyntheticFilter();
 
-	private AbstractInsnNode fromInclusive;
-	private AbstractInsnNode toInclusive;
-
 	@Test
 	public void testNonSynthetic() {
 		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
 				"name", "()V", null, null);
 		m.visitInsn(Opcodes.NOP);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
+		assertIgnored();
 	}
 
 	@Test
@@ -46,10 +40,9 @@
 				Opcodes.ACC_SYNTHETIC, "name", "()V", null, null);
 		m.visitInsn(Opcodes.NOP);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(m.instructions.getFirst(), fromInclusive);
-		assertEquals(m.instructions.getLast(), toInclusive);
+		assertMethodIgnored(m);
 	}
 
 	@Test
@@ -58,21 +51,50 @@
 				Opcodes.ACC_SYNTHETIC, "lambda$1", "()V", null, null);
 		m.visitInsn(Opcodes.NOP);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertNull(fromInclusive);
-		assertNull(toInclusive);
+		assertIgnored();
 	}
 
-	public void ignore(final AbstractInsnNode fromInclusive,
-			final AbstractInsnNode toInclusive) {
-		assertNull(this.fromInclusive);
-		this.fromInclusive = fromInclusive;
-		this.toInclusive = toInclusive;
+	@Test
+	public void should_not_filter_method_with_suffix_default_in_kotlin_classes() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE, "example$default",
+				"(LTarget;Ljava/lang/String;Ijava/lang/Object;)V", null, null);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+		m.visitInsn(Opcodes.NOP);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
 	}
 
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
+	@Test
+	public void should_filter_synthetic_method_with_suffix_default_in_non_kotlin_classes() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE, "example$default",
+				"(LTarget;Ljava/lang/String;Ijava/lang/Object;)V", null, null);
+		m.visitInsn(Opcodes.NOP);
+
+		filter.filter(m, context, output);
+
+		assertMethodIgnored(m);
+	}
+
+	@Test
+	public void should_not_filter_synthetic_methods_whose_last_argument_is_kotlin_coroutine_continuation() {
+		final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
+				Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC, "example",
+				"(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null,
+				null);
+		context.classAnnotations
+				.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+		m.visitInsn(Opcodes.NOP);
+
+		filter.filter(m, context, output);
+
+		assertIgnored();
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java
index 248ca4e..2a930d0 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,20 +11,16 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.List;
-
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Test;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
-public class TryWithResourcesEcjFilterTest implements IFilterOutput {
+/**
+ * Unit tests for {@link TryWithResourcesEcjFilter}.
+ */
+public class TryWithResourcesEcjFilterTest extends FilterTestBase {
 
 	private final TryWithResourcesEcjFilter filter = new TryWithResourcesEcjFilter();
 
@@ -310,15 +306,9 @@
 		// additional handlers
 		m.visitInsn(Opcodes.NOP);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(2, from.size());
-
-		assertEquals(range0.fromInclusive, from.get(0));
-		assertEquals(range0.toInclusive, to.get(0));
-
-		assertEquals(range1.fromInclusive, from.get(1));
-		assertEquals(range1.toInclusive, to.get(1));
+		assertIgnored(range0, range1);
 	}
 
 	/**
@@ -598,32 +588,9 @@
 		// additional handlers
 		m.visitInsn(Opcodes.NOP);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(2, from.size());
-
-		assertEquals(range0.fromInclusive, from.get(0));
-		assertEquals(range0.toInclusive, to.get(0));
-
-		assertEquals(range1.fromInclusive, from.get(1));
-		assertEquals(range1.toInclusive, to.get(1));
-	}
-
-	static class Range {
-		AbstractInsnNode fromInclusive;
-		AbstractInsnNode toInclusive;
-	}
-
-	private final List<AbstractInsnNode> from = new ArrayList<AbstractInsnNode>();
-	private final List<AbstractInsnNode> to = new ArrayList<AbstractInsnNode>();
-
-	public void ignore(AbstractInsnNode from, AbstractInsnNode to) {
-		this.from.add(from);
-		this.to.add(to);
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
+		assertIgnored(range0, range1);
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11FilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11FilterTest.java
new file mode 100644
index 0000000..cab9ee1
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11FilterTest.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.junit.Test;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Unit tests for {@link TryWithResourcesJavac11Filter}.
+ */
+public class TryWithResourcesJavac11FilterTest extends FilterTestBase {
+
+	private final TryWithResourcesJavac11Filter filter = new TryWithResourcesJavac11Filter();
+
+	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+			"name", "()V", null, null);
+
+	/**
+	 * <pre>
+	 *   try (r = new ...) {
+	 *     ...
+	 *   }
+	 * </pre>
+	 */
+	@Test
+	public void without_null_check() {
+		final Range range1 = new Range();
+		final Range range2 = new Range();
+
+		final Label e = new Label();
+		final Label t = new Label();
+
+		final Label handler = new Label();
+		m.visitTryCatchBlock(handler, handler, handler, "java/lang/Throwable");
+
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		range1.fromInclusive = m.instructions.getLast();
+		m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Resource", "close",
+			"()V", false);
+		m.visitJumpInsn(Opcodes.GOTO, e);
+		range1.toInclusive = m.instructions.getLast();
+
+		m.visitLabel(handler);
+		range2.fromInclusive = m.instructions.getLast();
+		m.visitVarInsn(Opcodes.ASTORE, 1);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Resource", "close",
+			"()V", false);
+		m.visitJumpInsn(Opcodes.GOTO, t);
+
+		m.visitVarInsn(Opcodes.ASTORE, 2);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable",
+			"addSuppressed", "(Ljava/lang/Throwable;)V", false);
+		m.visitLabel(t);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitInsn(Opcodes.ATHROW);
+		range2.toInclusive = m.instructions.getLast();
+
+		m.visitLabel(e);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range1, range2);
+	}
+
+	/**
+	 * <pre>
+	 *   try (r = open()) {
+	 *     ...
+	 *   }
+	 * </pre>
+	 */
+	@Test
+	public void with_null_check() {
+		final Range range1 = new Range();
+		final Range range2 = new Range();
+
+		final Label e = new Label();
+		final Label t = new Label();
+
+		final Label handler = new Label();
+		m.visitTryCatchBlock(handler, handler, handler, "java/lang/Throwable");
+
+		m.visitInsn(Opcodes.NOP);
+
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		range1.fromInclusive = m.instructions.getLast();
+		m.visitJumpInsn(Opcodes.IFNULL, e);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Resource", "close",
+				"()V", false);
+		m.visitJumpInsn(Opcodes.GOTO, e);
+		range1.toInclusive = m.instructions.getLast();
+
+		m.visitLabel(handler);
+		range2.fromInclusive = m.instructions.getLast();
+		m.visitVarInsn(Opcodes.ASTORE, 1);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitJumpInsn(Opcodes.IFNULL, t);
+		m.visitVarInsn(Opcodes.ALOAD, 0);
+		m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Resource", "close",
+				"()V", false);
+		m.visitJumpInsn(Opcodes.GOTO, t);
+
+		m.visitVarInsn(Opcodes.ASTORE, 2);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitVarInsn(Opcodes.ALOAD, 2);
+		m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable",
+				"addSuppressed", "(Ljava/lang/Throwable;)V", false);
+		m.visitLabel(t);
+		m.visitVarInsn(Opcodes.ALOAD, 1);
+		m.visitInsn(Opcodes.ATHROW);
+		range2.toInclusive = m.instructions.getLast();
+
+		m.visitLabel(e);
+
+		filter.filter(m, context, output);
+
+		assertIgnored(range1, range2);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java
index 83109ea..002ad33 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,20 +11,16 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.List;
-
 import org.jacoco.core.internal.instr.InstrSupport;
 import org.junit.Test;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
-public class TryWithResourcesJavacFilterTest implements IFilterOutput {
+/**
+ * Unit tests for {@link TryWithResourcesJavacFilter}.
+ */
+public class TryWithResourcesJavacFilterTest extends FilterTestBase {
 
 	private final TryWithResourcesJavacFilter filter = new TryWithResourcesJavacFilter();
 
@@ -219,21 +215,9 @@
 		m.visitVarInsn(Opcodes.ALOAD, 8);
 		m.visitInsn(Opcodes.ATHROW);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(4, from.size());
-
-		assertEquals(range0.fromInclusive, from.get(0));
-		assertEquals(range0.toInclusive, to.get(0));
-
-		assertEquals(range1.fromInclusive, from.get(1));
-		assertEquals(range1.toInclusive, to.get(1));
-
-		assertEquals(range2.fromInclusive, from.get(2));
-		assertEquals(range2.toInclusive, to.get(2));
-
-		assertEquals(range3.fromInclusive, from.get(3));
-		assertEquals(range3.toInclusive, to.get(3));
+		assertIgnored(range0, range1, range2, range3);
 	}
 
 	/**
@@ -548,21 +532,9 @@
 		m.visitVarInsn(Opcodes.ALOAD, 11);
 		m.visitInsn(Opcodes.ATHROW);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(4, from.size());
-
-		assertEquals(range0.fromInclusive, from.get(0));
-		assertEquals(range0.toInclusive, to.get(0));
-
-		assertEquals(range1.fromInclusive, from.get(1));
-		assertEquals(range1.toInclusive, to.get(1));
-
-		assertEquals(range2.fromInclusive, from.get(2));
-		assertEquals(range2.toInclusive, to.get(2));
-
-		assertEquals(range3.fromInclusive, from.get(3));
-		assertEquals(range3.toInclusive, to.get(3));
+		assertIgnored(range0, range1, range2, range3);
 	}
 
 	/**
@@ -726,15 +698,9 @@
 
 		m.visitLabel(end);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(2, from.size());
-
-		assertEquals(range0.fromInclusive, from.get(0));
-		assertEquals(range0.toInclusive, to.get(0));
-
-		assertEquals(range1.fromInclusive, from.get(1));
-		assertEquals(range1.toInclusive, to.get(1));
+		assertIgnored(range0, range1);
 	}
 
 	/**
@@ -794,26 +760,9 @@
 		m.visitVarInsn(Opcodes.ALOAD, 4);
 		m.visitInsn(Opcodes.ATHROW);
 
-		filter.filter("Foo", "java/lang/Object", m, this);
+		filter.filter(m, context, output);
 
-		assertEquals(0, from.size());
-	}
-
-	static class Range {
-		AbstractInsnNode fromInclusive;
-		AbstractInsnNode toInclusive;
-	}
-
-	private final List<AbstractInsnNode> from = new ArrayList<AbstractInsnNode>();
-	private final List<AbstractInsnNode> to = new ArrayList<AbstractInsnNode>();
-
-	public void ignore(AbstractInsnNode from, AbstractInsnNode to) {
-		this.from.add(from);
-		this.to.add(to);
-	}
-
-	public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
-		fail();
+		assertIgnored();
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/data/CRC64Test.java b/org.jacoco.core.test/src/org/jacoco/core/internal/data/CRC64Test.java
index 5b5f421..821e2fa 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/data/CRC64Test.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/data/CRC64Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,7 +26,10 @@
 public class CRC64Test {
 
 	@Test
-	public void testJava9() {
+	public void except_java_9_checksums_should_be_different_for_different_bytecode_versions() {
+		assertEquals(0x589E9080A572741EL,
+				CRC64.classId(createClass(Opcodes.V10)));
+
 		// should remove workaround for Java 9
 		// during change of exec file version
 		assertEquals(0x1007, ExecutionDataWriter.FORMAT_VERSION);
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/data/CompactDataInputOutputTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/data/CompactDataInputOutputTest.java
index 098db91..798bf0d 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/data/CompactDataInputOutputTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/data/CompactDataInputOutputTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/ClassProbesAdapterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/ClassProbesAdapterTest.java
index 66374f2..bc9be31 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/ClassProbesAdapterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/ClassProbesAdapterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/FrameSnapshotTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/FrameSnapshotTest.java
index e343657..c78fe44 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/FrameSnapshotTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/FrameSnapshotTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java
deleted file mode 100644
index 950827c..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.internal.flow;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.InsnNode;
-
-/**
- * Unit tests for {@link Instruction}.
- */
-public class InstructionTest {
-
-	private Instruction instruction;
-
-	@Before
-	public void setup() {
-		instruction = new Instruction(new InsnNode(Opcodes.NOP), 123);
-	}
-
-	@Test
-	public void testInit() {
-		final InsnNode node = new InsnNode(Opcodes.NOP);
-		instruction = new Instruction(node, 123);
-		assertSame(node, instruction.getNode());
-		assertEquals(123, instruction.getLine());
-		assertEquals(0, instruction.getBranches());
-		assertEquals(0, instruction.getCoveredBranches());
-	}
-
-	@Test
-	public void testAddBranch() {
-		instruction.addBranch();
-		assertEquals(1, instruction.getBranches());
-		instruction.addBranch();
-		assertEquals(2, instruction.getBranches());
-		instruction.addBranch();
-		assertEquals(3, instruction.getBranches());
-		assertEquals(0, instruction.getCoveredBranches());
-	}
-
-	@Test
-	public void testSetPredecessor() {
-		final Instruction predecessor = new Instruction(
-				new InsnNode(Opcodes.NOP), 122);
-		instruction.setPredecessor(predecessor, 0);
-		assertEquals(1, predecessor.getBranches());
-	}
-
-	@Test
-	public void setCovered_should_mark_branch_in_predecessor() {
-		final Instruction i = new Instruction(new InsnNode(Opcodes.NOP), 122);
-		i.setCovered(2);
-		assertEquals(1, i.getCoveredBranches());
-		assertEquals("{2}", i.toString());
-
-		final Instruction s1 = new Instruction(new InsnNode(Opcodes.NOP), 123);
-		s1.setPredecessor(i, 1);
-		s1.setCovered(0);
-		assertEquals("{0}", s1.toString());
-		assertEquals(1, s1.getCoveredBranches());
-		assertEquals("{1, 2}", i.toString());
-		assertEquals(2, i.getCoveredBranches());
-
-		final Instruction s2 = new Instruction(new InsnNode(Opcodes.NOP), 124);
-		s2.setPredecessor(i, 0);
-		s2.setCovered(1);
-		assertEquals("{0}", s1.toString());
-		assertEquals(1, s2.getCoveredBranches());
-		assertEquals("{0, 1, 2}", i.toString());
-		assertEquals(3, i.getCoveredBranches());
-	}
-
-	@Test
-	public void should_use_BitSet_to_hold_information_about_branches_of_big_switches() {
-		for (int branch = 0; branch < 256; branch++) {
-			instruction.setCovered(branch);
-		}
-		assertEquals(256, instruction.getCoveredBranches());
-	}
-
-	@Test
-	public void merge_should_add_covered_branches_from_another_instruction() {
-		final Instruction i1 = new Instruction(new InsnNode(Opcodes.NOP), 123);
-		i1.setCovered(0);
-		final Instruction i2 = new Instruction(new InsnNode(Opcodes.NOP), 123);
-		i2.setCovered(1);
-		i1.merge(i2);
-		assertEquals("{0, 1}", i1.toString());
-		assertEquals(2, i1.getCoveredBranches());
-		assertEquals("{1}", i2.toString());
-	}
-
-	@Test
-	public void testSetCoveredOnLongSequence() {
-		final Instruction first = new Instruction(new InsnNode(Opcodes.NOP), 0);
-		Instruction next = first;
-		for (int i = 0; i < 0x10000; i++) {
-			final Instruction insn = new Instruction(new InsnNode(Opcodes.NOP),
-					i);
-			insn.setPredecessor(next, 0);
-			next = insn;
-		}
-
-		// The implementation must not cause an StackOverflowError even on very
-		// long sequences:
-		next.setCovered(0);
-		assertEquals(1, first.getCoveredBranches());
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelFlowAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelFlowAnalyzerTest.java
index 972ca8a..b7ac258 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelFlowAnalyzerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelFlowAnalyzerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java
index 8500795..2ca1339 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -17,11 +17,10 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import org.jacoco.core.internal.analysis.Instruction;
 import org.junit.Before;
 import org.junit.Test;
 import org.objectweb.asm.Label;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.InsnNode;
 
 /**
  * Unit tests for {@link LabelInfoTest}.
@@ -161,8 +160,7 @@
 
 	@Test
 	public void testSetInstruction() {
-		final Instruction instruction = new Instruction(
-				new InsnNode(Opcodes.NOP), 123);
+		final Instruction instruction = new Instruction(123);
 		LabelInfo.setInstruction(label, instruction);
 		assertSame(instruction, LabelInfo.getInstruction(label));
 	}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodProbesAdapterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodProbesAdapterTest.java
index 4b81ae3..ad32aea 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodProbesAdapterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodProbesAdapterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodSanitizerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodSanitizerTest.java
index 90bc881..d472405 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodSanitizerTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/MethodSanitizerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassInstrumenterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassInstrumenterTest.java
index 30bce8c..c5ef820 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassInstrumenterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ClassInstrumenterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategyTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategyTest.java
new file mode 100644
index 0000000..6397a59
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategyTest.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.instr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator;
+import org.junit.Before;
+import org.junit.Test;
+import org.objectweb.asm.ConstantDynamic;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TypeInsnNode;
+import org.objectweb.asm.tree.VarInsnNode;
+
+public class CondyProbeArrayStrategyTest {
+
+	private CondyProbeArrayStrategy strategy;
+
+	@Before
+	public void setup() {
+		strategy = new CondyProbeArrayStrategy("ClassName", true, 1L,
+				new OfflineInstrumentationAccessGenerator());
+	}
+
+	@Test
+	public void should_store_instance_using_condy_and_checkcast() {
+		final MethodNode m = new MethodNode();
+		final int maxStack = strategy.storeInstance(m, false, 1);
+
+		assertEquals(1, maxStack);
+
+		final ConstantDynamic constantDynamic = (ConstantDynamic) ((LdcInsnNode) m.instructions
+				.get(0)).cst;
+		assertEquals("$jacocoData", constantDynamic.getName());
+		assertEquals("Ljava/lang/Object;", constantDynamic.getDescriptor());
+
+		final Handle bootstrapMethod = constantDynamic.getBootstrapMethod();
+		assertEquals(Opcodes.H_INVOKESTATIC, bootstrapMethod.getTag());
+		assertEquals("ClassName", bootstrapMethod.getOwner());
+		assertEquals("$jacocoInit", bootstrapMethod.getName());
+		assertEquals(
+				"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)[Z",
+				bootstrapMethod.getDesc());
+		assertTrue(bootstrapMethod.isInterface());
+
+		final TypeInsnNode castInstruction = (TypeInsnNode) m.instructions
+				.get(1);
+		assertEquals(Opcodes.CHECKCAST, castInstruction.getOpcode());
+		assertEquals("[Z", castInstruction.desc);
+
+		final VarInsnNode storeInstruction = (VarInsnNode) m.instructions
+				.get(2);
+		assertEquals(Opcodes.ASTORE, storeInstruction.getOpcode());
+		assertEquals(1, storeInstruction.var);
+
+		assertEquals(3, m.instructions.size());
+	}
+
+	@Test
+	public void should_not_add_fields() {
+		final ClassNode c = new ClassNode();
+		strategy.addMembers(c, 1);
+
+		assertEquals(0, c.fields.size());
+	}
+
+	@Test
+	public void should_add_bootstrap_method() {
+		final ClassNode c = new ClassNode();
+		strategy.addMembers(c, 1);
+
+		assertEquals(1, c.methods.size());
+
+		final MethodNode m = c.methods.get(0);
+		assertEquals(Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PRIVATE
+				| Opcodes.ACC_STATIC, m.access);
+		assertEquals("$jacocoInit", m.name);
+		assertEquals(
+				"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)[Z",
+				m.desc);
+
+		assertEquals(4, m.maxStack);
+		assertEquals(3, m.maxLocals);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/DuplicateFrameEliminatorTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/DuplicateFrameEliminatorTest.java
index 2042397..4098189 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/DuplicateFrameEliminatorTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/DuplicateFrameEliminatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -101,7 +101,7 @@
 	@Test
 	public void testInvokeDynamicInsn() {
 		testInstructionBetweenFrames(new InvokeDynamicInsnNode("foo", "()V",
-				new Handle(0, null, null, null, false)));
+				new Handle(Opcodes.H_INVOKEVIRTUAL, null, null, null, false)));
 	}
 
 	@Test
@@ -149,7 +149,7 @@
 	}
 
 	private void frame(MethodVisitor mv) {
-		mv.visitFrame(Opcodes.NEW, 1, new Object[] { Opcodes.INTEGER }, 0,
+		mv.visitFrame(Opcodes.F_NEW, 1, new Object[] { Opcodes.INTEGER }, 0,
 				new Object[0]);
 	}
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java
index fb1cb3e..8345ac1 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,10 +11,19 @@
  *******************************************************************************/
 package org.jacoco.core.internal.instr;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.util.Printer;
 import org.objectweb.asm.util.Textifier;
 import org.objectweb.asm.util.TraceMethodVisitor;
@@ -27,6 +36,9 @@
 	private Printer printer;
 	private TraceMethodVisitor trace;
 
+	@Rule
+	public ExpectedException exception = ExpectedException.none();
+
 	@Before
 	public void setup() {
 		printer = new Textifier();
@@ -34,17 +46,112 @@
 	}
 
 	@Test
-	public void testAssertNotIntrumentedPositive() {
+	public void classReaderFor_should_read_java_13_class() {
+		final byte[] bytes = createJava13Class();
+
+		final ClassReader classReader = InstrSupport.classReaderFor(bytes);
+
+		classReader.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION) {
+			@Override
+			public void visit(final int version, final int access,
+					final String name, final String signature,
+					final String superName, final String[] interfaces) {
+				assertEquals(Opcodes.V12 + 1, version);
+			}
+		}, 0);
+
+		assertArrayEquals(createJava13Class(), bytes);
+	}
+
+	private static byte[] createJava13Class() {
+		final ClassWriter cw = new ClassWriter(0);
+		cw.visit(Opcodes.V12 + 1, 0, "Foo", null, "java/lang/Object", null);
+		cw.visitEnd();
+		return cw.toByteArray();
+	}
+
+	@Test
+	public void getMajorVersion_should_read_unsigned_two_bytes_at_offset_6() {
+		final byte[] bytes = new byte[] { //
+				(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE, // magic
+				(byte) 0xFF, (byte) 0xFF, // minor_version
+				(byte) 0x80, (byte) 0x12 // major_version
+		};
+
+		assertEquals(32786, InstrSupport.getMajorVersion(bytes));
+	}
+
+	@Test
+	public void setMajorVersion_should_write_unsigned_two_bytes_at_offset_6() {
+		final byte[] bytes = new byte[8];
+
+		InstrSupport.setMajorVersion(32786, bytes);
+
+		assertArrayEquals(
+				new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // magic
+						(byte) 0x00, (byte) 0x00, // minor_version
+						(byte) 0x80, (byte) 0x12 // major_version
+				}, bytes);
+	}
+
+	@Test
+	public void getMajorVersion_should_read_major_version_from_ClassReader_at_offset_relative_to_constant_pool() {
+		final byte[] bytes = new byte[] { //
+				(byte) 0xFF, // before class bytes
+				(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE, // magic
+				0x00, 0x03, // minor_version
+				(byte) 0x80, 0x12, // major_version
+				0x00, 0x02, // constant_pool_count
+				0x01, 0x00, 0x00 // constant_pool
+		};
+
+		assertEquals(32786,
+				InstrSupport.getMajorVersion(new ClassReader(bytes, 1, -1)));
+	}
+
+	@Test
+	public void needFrames_should_return_false_for_versions_less_than_1_6() {
+		assertFalse(InstrSupport.needsFrames(Opcodes.V1_1));
+		assertFalse(InstrSupport.needsFrames(Opcodes.V1_2));
+		assertFalse(InstrSupport.needsFrames(Opcodes.V1_3));
+		assertFalse(InstrSupport.needsFrames(Opcodes.V1_4));
+		assertFalse(InstrSupport.needsFrames(Opcodes.V1_5));
+	}
+
+	@Test
+	public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_1_6() {
+		assertTrue(InstrSupport.needsFrames(Opcodes.V1_6));
+		assertTrue(InstrSupport.needsFrames(Opcodes.V1_7));
+		assertTrue(InstrSupport.needsFrames(Opcodes.V1_8));
+		assertTrue(InstrSupport.needsFrames(Opcodes.V9));
+		assertTrue(InstrSupport.needsFrames(Opcodes.V10));
+		assertTrue(InstrSupport.needsFrames(Opcodes.V11));
+		assertTrue(InstrSupport.needsFrames(Opcodes.V12));
+		assertTrue(InstrSupport.needsFrames(Opcodes.V12 + 1));
+
+		assertTrue(InstrSupport.needsFrames(0x0100));
+	}
+
+	@Test
+	public void assertNotIntrumented_should_accept_non_jacoco_memebers() {
 		InstrSupport.assertNotInstrumented("run", "Foo");
 	}
 
-	@Test(expected = IllegalStateException.class)
-	public void testAssertNotIntrumentedField() {
+	@Test
+	public void assertNotIntrumented_should_throw_exception_when_jacoco_data_field_is_present() {
+		exception.expect(IllegalStateException.class);
+		exception.expectMessage(
+				"Cannot process instrumented class Foo. Please supply original non-instrumented classes.");
+
 		InstrSupport.assertNotInstrumented("$jacocoData", "Foo");
 	}
 
-	@Test(expected = IllegalStateException.class)
-	public void testAssertNotIntrumentedMethod() {
+	@Test
+	public void assertNotIntrumented_should_throw_exception_when_jacoco_init_method_is_present() {
+		exception.expect(IllegalStateException.class);
+		exception.expectMessage(
+				"Cannot process instrumented class Foo. Please supply original non-instrumented classes.");
+
 		InstrSupport.assertNotInstrumented("$jacocoInit", "Foo");
 	}
 
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/MethodInstrumenterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/MethodInstrumenterTest.java
index 6d7c4de..0d253fc 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/MethodInstrumenterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/MethodInstrumenterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/NoneProbeArrayStrategyTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/NoneProbeArrayStrategyTest.java
new file mode 100644
index 0000000..0c21f02
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/NoneProbeArrayStrategyTest.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.instr;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.objectweb.asm.tree.ClassNode;
+
+/**
+ * Unit tests for {@link NoneProbeArrayStrategy}.
+ */
+public class NoneProbeArrayStrategyTest {
+
+	private NoneProbeArrayStrategy strategy;
+
+	@Before
+	public void setup() {
+		strategy = new NoneProbeArrayStrategy();
+	}
+
+	@Test(expected = UnsupportedOperationException.class)
+	public void storeInstance_should_throw_UnsupportedOperationException() {
+		strategy.storeInstance(null, false, 0);
+	}
+
+	@Test
+	public void addMembers_should_not_add_members() {
+		final ClassNode c = new ClassNode();
+		strategy.addMembers(c, 0);
+
+		assertEquals(0, c.methods.size());
+		assertEquals(0, c.fields.size());
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactoryTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactoryTest.java
index 6d9ed5c..f1d1282 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactoryTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactoryTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -212,16 +212,65 @@
 	}
 
 	@Test
-	public void testModule() {
+	public void test_java9_module() {
+		final IProbeArrayStrategy strategy = createForModule(Opcodes.V9);
+		assertEquals(NoneProbeArrayStrategy.class, strategy.getClass());
+	}
+
+	@Test
+	public void test_java11_class() {
+		final IProbeArrayStrategy strategy = test(Opcodes.V11, 0, true, true,
+				true);
+
+		assertEquals(CondyProbeArrayStrategy.class, strategy.getClass());
+		assertNoDataField();
+		assertCondyBootstrapMethod();
+	}
+
+	@Test
+	public void test_java11_interface_with_clinit_and_methods() {
+		final IProbeArrayStrategy strategy = test(Opcodes.V11,
+				Opcodes.ACC_INTERFACE, true, true, true);
+
+		assertEquals(CondyProbeArrayStrategy.class, strategy.getClass());
+		assertNoDataField();
+		assertCondyBootstrapMethod();
+	}
+
+	@Test
+	public void test_java11_interface_with_clinit() {
+		final IProbeArrayStrategy strategy = test(Opcodes.V11,
+				Opcodes.ACC_INTERFACE, true, false, true);
+
+		assertEquals(LocalProbeArrayStrategy.class, strategy.getClass());
+		assertNoDataField();
+		assertNoInitMethod();
+	}
+
+	@Test
+	public void test_java11_interface_without_code() {
+		final IProbeArrayStrategy strategy = test(Opcodes.V11,
+				Opcodes.ACC_INTERFACE, false, false, true);
+
+		assertEquals(NoneProbeArrayStrategy.class, strategy.getClass());
+		assertNoDataField();
+		assertNoInitMethod();
+	}
+
+	@Test
+	public void test_java11_module() {
+		final IProbeArrayStrategy strategy = createForModule(Opcodes.V11);
+		assertEquals(NoneProbeArrayStrategy.class, strategy.getClass());
+	}
+
+	private IProbeArrayStrategy createForModule(int version) {
 		final ClassWriter writer = new ClassWriter(0);
-		writer.visit(Opcodes.V9, Opcodes.ACC_MODULE, "module-info", null, null,
+		writer.visit(version, Opcodes.ACC_MODULE, "module-info", null, null,
 				null);
 		writer.visitModule("module", 0, null).visitEnd();
 		writer.visitEnd();
-
-		final IProbeArrayStrategy strategy = ProbeArrayStrategyFactory
-				.createFor(new ClassReader(writer.toByteArray()), generator);
-		assertEquals(NoneProbeArrayStrategy.class, strategy.getClass());
+		return ProbeArrayStrategyFactory.createFor(0,
+				new ClassReader(writer.toByteArray()), generator);
 	}
 
 	private IProbeArrayStrategy test(int version, int access, boolean clinit,
@@ -254,7 +303,7 @@
 		writer.visitEnd();
 
 		final IProbeArrayStrategy strategy = ProbeArrayStrategyFactory
-				.createFor(new ClassReader(writer.toByteArray()), generator);
+				.createFor(0, new ClassReader(writer.toByteArray()), generator);
 
 		strategy.addMembers(cv, 123);
 		return strategy;
@@ -272,9 +321,9 @@
 			this.desc = desc;
 		}
 
-		void assertInitMethod(boolean frames) {
+		void assertInitMethod(String expectedDesc, boolean frames) {
 			assertEquals(InstrSupport.INITMETHOD_NAME, name);
-			assertEquals(InstrSupport.INITMETHOD_DESC, desc);
+			assertEquals(expectedDesc, desc);
 			assertEquals(InstrSupport.INITMETHOD_ACC, access);
 			assertEquals(Boolean.valueOf(frames), Boolean.valueOf(frames));
 		}
@@ -296,7 +345,7 @@
 		private final List<AddedMethod> methods = new ArrayList<AddedMethod>();
 
 		ClassVisitorMock() {
-			super(Opcodes.ASM6);
+			super(InstrSupport.ASM_API_VERSION);
 		}
 
 		@Override
@@ -313,7 +362,7 @@
 				String signature, String[] exceptions) {
 			final AddedMethod m = new AddedMethod(access, name, desc);
 			methods.add(m);
-			return new MethodVisitor(Opcodes.ASM6) {
+			return new MethodVisitor(InstrSupport.ASM_API_VERSION) {
 				@Override
 				public void visitFrame(int type, int nLocal, Object[] local,
 						int nStack, Object[] stack) {
@@ -373,12 +422,19 @@
 
 	void assertInitMethod(boolean frames) {
 		assertEquals(cv.methods.size(), 1);
-		cv.methods.get(0).assertInitMethod(frames);
+		cv.methods.get(0).assertInitMethod(InstrSupport.INITMETHOD_DESC,
+				frames);
+	}
+
+	void assertCondyBootstrapMethod() {
+		assertEquals(cv.methods.size(), 1);
+		cv.methods.get(0).assertInitMethod(CondyProbeArrayStrategy.B_DESC,
+				false);
 	}
 
 	void assertInitAndClinitMethods() {
 		assertEquals(2, cv.methods.size());
-		cv.methods.get(0).assertInitMethod(true);
+		cv.methods.get(0).assertInitMethod(InstrSupport.INITMETHOD_DESC, true);
 		cv.methods.get(1).assertClinit();
 	}
 
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeCounterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeCounterTest.java
index 928cdf1..8695625 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeCounterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeCounterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeInserterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeInserterTest.java
index 79224d3..c086f51 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeInserterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/ProbeInserterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/SignatureRemoverTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/SignatureRemoverTest.java
index f8254f0..1500b7c 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/SignatureRemoverTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/SignatureRemoverTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
index 155e3e8..b811b52 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/CommandLineSupportTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/CommandLineSupportTest.java
index b221a39..0c7e9b1 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/CommandLineSupportTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/CommandLineSupportTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/InjectedClassRuntimeTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/InjectedClassRuntimeTest.java
new file mode 100644
index 0000000..c3fc800
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/InjectedClassRuntimeTest.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.runtime;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.internal.AssumptionViolatedException;
+import org.junit.rules.TestName;
+
+/**
+ * Unit test for {@link InjectedClassRuntime}.
+ */
+public class InjectedClassRuntimeTest extends RuntimeTestBase {
+
+	@Rule
+	public TestName testName = new TestName();
+
+	@BeforeClass
+	public static void requires_at_least_Java_9() {
+		try {
+			Class.forName("java.lang.Module");
+		} catch (final ClassNotFoundException e) {
+			throw new AssumptionViolatedException(
+					"this test requires at least Java 9");
+		}
+	}
+
+	@Override
+	public IRuntime createRuntime() {
+		return new InjectedClassRuntime(InjectedClassRuntimeTest.class,
+				testName.getMethodName());
+	}
+
+	@Test
+	public void startup_should_not_create_duplicate_class_definition()
+			throws Exception {
+		try {
+			createRuntime().startup(null);
+			fail("exception expected");
+		} catch (final InvocationTargetException e) {
+			assertTrue(e.getCause() instanceof LinkageError);
+			assertTrue(e.getCause().getMessage()
+					.contains("duplicate class definition"));
+		}
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/LoggerRuntimeTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/LoggerRuntimeTest.java
index 20a6750..fcc66e5 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/LoggerRuntimeTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/LoggerRuntimeTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/ModifiedSystemClassRuntimeTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/ModifiedSystemClassRuntimeTest.java
index 8a96884..e380427 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/ModifiedSystemClassRuntimeTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/ModifiedSystemClassRuntimeTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGeneratorTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGeneratorTest.java
index cf41bf6..9a6707a 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGeneratorTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGeneratorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/RemoteControlReaderWriterTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/RemoteControlReaderWriterTest.java
index e098798..69203cb 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/RemoteControlReaderWriterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/RemoteControlReaderWriterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeDataTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeDataTest.java
index dd3e352..272dc92 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeDataTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeDataTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeTestBase.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeTestBase.java
index d912e87..564b372 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeTestBase.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/RuntimeTestBase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/SystemPropertiesRuntimeTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/SystemPropertiesRuntimeTest.java
index 6ad9631..c058972 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/SystemPropertiesRuntimeTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/SystemPropertiesRuntimeTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/TestStorage.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/TestStorage.java
index e133c5c..5698594 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/TestStorage.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/TestStorage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -56,4 +56,4 @@
 		this.info = info;
 	}
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/URLStreamHandlerRuntimeTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/URLStreamHandlerRuntimeTest.java
index 2184f46..51428a0 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/URLStreamHandlerRuntimeTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/URLStreamHandlerRuntimeTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/WildcardMatcherTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/WildcardMatcherTest.java
index 21d50f8..8f1313b 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/runtime/WildcardMatcherTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/WildcardMatcherTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -19,30 +19,31 @@
 public class WildcardMatcherTest {
 
 	@Test
-	public void testEmpty() {
+	public void empty_expression_should_match_any_string() {
 		assertTrue(new WildcardMatcher("").matches(""));
 		assertFalse(new WildcardMatcher("").matches("abc"));
 	}
 
 	@Test
-	public void testExact() {
+	public void expressions_without_wildcards_should_match_exactly() {
 		assertTrue(new WildcardMatcher("abc/def.txt").matches("abc/def.txt"));
+		assertFalse(new WildcardMatcher("abc/def.txt").matches("/abc/def.txt"));
 	}
 
 	@Test
-	public void testCaseSensitive() {
+	public void should_match_case_sensitive() {
 		assertFalse(new WildcardMatcher("abcdef").matches("abcDef"));
 		assertFalse(new WildcardMatcher("ABCDEF").matches("AbCDEF"));
 	}
 
 	@Test
-	public void testQuote() {
+	public void should_not_use_regex_characters() {
 		assertFalse(new WildcardMatcher("rst.xyz").matches("rstAxyz"));
 		assertTrue(new WildcardMatcher("(x)+").matches("(x)+"));
 	}
 
 	@Test
-	public void testWildcards() {
+	public void asterix_should_match_any_number_of_any_character() {
 		assertTrue(new WildcardMatcher("*").matches(""));
 		assertTrue(new WildcardMatcher("*").matches("java/lang/Object"));
 		assertTrue(new WildcardMatcher("*Test").matches("jacoco/MatcherTest"));
@@ -50,20 +51,24 @@
 		assertTrue(new WildcardMatcher("Matcher*").matches("MatcherTest"));
 		assertTrue(new WildcardMatcher("a*b*a").matches("a-b-b-a"));
 		assertFalse(new WildcardMatcher("a*b*a").matches("alaska"));
-		assertTrue(new WildcardMatcher("Hello?orld").matches("HelloWorld"));
-		assertFalse(new WildcardMatcher("Hello?orld").matches("HelloWWWorld"));
-		assertTrue(new WildcardMatcher("?aco*").matches("jacoco"));
 	}
 
 	@Test
-	public void testMultiExpression() {
-		assertTrue(new WildcardMatcher("Hello:World").matches("World"));
+	public void questionmark_should_match_any_single_character() {
+		assertTrue(new WildcardMatcher("Hello?orld").matches("HelloWorld"));
+		assertFalse(new WildcardMatcher("Hello?orld").matches("Helloorld"));
+		assertFalse(new WildcardMatcher("Hello?orld").matches("HelloWWWorld"));
+	}
+
+	@Test
+	public void should_match_any_expression_when_multiple_expressions_are_given() {
 		assertTrue(new WildcardMatcher("Hello:World").matches("World"));
 		assertTrue(new WildcardMatcher("*Test:*Foo").matches("UnitTest"));
+		assertFalse(new WildcardMatcher("foo:bar").matches("foo:bar"));
 	}
 
 	@Test
-	public void testDollar() {
+	public void should_match_dollar_sign() {
 		assertTrue(new WildcardMatcher("*$*").matches("java/util/Map$Entry"));
 		assertTrue(new WildcardMatcher("*$$$*")
 				.matches("org/example/Enity$$$generated123"));
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoader.java b/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoader.java
index a870267..f3eb7e9 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoader.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/InstrumentingLoader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java b/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java
index 43a4fb3..3418c63 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/TargetLoader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/ConstructorTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/ConstructorTest.java
deleted file mode 100644
index 1dffc68..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/ConstructorTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.filter.targets.Constructor;
-import org.jacoco.core.test.validation.ValidationTestBase;
-import org.junit.Test;
-
-/**
- * Test of filtering of a bytecode that is generated for a private empty
- * constructors that do not have no arguments.
- */
-public class ConstructorTest extends ValidationTestBase {
-
-	public ConstructorTest() {
-		super(Constructor.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-		// not filtered because not private:
-		assertLine("packageLocal", ICounter.FULLY_COVERED);
-
-		// not filtered because has argument:
-		assertLine("arg", ICounter.FULLY_COVERED);
-
-		// not filtered because not empty - prepares arguments for super
-		// constructor:
-		assertLine("super", ICounter.FULLY_COVERED);
-
-		// not filtered because contains initialization of a field to hold
-		// reference to an instance of outer class that is passed as an
-		// argument:
-		assertLine("inner", ICounter.FULLY_COVERED);
-
-		// not filtered because not empty - contains initialization of
-		// a field:
-		assertLine("innerStatic", ICounter.FULLY_COVERED);
-
-		// not filtered because default constructor for not private inner
-		// classes is not private:
-		assertLine("publicDefault", ICounter.FULLY_COVERED);
-		assertLine("packageLocalDefault", ICounter.FULLY_COVERED);
-
-		assertLine("privateDefault", ICounter.EMPTY);
-
-		assertLine("privateNonEmptyNoArg", ICounter.FULLY_COVERED);
-
-		assertLine("privateEmptyNoArg", ICounter.EMPTY);
-		assertLine("return", ICounter.EMPTY);
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/FinallyTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/FinallyTest.java
deleted file mode 100644
index 758bec3..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/FinallyTest.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.TargetLoader;
-import org.jacoco.core.test.filter.targets.Finally;
-import org.jacoco.core.test.validation.Source;
-import org.jacoco.core.test.validation.ValidationTestBase;
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
-import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.LineNumberNode;
-import org.objectweb.asm.tree.MethodNode;
-
-/**
- * Test of filtering of duplicated bytecode that is generated for finally block.
- */
-public class FinallyTest extends ValidationTestBase {
-
-	private static boolean isJDK8 = !Pattern.compile("1\\.[567]\\.0_(\\d++)")
-			.matcher(System.getProperty("java.version")).matches();
-
-	public FinallyTest() {
-		super(Finally.class);
-	}
-
-	/**
-	 * {@link Finally#example(boolean)}
-	 */
-	@Test
-	public void example() {
-		if (isJDKCompiler) {
-			assertLine("example.0", ICounter.EMPTY);
-		} else {
-			assertLine("example.0", ICounter.FULLY_COVERED);
-		}
-		assertLine("example.1", ICounter.FULLY_COVERED, 0, 2);
-		assertLine("example.2", ICounter.FULLY_COVERED);
-		assertLine("example.3", ICounter.EMPTY);
-		assertLine("example.4", ICounter.EMPTY);
-	}
-
-	/**
-	 * GOTO instructions at the end of duplicates of finally block might have
-	 * line number of a last instruction of finally block and hence lead to
-	 * unexpected coverage results, like for example in case of ECJ for
-	 * {@link Finally#catchNotExecuted()}, {@link Finally#emptyCatch()}. So we
-	 * decided to ignore them, even if they can correspond to a real break
-	 * statement.
-	 * <p>
-	 * See also <a href=
-	 * "https://bugs.openjdk.java.net/browse/JDK-8180141">JDK-8180141</a> and
-	 * <a href=
-	 * "https://bugs.openjdk.java.net/browse/JDK-7008643">JDK-7008643</a>.
-	 * <p>
-	 * {@link Finally#breakStatement()}
-	 */
-	@Test
-	public void breakStatement() {
-		assertLine("breakStatement", ICounter.EMPTY);
-
-		assertLine("breakStatement.1", ICounter.FULLY_COVERED);
-		assertLine("breakStatement.2", ICounter.EMPTY);
-	}
-
-	/**
-	 * {@link Finally#catchNotExecuted()}
-	 */
-	@Test
-	public void catchNotExecuted() {
-		assertLine("catchNotExecuted.catch", ICounter.NOT_COVERED);
-		assertLine("catchNotExecuted.0", ICounter.EMPTY);
-		assertLine("catchNotExecuted.1", ICounter.FULLY_COVERED);
-		assertLine("catchNotExecuted.2", ICounter.EMPTY);
-	}
-
-	/**
-	 * {@link Finally#emptyCatch()}
-	 */
-	@Test
-	public void emptyCatch() {
-		assertLine("emptyCatch.0", ICounter.EMPTY);
-		assertLine("emptyCatch.1", ICounter.FULLY_COVERED);
-		assertLine("emptyCatch.2", ICounter.EMPTY);
-	}
-
-	/**
-	 * {@link Finally#twoRegions()}
-	 */
-	@Test
-	public void twoRegions() {
-		assertLine("twoRegions.0", ICounter.EMPTY);
-		if (isJDKCompiler && !isJDK8) {
-			// https://bugs.openjdk.java.net/browse/JDK-7008643
-			assertLine("twoRegions.1", ICounter.PARTLY_COVERED);
-			assertLine("twoRegions.return.1", ICounter.EMPTY);
-			assertLine("twoRegions.return.2", ICounter.EMPTY);
-		} else {
-			assertLine("twoRegions.1", ICounter.FULLY_COVERED);
-			assertLine("twoRegions.return.1", ICounter.FULLY_COVERED);
-			assertLine("twoRegions.return.2", ICounter.NOT_COVERED);
-		}
-		assertLine("twoRegions.2", ICounter.EMPTY);
-
-		assertLine("twoRegions.if", ICounter.FULLY_COVERED);
-		assertLine("twoRegions.region.1", ICounter.FULLY_COVERED);
-		assertLine("twoRegions.region.2", ICounter.NOT_COVERED);
-	}
-
-	/**
-	 * {@link Finally#nested()}
-	 */
-	@Test
-	public void nested() {
-		if (isJDKCompiler) {
-			assertLine("nested.0", ICounter.EMPTY);
-		} else {
-			assertLine("nested.0", ICounter.FULLY_COVERED);
-		}
-		assertLine("nested.1", ICounter.EMPTY);
-		assertLine("nested.2", ICounter.FULLY_COVERED);
-		if (isJDKCompiler) {
-			assertLine("nested.3", ICounter.EMPTY);
-		} else {
-			assertLine("nested.3", ICounter.FULLY_COVERED);
-		}
-		assertLine("nested.4", ICounter.FULLY_COVERED);
-	}
-
-	/**
-	 * {@link Finally#emptyTry()}
-	 */
-	@Test
-	public void emptyTry() {
-		assertLine("emptyTry.0", ICounter.EMPTY);
-		if (!isJDKCompiler || isJDK8) {
-			assertLine("emptyTry.1", ICounter.FULLY_COVERED);
-			assertLine("emptyTry.2", ICounter.EMPTY);
-		} else {
-			// compiler bug fixed in javac >= 1.8:
-			assertLine("emptyTry.1", ICounter.PARTLY_COVERED);
-			assertLine("emptyTry.2", ICounter.FULLY_COVERED);
-		}
-	}
-
-	/**
-	 * {@link Finally#alwaysCompletesAbruptly()}
-	 */
-	@Test
-	public void alwaysCompletesAbruptly() {
-		if (isJDKCompiler) {
-			// uncovered case:
-			assertLine("alwaysCompletesAbruptly.0", ICounter.EMPTY);
-			assertLine("alwaysCompletesAbruptly.1", ICounter.PARTLY_COVERED);
-		} else {
-			assertLine("alwaysCompletesAbruptly.0", ICounter.PARTLY_COVERED);
-			assertLine("alwaysCompletesAbruptly.1", ICounter.FULLY_COVERED);
-		}
-		assertLine("alwaysCompletesAbruptly.2", ICounter.EMPTY);
-	}
-
-	/**
-	 * This test studies placement of GOTO instructions.
-	 */
-	@Test
-	public void gotos() throws IOException {
-		final Source source = Source.getSourceFor("src", Finally.class);
-
-		final ClassNode classNode = new ClassNode();
-		new ClassReader(TargetLoader.getClassDataAsBytes(Finally.class))
-				.accept(classNode, 0);
-		final Set<String> tags = new HashSet<String>();
-		for (final MethodNode m : classNode.methods) {
-			if ("main".equals(m.name)) {
-				// skip it
-				continue;
-			}
-			int lineNumber = -1;
-			for (AbstractInsnNode i = m.instructions
-					.getFirst(); i != null; i = i.getNext()) {
-				if (AbstractInsnNode.LINE == i.getType()) {
-					lineNumber = ((LineNumberNode) i).line;
-				}
-				if (Opcodes.GOTO == i.getOpcode()) {
-					final String line = source.getLine(lineNumber);
-					if (line.indexOf('$') < 0) {
-						throw new AssertionError(
-								"No tag at line " + lineNumber);
-					}
-					final String tag = line.substring(
-							line.indexOf('$') + "$line-".length(),
-							line.lastIndexOf('$'));
-					tags.add(tag);
-				}
-			}
-		}
-
-		final Set<String> expected = new HashSet<String>();
-
-		if (isJDKCompiler) {
-			expected.add("example.2");
-		} else {
-			expected.add("example.0");
-		}
-
-		expected.add("breakStatement.for");
-		if (isJDKCompiler) {
-			expected.add("breakStatement.1");
-			expected.add("breakStatement.2");
-		} else {
-			expected.add("breakStatement");
-		}
-
-		if (isJDKCompiler) {
-			expected.add("emptyCatch.2");
-		} else {
-			expected.add("emptyCatch");
-			expected.add("emptyCatch.1");
-		}
-
-		if (isJDKCompiler) {
-			expected.add("catchNotExecuted.2");
-		} else {
-			expected.add("catchNotExecuted");
-			expected.add("catchNotExecuted.1");
-		}
-
-		if (isJDKCompiler) {
-			expected.add("nested.5");
-			expected.add("nested.6");
-		} else {
-			expected.add("nested.0");
-			expected.add("nested.3");
-		}
-
-		if (isJDKCompiler && !isJDK8) {
-			expected.add("emptyTry.2");
-		}
-
-		if (!isJDKCompiler) {
-			expected.add("alwaysCompletesAbruptly.0");
-		}
-
-		assertEquals(expected, tags);
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/SynchronizedTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/SynchronizedTest.java
deleted file mode 100644
index 2d0fa97..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/SynchronizedTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.filter.targets.Synchronized;
-import org.jacoco.core.test.validation.ValidationTestBase;
-import org.junit.Test;
-
-/**
- * Test of filtering of a bytecode that is generated for a synchronized
- * statement.
- */
-public class SynchronizedTest extends ValidationTestBase {
-
-	public SynchronizedTest() {
-		super(Synchronized.class);
-	}
-
-	/**
-	 * {@link Synchronized#normal()}
-	 */
-	@Test
-	public void normal() {
-		assertLine("before", ICounter.FULLY_COVERED);
-		// when compiled with ECJ next line covered partly without filter:
-		assertLine("monitorEnter", ICounter.FULLY_COVERED);
-		assertLine("body", ICounter.FULLY_COVERED);
-		if (isJDKCompiler) {
-			// without filter next line covered partly:
-			assertLine("monitorExit", ICounter.FULLY_COVERED);
-		} else {
-			assertLine("monitorExit", ICounter.EMPTY);
-		}
-		assertLine("after", ICounter.FULLY_COVERED);
-	}
-
-	/**
-	 * {@link Synchronized#explicitException()}
-	 */
-	@Test
-	public void explicitException() {
-		assertLine("explicitException.monitorEnter", ICounter.FULLY_COVERED);
-		assertLine("explicitException.exception", ICounter.FULLY_COVERED);
-		// when compiled with javac next line covered fully without filter:
-		assertLine("explicitException.monitorExit", ICounter.EMPTY);
-	}
-
-	/**
-	 * {@link Synchronized#implicitException()}
-	 */
-	@Test
-	public void implicitException() {
-		assertLine("implicitException.monitorEnter", isJDKCompiler
-				? ICounter.FULLY_COVERED : ICounter.PARTLY_COVERED);
-		assertLine("implicitException.exception", ICounter.NOT_COVERED);
-		if (isJDKCompiler) {
-			// without filter next line covered partly:
-			assertLine("implicitException.monitorExit", ICounter.NOT_COVERED);
-		} else {
-			assertLine("implicitException.monitorExit", ICounter.EMPTY);
-		}
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Constructor.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Constructor.java
deleted file mode 100644
index 8a3e394..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Constructor.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.nop;
-
-/**
- * This test target is a constructors.
- */
-public class Constructor {
-
-	Constructor() { // $line-packageLocal$
-	}
-
-	private Constructor(Object arg) { // $line-arg$
-	}
-
-	private static class Super extends Constructor {
-		private Super() {
-			super(null); // $line-super$
-		}
-	}
-
-	private class Inner {
-		private Inner() { // $line-inner$
-		}
-	}
-
-	private static class InnerStatic {
-		@SuppressWarnings("unused")
-		private final Object field = this;
-
-		private InnerStatic() { // $line-innerStatic$
-		}
-	}
-
-	public static class PublicDefault { // $line-publicDefault$
-	}
-
-	static class PackageLocalDefault { // $line-packageLocalDefault$
-	}
-
-	private static class PrivateDefault { // $line-privateDefault$
-	}
-
-	private static class PrivateNonEmptyNoArg {
-		private PrivateNonEmptyNoArg() {
-			nop(); // $line-privateNonEmptyNoArg$
-		}
-	}
-
-	private static class PrivateEmptyNoArg {
-		private PrivateEmptyNoArg() { // $line-privateEmptyNoArg$
-		} // $line-return$
-	}
-
-	public static void main(String[] args) {
-		new Super();
-		new Constructor().new Inner();
-		new InnerStatic();
-		new PublicDefault();
-		new PackageLocalDefault();
-		new PrivateDefault();
-		new PrivateNonEmptyNoArg();
-		new PrivateEmptyNoArg();
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Finally.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Finally.java
deleted file mode 100644
index 6471a80..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Finally.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.filter.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.ex;
-import static org.jacoco.core.test.validation.targets.Stubs.f;
-import static org.jacoco.core.test.validation.targets.Stubs.nop;
-import static org.jacoco.core.test.validation.targets.Stubs.t;
-
-public class Finally {
-
-	/**
-	 * <pre>
-	 *   InputStream in = null;
-	 *   try {
-	 *     in = ...;
-	 *     ...
-	 *   } finally {
-	 *     if (in != null) {
-	 *       in.close();
-	 *     }
-	 *   }
-	 * </pre>
-	 */
-	private static void example(boolean t) {
-		Object in = null;
-		try {
-			in = open(t);
-		} finally { // $line-example.0$
-			if (in != null) { // $line-example.1$
-				nop(); // $line-example.2$
-			} // $line-example.3$
-		} // $line-example.4$
-	}
-
-	private static Object open(boolean t) {
-		ex(t);
-		return new Object();
-	}
-
-	private static void breakStatement() {
-		for (int i = 0; i < 1; i++) { // $line-breakStatement.for$
-			try {
-				if (f()) {
-					break; // $line-breakStatement$
-				}
-			} finally {
-				nop("finally"); // $line-breakStatement.1$
-			} // $line-breakStatement.2$
-		}
-	}
-
-	private static void catchNotExecuted() {
-		try {
-			nop("try");
-		} catch (Exception e) { // $line-catchNotExecuted$
-			nop("catch"); // $line-catchNotExecuted.catch$
-		} finally { // $line-catchNotExecuted.0$
-			nop("finally"); // $line-catchNotExecuted.1$
-		} // $line-catchNotExecuted.2$
-	}
-
-	private static void emptyCatch() {
-		try {
-			nop("try");
-		} catch (Exception e) { // $line-emptyCatch$
-			// empty
-		} finally { // $line-emptyCatch.0$
-			nop("finally"); // $line-emptyCatch.1$
-		} // $line-emptyCatch.2$
-	}
-
-	private static void twoRegions() {
-		try {
-			// jump to another region associated with same handler:
-			if (t()) { // $line-twoRegions.if$
-				nop(); // $line-twoRegions.region.1$
-				return; // $line-twoRegions.return.1$
-			} else {
-				nop(); // $line-twoRegions.region.2$
-				return; // $line-twoRegions.return.2$
-			}
-		} finally { // $line-twoRegions.0$
-			nop(); // $line-twoRegions.1$
-		} // $line-twoRegions.2$
-	}
-
-	private static void nested() {
-		try {
-			nop();
-		} finally { // $line-nested.0$
-			try { // $line-nested.1$
-				nop(); // $line-nested.2$
-			} finally { // $line-nested.3$
-				nop(); // $line-nested.4$
-			} // $line-nested.5$
-		} // $line-nested.6$
-	}
-
-	private static void emptyTry() {
-		try {
-			// empty
-		} finally { // $line-emptyTry.0$
-			nop(); // $line-emptyTry.1$
-		} // $line-emptyTry.2$
-	}
-
-	@SuppressWarnings("finally")
-	private static void alwaysCompletesAbruptly() {
-		try {
-			nop();
-		} finally { // $line-alwaysCompletesAbruptly.0$
-			return; // $line-alwaysCompletesAbruptly.1$
-		} // $line-alwaysCompletesAbruptly.2$
-	}
-
-	public static void main(String[] args) {
-		example(false);
-		try {
-			example(true);
-		} catch (Exception ignore) {
-		}
-
-		breakStatement();
-
-		catchNotExecuted();
-
-		emptyCatch();
-
-		twoRegions();
-
-		nested();
-
-		emptyTry();
-
-		alwaysCompletesAbruptly();
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/AnalysisTimeScenario.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/AnalysisTimeScenario.java
index 41da19c..dc155e1 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/AnalysisTimeScenario.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/AnalysisTimeScenario.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java
index d199b0c..20bd02a 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/ExecuteInstrumentedCodeScenario.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -18,7 +18,6 @@
 import org.jacoco.core.runtime.LoggerRuntime;
 import org.jacoco.core.runtime.RuntimeData;
 import org.jacoco.core.test.TargetLoader;
-import org.objectweb.asm.ClassReader;
 
 /**
  * This scenario runs a given scenario twice and reports the execution time:
@@ -37,11 +36,11 @@
 	@Override
 	@SuppressWarnings("unchecked")
 	protected Callable<Void> getInstrumentedCallable() throws Exception {
-		ClassReader reader = new ClassReader(TargetLoader.getClassData(target));
 		IRuntime runtime = new LoggerRuntime();
 		runtime.startup(new RuntimeData());
 		final Instrumenter instr = new Instrumenter(runtime);
-		final byte[] instrumentedBuffer = instr.instrument(reader);
+		final byte[] original = TargetLoader.getClassDataAsBytes(target);
+		final byte[] instrumentedBuffer = instr.instrument(original, "");
 		final TargetLoader loader = new TargetLoader();
 
 		return (Callable<Void>) loader.add(target, instrumentedBuffer)
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfOutput.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfOutput.java
index 2298111..440f10e 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfOutput.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -17,7 +17,7 @@
 public interface IPerfOutput {
 
 	/** Indicator for no reference time given */
-	public static final long NO_REFERENCE = Long.MIN_VALUE;
+	long NO_REFERENCE = Long.MIN_VALUE;
 
 	/**
 	 * Reports the result of a time measurement with a optional reference time
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfScenario.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfScenario.java
index 471b839..ca5590f 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfScenario.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/IPerfScenario.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,6 @@
 	 * 
 	 * @param output
 	 */
-	public void run(IPerfOutput output) throws Exception;
+	void run(IPerfOutput output) throws Exception;
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationSizeSzenario.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationSizeSzenario.java
index f11a39d..27e0545 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationSizeSzenario.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationSizeSzenario.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -15,7 +15,6 @@
 import org.jacoco.core.runtime.IRuntime;
 import org.jacoco.core.runtime.LoggerRuntime;
 import org.jacoco.core.test.TargetLoader;
-import org.objectweb.asm.ClassReader;
 
 /**
  * Scenario to measure the overhead in terms of additional byte code size
@@ -31,11 +30,11 @@
 
 	public void run(IPerfOutput output) throws Exception {
 		final IRuntime runtime = new LoggerRuntime();
-		ClassReader reader = new ClassReader(TargetLoader.getClassData(target));
 		final Instrumenter instr = new Instrumenter(runtime);
-		instr.instrument(reader);
-		output.writeByteResult("instrumented class",
-				instr.instrument(reader).length, reader.b.length);
+		final byte[] original = TargetLoader.getClassDataAsBytes(target);
+		final byte[] instrumented = instr.instrument(original, "");
+		output.writeByteResult("instrumented class", instrumented.length,
+				original.length);
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationTimeScenario.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationTimeScenario.java
index bf85f0c..3ecbbed 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationTimeScenario.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/InstrumentationTimeScenario.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerfOutputWriter.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerfOutputWriter.java
index bba15e4..c6b5c4e 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerfOutputWriter.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerfOutputWriter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerformanceSuite.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerformanceSuite.java
index b0aa47b..32d99b0 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerformanceSuite.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/PerformanceSuite.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/TimedScenario.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/TimedScenario.java
index 414a1ce..fd71c51 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/TimedScenario.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/TimedScenario.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target01.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target01.java
index 4c9f2c2..907e59e 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target01.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target01.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target02.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target02.java
index 0b79b52..ca29a13 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target02.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target02.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target03.java b/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target03.java
index 9847022..9ce6bff 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target03.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/perf/targets/Target03.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/BooleanExpressionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/BooleanExpressionsTest.java
deleted file mode 100644
index 64dee47..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/BooleanExpressionsTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target02;
-import org.junit.Test;
-
-/**
- * Tests of basic Java boolean expressions.
- */
-public class BooleanExpressionsTest extends ValidationTestBase {
-
-	public BooleanExpressionsTest() {
-		super(Target02.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		// 1. Boolean comparison result (one case)
-		assertLine("booleancmp1", ICounter.PARTLY_COVERED, 1, 1);
-
-		// 2. Boolean comparison result (both cases)
-		assertLine("booleancmp2", ICounter.FULLY_COVERED, 0, 2);
-
-		// 3. And
-		assertLine("andFF", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("andFT", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("andTF", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("andTT", ICounter.FULLY_COVERED, 1, 1);
-
-		// 4. Conditional And
-		assertLine("conditionalandFF", ICounter.PARTLY_COVERED, 3, 1);
-		assertLine("conditionalandFT", ICounter.PARTLY_COVERED, 3, 1);
-		assertLine("conditionalandTF", ICounter.FULLY_COVERED, 2, 2);
-		assertLine("conditionalandTT", ICounter.FULLY_COVERED, 2, 2);
-
-		// 5. Or
-		assertLine("orFF", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("orFT", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("orTF", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("orTT", ICounter.FULLY_COVERED, 1, 1);
-
-		// 6. Conditional Or
-		assertLine("conditionalorFF", ICounter.FULLY_COVERED, 2, 2);
-		assertLine("conditionalorFT", ICounter.FULLY_COVERED, 2, 2);
-		assertLine("conditionalorTF", ICounter.PARTLY_COVERED, 3, 1);
-		assertLine("conditionalorTT", ICounter.PARTLY_COVERED, 3, 1);
-
-		// 7. Exclusive Or
-		assertLine("xorFF", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("xorFT", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("xorTF", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("xorTT", ICounter.FULLY_COVERED, 1, 1);
-
-		// 8. Conditional Operator
-		assertLine("condT", ICounter.PARTLY_COVERED, 1, 1);
-		assertLine("condF", ICounter.PARTLY_COVERED, 1, 1);
-
-		// 9. Not (one case)
-		assertLine("notT", ICounter.PARTLY_COVERED, 1, 1);
-		assertLine("notF", ICounter.PARTLY_COVERED, 1, 1);
-
-		// 10. Not (both cases)
-		assertLine("notTF", ICounter.FULLY_COVERED, 0, 2);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ClassFileVersionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ClassFileVersionsTest.java
deleted file mode 100644
index d73fc64..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ClassFileVersionsTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import static org.junit.Assert.assertEquals;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ACC_SUPER;
-import static org.objectweb.asm.Opcodes.ALOAD;
-import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
-import static org.objectweb.asm.Opcodes.RETURN;
-import static org.objectweb.asm.Opcodes.V1_1;
-import static org.objectweb.asm.Opcodes.V1_2;
-import static org.objectweb.asm.Opcodes.V1_3;
-import static org.objectweb.asm.Opcodes.V1_4;
-import static org.objectweb.asm.Opcodes.V1_5;
-import static org.objectweb.asm.Opcodes.V1_6;
-import static org.objectweb.asm.Opcodes.V1_7;
-import static org.objectweb.asm.Opcodes.V1_8;
-import static org.objectweb.asm.Opcodes.V9;
-
-import java.io.IOException;
-
-import org.jacoco.core.instr.Instrumenter;
-import org.jacoco.core.internal.instr.InstrSupport;
-import org.jacoco.core.runtime.IRuntime;
-import org.jacoco.core.runtime.SystemPropertiesRuntime;
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.MethodVisitor;
-
-/**
- * Test class inserted stackmap frames for different class file versions.
- */
-public class ClassFileVersionsTest {
-
-	@Test
-	public void test_1_1() throws IOException {
-		testVersion(V1_1, false);
-	}
-
-	@Test
-	public void test_1_2() throws IOException {
-		testVersion(V1_2, false);
-	}
-
-	@Test
-	public void test_1_3() throws IOException {
-		testVersion(V1_3, false);
-	}
-
-	@Test
-	public void test_1_4() throws IOException {
-		testVersion(V1_4, false);
-	}
-
-	@Test
-	public void test_1_5() throws IOException {
-		testVersion(V1_5, false);
-	}
-
-	@Test
-	public void test_1_6() throws IOException {
-		testVersion(V1_6, true);
-	}
-
-	@Test
-	public void test_1_7() throws IOException {
-		testVersion(V1_7, true);
-	}
-
-	@Test
-	public void test_1_8() throws IOException {
-		testVersion(V1_8, true);
-	}
-
-	@Test
-	public void test_1_9() throws IOException {
-		testVersion(V9, true);
-	}
-
-	private void testVersion(int version, boolean frames) throws IOException {
-		final byte[] original = createClass(version);
-
-		IRuntime runtime = new SystemPropertiesRuntime();
-		Instrumenter instrumenter = new Instrumenter(runtime);
-		byte[] instrumented = instrumenter.instrument(original, "TestTarget");
-
-		assertFrames(instrumented, frames);
-	}
-
-	private void assertFrames(byte[] source, boolean expected) {
-		final boolean[] hasFrames = new boolean[] { false };
-		new ClassReader(source)
-				.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION) {
-
-					@Override
-					public MethodVisitor visitMethod(int access, String name,
-							String desc, String signature, String[] exceptions) {
-						return new MethodVisitor(InstrSupport.ASM_API_VERSION) {
-
-							@Override
-							public void visitFrame(int type, int nLocal,
-									Object[] local, int nStack, Object[] stack) {
-								hasFrames[0] = true;
-							}
-
-						};
-					}
-
-				}, 0);
-		assertEquals(Boolean.valueOf(expected), Boolean.valueOf(hasFrames[0]));
-	}
-
-	private byte[] createClass(int version) {
-
-		ClassWriter cw = new ClassWriter(0);
-		MethodVisitor mv;
-
-		cw.visit(version, ACC_PUBLIC + ACC_SUPER, "org/jacoco/test/Sample",
-				null, "java/lang/Object", null);
-
-		mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
-		mv.visitCode();
-		mv.visitVarInsn(ALOAD, 0);
-		mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V",
-				false);
-		mv.visitInsn(RETURN);
-		mv.visitMaxs(1, 1);
-		mv.visitEnd();
-
-		cw.visitEnd();
-
-		return cw.toByteArray();
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ClassInitializerTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ClassInitializerTest.java
deleted file mode 100644
index f87e705..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ClassInitializerTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target05;
-import org.junit.Test;
-
-/**
- * Tests of static initializer in classes.
- */
-public class ClassInitializerTest extends ValidationTestBase {
-
-	public ClassInitializerTest() {
-		super(Target05.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("const1", ICounter.EMPTY);
-		assertLine("const2", ICounter.EMPTY);
-
-		assertLine("const3", ICounter.FULLY_COVERED);
-		assertLine("const4", ICounter.FULLY_COVERED);
-
-		assertLine("field1", ICounter.FULLY_COVERED);
-		assertLine("field2", ICounter.FULLY_COVERED);
-		assertLine("field3", ICounter.FULLY_COVERED);
-		assertLine("field4", ICounter.FULLY_COVERED);
-
-		assertLine("staticblock", ICounter.FULLY_COVERED);
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/Compiler.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/Compiler.java
index a273e84..622fca5 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/Compiler.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/Compiler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ControlStructuresTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ControlStructuresTest.java
deleted file mode 100644
index 37db4c1..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ControlStructuresTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target01;
-import org.junit.Test;
-
-/**
- * Tests of basic Java control structures.
- */
-public class ControlStructuresTest extends ValidationTestBase {
-
-	public ControlStructuresTest() {
-		super(Target01.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		// 1. Direct unconditional execution
-		assertLine("unconditional", ICounter.FULLY_COVERED);
-
-		// 2. Missed if block
-		assertLine("iffalse", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("missedif", ICounter.NOT_COVERED);
-		assertLine("executedelse", ICounter.FULLY_COVERED);
-
-		// 3. Executed if block
-		assertLine("iftrue", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("executedif", ICounter.FULLY_COVERED);
-		assertLine("missedelse", ICounter.NOT_COVERED);
-
-		// 4. Missed while block
-		assertLine("whilefalse", ICounter.FULLY_COVERED, 1, 1);
-		assertLine("missedwhile", ICounter.NOT_COVERED);
-
-		// 5. Always true while block
-		assertLine("whiletrue", ICounter.FULLY_COVERED, 1, 1);
-
-		// 6. Executed while block
-		assertLine("whiletruefalse", ICounter.FULLY_COVERED, 0, 2);
-		assertLine("executedwhile", ICounter.FULLY_COVERED);
-
-		// 7. Executed do while block
-		assertLine("executeddowhile", ICounter.FULLY_COVERED);
-		assertLine("executeddowhilefalse", ICounter.FULLY_COVERED, 1, 1);
-
-		// 8. Missed for block
-		assertLine("missedforincrementer", ICounter.PARTLY_COVERED, 1, 1);
-		assertLine("missedfor", ICounter.NOT_COVERED);
-
-		// 9. Executed for block
-		assertLine("executedforincrementer", ICounter.FULLY_COVERED, 0, 2);
-		assertLine("executedfor", ICounter.FULLY_COVERED);
-
-		// 10. Missed for each block
-		assertLine("missedforeachincrementer", ICounter.PARTLY_COVERED, 1, 1);
-		assertLine("missedforeach", ICounter.NOT_COVERED);
-
-		// 11. Executed for each block
-		assertLine("executedforeachincrementer", ICounter.FULLY_COVERED, 0, 2);
-		assertLine("executedforeach", ICounter.FULLY_COVERED);
-
-		// 12. Table switch with hit
-		assertLine("tswitch1", ICounter.FULLY_COVERED, 3, 1);
-		assertLine("tswitch1case1", ICounter.NOT_COVERED);
-		assertLine("tswitch1case2", ICounter.FULLY_COVERED);
-		assertLine("tswitch1case3", ICounter.NOT_COVERED);
-		assertLine("tswitch1default", ICounter.NOT_COVERED);
-
-		// 13. Continued table switch with hit
-		assertLine("tswitch2", ICounter.FULLY_COVERED, 3, 1);
-		assertLine("tswitch2case1", ICounter.NOT_COVERED);
-		assertLine("tswitch2case2", ICounter.FULLY_COVERED);
-		assertLine("tswitch2case3", ICounter.FULLY_COVERED);
-		assertLine("tswitch2default", ICounter.FULLY_COVERED);
-
-		// 14. Table switch without hit
-		assertLine("tswitch2", ICounter.FULLY_COVERED, 3, 1);
-		assertLine("tswitch3case1", ICounter.NOT_COVERED);
-		assertLine("tswitch3case2", ICounter.NOT_COVERED);
-		assertLine("tswitch3case3", ICounter.NOT_COVERED);
-		assertLine("tswitch3default", ICounter.FULLY_COVERED);
-
-		// 15. Lookup switch with hit
-		assertLine("lswitch1", ICounter.FULLY_COVERED, 3, 1);
-		assertLine("lswitch1case1", ICounter.NOT_COVERED);
-		assertLine("lswitch1case2", ICounter.FULLY_COVERED);
-		assertLine("lswitch1case3", ICounter.NOT_COVERED);
-		assertLine("lswitch1default", ICounter.NOT_COVERED);
-
-		// 16. Continued lookup switch with hit
-		assertLine("lswitch2", ICounter.FULLY_COVERED, 3, 1);
-		assertLine("lswitch2case1", ICounter.NOT_COVERED);
-		assertLine("lswitch2case2", ICounter.FULLY_COVERED);
-		assertLine("lswitch2case3", ICounter.FULLY_COVERED);
-		assertLine("lswitch2default", ICounter.FULLY_COVERED);
-
-		// 17. Lookup switch without hit
-		assertLine("lswitch3", ICounter.FULLY_COVERED, 3, 1);
-		assertLine("lswitch3case1", ICounter.NOT_COVERED);
-		assertLine("lswitch3case2", ICounter.NOT_COVERED);
-		assertLine("lswitch3case3", ICounter.NOT_COVERED);
-		assertLine("lswitch3default", ICounter.FULLY_COVERED);
-
-		// 18. Break statement
-		assertLine("executedbreak", ICounter.FULLY_COVERED);
-		assertLine("missedafterbreak", ICounter.NOT_COVERED);
-
-		// 19. Continue statement
-		assertLine("executedcontinue", ICounter.FULLY_COVERED);
-		assertLine("missedaftercontinue", ICounter.NOT_COVERED);
-
-		// 20. Conditional return statement
-		assertLine("conditionalreturn", ICounter.FULLY_COVERED);
-		assertLine("afterconditionalreturn", ICounter.NOT_COVERED);
-
-		// 21. Implicit return
-		assertLine("implicitreturn", ICounter.FULLY_COVERED);
-
-		// 22. Explicit return
-		assertLine("explicitreturn", ICounter.FULLY_COVERED);
-		assertLine("afterexplicitreturn", ICounter.EMPTY);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java
deleted file mode 100644
index fbd9e54..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Evgeny Mandrikov - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.EnumImplicitMethods;
-import org.junit.Test;
-
-/**
- * Test of an implicit methods and static initializer in enums.
- */
-public class EnumImplicitMethodsTest extends ValidationTestBase {
-
-    public EnumImplicitMethodsTest() {
-        super(EnumImplicitMethods.class);
-    }
-
-    @Test
-    public void testCoverageResult() {
-        assertMethodCount(5);
-
-        assertLine("classdef", ICounter.FULLY_COVERED);
-        assertLine("customValueOfMethod", ICounter.NOT_COVERED);
-        assertLine("customValuesMethod", ICounter.NOT_COVERED);
-
-        assertLine("const", ICounter.PARTLY_COVERED);
-        assertLine("staticblock", ICounter.FULLY_COVERED);
-        assertLine("super", ICounter.FULLY_COVERED);
-        assertLine("constructor", ICounter.FULLY_COVERED);
-    }
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ExceptionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ExceptionsTest.java
deleted file mode 100644
index c68bd37..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ExceptionsTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target03;
-import org.junit.Test;
-
-/**
- * Tests of exception based control flow.
- */
-public class ExceptionsTest extends ValidationTestBase {
-
-	public ExceptionsTest() {
-		super(Target03.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		// 0. Implicit NullPointerException
-		// Currently no coverage at all, as we don't see when a block aborts
-		// somewhere in the middle.
-		assertLine("implicitNullPointerException.before", ICounter.NOT_COVERED);
-		assertLine("implicitNullPointerException.exception",
-				ICounter.NOT_COVERED);
-		assertLine("implicitNullPointerException.after", ICounter.NOT_COVERED);
-
-		// 1. Implicit Exception
-		assertLine("implicitException.before", ICounter.FULLY_COVERED);
-		assertLine("implicitException.exception", ICounter.NOT_COVERED);
-		assertLine("implicitException.after", ICounter.NOT_COVERED);
-
-		// 2. Explicit Exception
-		// Full coverage, as we recognize throw statements as block boundaries.
-		assertLine("explicitException.before", ICounter.FULLY_COVERED);
-		assertLine("explicitException.throw", ICounter.FULLY_COVERED);
-
-		// 3. Try/Catch Block Without Exception Thrown
-		assertLine("noExceptionTryCatch.beforeBlock", ICounter.FULLY_COVERED);
-		assertLine("noExceptionTryCatch.tryBlock", ICounter.FULLY_COVERED);
-		assertLine("noExceptionTryCatch.catch",
-				isJDKCompiler ? ICounter.NOT_COVERED : ICounter.PARTLY_COVERED);
-		assertLine("noExceptionTryCatch.catchBlock", ICounter.NOT_COVERED);
-		assertLine("noExceptionTryCatch.catchBlockEnd",
-				isJDKCompiler ? ICounter.FULLY_COVERED : ICounter.EMPTY);
-		assertLine("noExceptionTryCatch.afterBlock", ICounter.FULLY_COVERED);
-
-		// 4. Try/Catch Block With Exception Thrown Implicitly
-		assertLine("implicitExceptionTryCatch.beforeBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("implicitExceptionTryCatch.before", ICounter.FULLY_COVERED);
-		assertLine("implicitExceptionTryCatch.exception", ICounter.NOT_COVERED);
-		assertLine("implicitExceptionTryCatch.after", ICounter.NOT_COVERED);
-		assertLine("implicitExceptionTryCatch.catch", isJDKCompiler
-				? ICounter.FULLY_COVERED : ICounter.PARTLY_COVERED);
-		assertLine("implicitExceptionTryCatch.catchBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("implicitExceptionTryCatch.catchBlockEnd",
-				isJDKCompiler ? ICounter.NOT_COVERED : ICounter.EMPTY);
-		assertLine("implicitExceptionTryCatch.afterBlock",
-				ICounter.FULLY_COVERED);
-
-		// 5. Try/Catch Block With Exception Thrown Implicitly After Condition
-		// As the try/catch block is entered at one branch of the condition
-		// should be marked as executed
-		assertLine("implicitExceptionTryCatchAfterCondition.condition",
-				ICounter.FULLY_COVERED, 1, 1);
-		assertLine("implicitExceptionTryCatchAfterCondition.exception",
-				ICounter.NOT_COVERED);
-		assertLine("implicitExceptionTryCatchAfterCondition.catchBlock",
-				ICounter.FULLY_COVERED);
-
-		// 6. Try/Catch Block With Exception Thrown Explicitly
-		assertLine("explicitExceptionTryCatch.beforeBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionTryCatch.before", ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionTryCatch.throw", ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionTryCatch.catch", ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionTryCatch.catchBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionTryCatch.catchBlockEnd", ICounter.EMPTY);
-		assertLine("explicitExceptionTryCatch.afterBlock",
-				ICounter.FULLY_COVERED);
-
-		// 7. Finally Block Without Exception Thrown
-		assertLine("noExceptionFinally.beforeBlock", ICounter.FULLY_COVERED);
-		assertLine("noExceptionFinally.tryBlock", ICounter.FULLY_COVERED);
-		assertLine("noExceptionFinally.finally",
-				isJDKCompiler ? ICounter.EMPTY : ICounter.FULLY_COVERED);
-		assertLine("noExceptionFinally.finallyBlock", ICounter.FULLY_COVERED);
-		assertLine("noExceptionFinally.finallyBlockEnd", ICounter.EMPTY);
-		assertLine("noExceptionFinally.afterBlock", ICounter.FULLY_COVERED);
-
-		// 8. Finally Block With Implicit Exception
-		assertLine("implicitExceptionFinally.beforeBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("implicitExceptionFinally.before", ICounter.FULLY_COVERED);
-		assertLine("implicitExceptionFinally.exception", ICounter.NOT_COVERED);
-		assertLine("implicitExceptionFinally.after", ICounter.NOT_COVERED);
-		assertLine("implicitExceptionFinally.finally",
-				isJDKCompiler ? ICounter.EMPTY : ICounter.NOT_COVERED);
-		assertLine("implicitExceptionFinally.finallyBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("implicitExceptionFinally.finallyBlockEnd", ICounter.EMPTY);
-		assertLine("implicitExceptionFinally.afterBlock", ICounter.NOT_COVERED);
-
-		// 9. Finally Block With Exception Thrown Explicitly
-		assertLine("explicitExceptionFinally.beforeBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionFinally.before", ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionFinally.throw", ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionFinally.finally",
-				isJDKCompiler ? ICounter.EMPTY : ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionFinally.finallyBlock",
-				ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionFinally.finallyBlockEnd",
-				isJDKCompiler ? ICounter.EMPTY : ICounter.FULLY_COVERED);
-		assertLine("explicitExceptionFinally.afterBlock", ICounter.EMPTY);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/FieldInitializationInTwoConstructorsTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/FieldInitializationInTwoConstructorsTest.java
deleted file mode 100644
index 6896bf6..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/FieldInitializationInTwoConstructorsTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target09;
-import org.junit.Test;
-
-/**
- * Test of field initialization in two constructors.
- */
-public class FieldInitializationInTwoConstructorsTest extends
-		ValidationTestBase {
-
-	public FieldInitializationInTwoConstructorsTest() {
-		super(Target09.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("field1", ICounter.PARTLY_COVERED);
-		assertLine("field2", ICounter.PARTLY_COVERED);
-		assertLine("constr1", ICounter.FULLY_COVERED);
-		assertLine("constr2", ICounter.NOT_COVERED);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ImplicitDefaultConstructorTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ImplicitDefaultConstructorTest.java
deleted file mode 100644
index 09872e8..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ImplicitDefaultConstructorTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target06;
-import org.junit.Test;
-
-/**
- * Test of a implicit default constructor.
- *
- * @see PrivateEmptyDefaultConstructorTest
- */
-public class ImplicitDefaultConstructorTest extends ValidationTestBase {
-
-	public ImplicitDefaultConstructorTest() {
-		super(Target06.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("classdef", ICounter.FULLY_COVERED);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ImplicitFieldInitializationTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ImplicitFieldInitializationTest.java
deleted file mode 100644
index 769593d..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ImplicitFieldInitializationTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target08;
-import org.junit.Test;
-
-/**
- * Test of a implicit field initialization.
- */
-public class ImplicitFieldInitializationTest extends ValidationTestBase {
-
-	public ImplicitFieldInitializationTest() {
-		super(Target08.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("classdef", ICounter.FULLY_COVERED);
-		assertLine("field1", ICounter.EMPTY);
-		assertLine("field2", ICounter.FULLY_COVERED);
-		assertLine("field3", ICounter.EMPTY);
-		assertLine("field4", ICounter.FULLY_COVERED);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersion.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersion.java
new file mode 100644
index 0000000..1fb5590
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersion.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+/**
+ * Parsed value of "java.version" system property.
+ */
+public final class JavaVersion {
+
+	private final int feature;
+
+	private final int update;
+
+	/**
+	 * @param javaVersionPropertyValue
+	 *            value of "java.version" property
+	 * @see System#getProperties() description of properties
+	 */
+	JavaVersion(final String javaVersionPropertyValue) {
+		final String[] s = javaVersionPropertyValue.split("[._-]");
+		if ("1".equals(s[0])) {
+			this.feature = Integer.parseInt(s[1]);
+			this.update = s.length > 3 ? Integer.parseInt(s[3]) : 0;
+		} else {
+			this.feature = Integer.parseInt(s[0]);
+			this.update = s.length > 2 ? Integer.parseInt(s[2]) : 0;
+		}
+	}
+
+	/**
+	 * @return value of feature-release counter, for example: 8 for version
+	 *         "1.8.0_152" and 9 for version "9.0.1"
+	 */
+	int feature() {
+		return feature;
+	}
+
+	/**
+	 * @return value of update-release counter, for example: 152 for version
+	 *         "1.8.0_152" and 1 for version "9.0.1"
+	 */
+	int update() {
+		return update;
+	}
+
+	/**
+	 * @param version
+	 *            version to compare with
+	 * @return <code>true</code> if this version is less than given
+	 */
+	public boolean isBefore(final String version) {
+		final JavaVersion other = new JavaVersion(version);
+		return this.feature < other.feature || (this.feature == other.feature
+				&& this.update < other.update);
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersionTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersionTest.java
new file mode 100644
index 0000000..389a242
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/JavaVersionTest.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class JavaVersionTest {
+
+	@Test
+	public void should_parse_values_of_java_version_property() {
+		JavaVersion v;
+
+		v = new JavaVersion("1.8.0_162");
+		assertEquals(8, v.feature());
+		assertEquals(162, v.update());
+
+		v = new JavaVersion("1.8.0_172-ea");
+		assertEquals(8, v.feature());
+		assertEquals(172, v.update());
+
+		v = new JavaVersion("9");
+		assertEquals(9, v.feature());
+		assertEquals(0, v.update());
+
+		v = new JavaVersion("9.0.1");
+		assertEquals(9, v.feature());
+		assertEquals(1, v.update());
+
+		v = new JavaVersion("10-ea");
+		assertEquals(10, v.feature());
+		assertEquals(0, v.update());
+	}
+
+	@Test
+	public void should_compare_with_given_version() {
+		assertTrue(new JavaVersion("1.7.0_80").isBefore("1.8.0_92"));
+
+		assertTrue(new JavaVersion("1.8.0_31").isBefore("1.8.0_92"));
+
+		assertFalse(new JavaVersion("1.8.0_92").isBefore("1.8.0_92"));
+
+		assertFalse(new JavaVersion("1.8.0_162").isBefore("1.8.0_92"));
+		assertFalse(new JavaVersion("1.8.0_162").isBefore("1.8"));
+
+		assertFalse(new JavaVersion("9.0.1").isBefore("1.8.0_92"));
+	}
+
+}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/PrivateEmptyDefaultConstructorTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/PrivateEmptyDefaultConstructorTest.java
deleted file mode 100644
index 1d144b7..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/PrivateEmptyDefaultConstructorTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target07;
-import org.junit.Test;
-
-/**
- * Test of a private empty default constructor.
- *
- * @see ImplicitDefaultConstructorTest
- */
-public class PrivateEmptyDefaultConstructorTest extends ValidationTestBase {
-
-	public PrivateEmptyDefaultConstructorTest() {
-		super(Target07.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("classdef", ICounter.EMPTY);
-		assertLine("super", ICounter.EMPTY);
-		assertLine("constructor", ICounter.EMPTY);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ProbesBeforeSuperConstructorTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ProbesBeforeSuperConstructorTest.java
deleted file mode 100644
index 88b1ae5..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ProbesBeforeSuperConstructorTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.test.validation.targets.Target10;
-import org.junit.Test;
-
-/**
- * Test of probes before the super constructor call.
- */
-public class ProbesBeforeSuperConstructorTest extends ValidationTestBase {
-
-	public ProbesBeforeSuperConstructorTest() {
-		super(Target10.class);
-	}
-
-	@Test
-	public void testCoverageResult() {
-
-		assertLine("super", ICounter.PARTLY_COVERED, 3, 1);
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/Source.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/Source.java
index c04841e..fe9dde5 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/Source.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/Source.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,108 +12,157 @@
 package org.jacoco.core.test.validation;
 
 import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
+import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.Reader;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.analysis.ICoverageNode;
+import org.jacoco.core.analysis.ILine;
+import org.jacoco.core.analysis.IPackageCoverage;
+import org.jacoco.core.analysis.ISourceFileCoverage;
+
 /**
- * Reads a single source file and allows access to it through special probe
- * comments in the following format <code>//$line-<i>tag</i>$.
+ * Reads a single source file and allows access to its line coverage.
  */
 public class Source {
 
+	private static final String SRC_LOCATION = "src/";
+
+	private static final String SRC_ENCODING = "UTF-8";
+
+	private static final Pattern COMMENT_PATTERN = Pattern
+			.compile("(?<!https?:)//(.*)");
+
 	/**
-	 * Reads the source for the given type from the given source folder relative
-	 * to the working directory.
-	 * 
-	 * @param srcFolder
-	 *            source folder
-	 * @param type
-	 *            type to load the source file for
+	 * Represents a single line in a source file.
 	 */
-	public static Source getSourceFor(final String srcFolder,
-			final Class<?> type) throws IOException {
-		File folder = new File(srcFolder);
-		File file = new File(folder, type.getName().replace('.', '/') + ".java");
-		return new Source(new FileReader(file));
+	public class Line {
+
+		private final int nr;
+		private final String text;
+		private final ILine coverage;
+
+		private Line(int nr, String text, ILine coverage) {
+			this.nr = nr;
+			this.text = text;
+			this.coverage = coverage;
+		}
+
+		public int getNr() {
+			return nr;
+		}
+
+		public String getText() {
+			return text;
+		}
+
+		public ILine getCoverage() {
+			return coverage;
+		}
+
+		/**
+		 * @return the text of a single line comment if present or
+		 *         <code>null</code>
+		 */
+		public String getComment() {
+			final Matcher matcher = COMMENT_PATTERN.matcher(text);
+			return matcher.find() ? matcher.group(1) : null;
+		}
+
+		@Override
+		public String toString() {
+			return Source.this.coverage.getName() + ":" + nr;
+		}
+
 	}
 
-	private static final Pattern TAG_PATTERN = Pattern
-			.compile("\\$line-(.*)\\$");
+	private final List<Line> lines;
 
-	private final List<String> lines = new ArrayList<String>();
-
-	private final Map<String, Integer> tags = new HashMap<String, Integer>();
+	private final ISourceFileCoverage coverage;
 
 	/**
 	 * Reads a source file from the given reader.
 	 * 
 	 * @param reader
+	 *            the reader to read from, will be closed
+	 * @param coverage
+	 *            corresponding coverage data
 	 * @throws IOException
+	 *             if an I/O error occurs
 	 */
-	public Source(final Reader reader) throws IOException {
+	public Source(final Reader reader, ISourceFileCoverage coverage)
+			throws IOException {
+		this.lines = new ArrayList<Line>();
+		this.coverage = coverage;
 		final BufferedReader buffer = new BufferedReader(reader);
+		int nr = 1;
 		for (String l = buffer.readLine(); l != null; l = buffer.readLine()) {
-			addLine(l);
+			lines.add(new Line(nr, l, coverage.getLine(nr)));
+			nr++;
 		}
 		buffer.close();
 	}
 
-	private void addLine(final String l) {
-		lines.add(l);
-		final Matcher m = TAG_PATTERN.matcher(l);
-		if (m.find()) {
-			final String tag = m.group(1);
-			if (tags.put(tag, Integer.valueOf(lines.size())) != null) {
-				throw new IllegalArgumentException("Duplicate tag: " + tag);
-			}
-		}
-	}
-
 	/**
-	 * Returns all lines of the source file as a list.
-	 * 
 	 * @return all lines of the source file
 	 */
-	public List<String> getLines() {
+	public List<Line> getLines() {
 		return Collections.unmodifiableList(lines);
 	}
 
 	/**
-	 * Returns the line with the given number
-	 * 
-	 * @param nr
-	 *            line number (first line is 1)
-	 * @return line content
+	 * @return the corresponding coverage node
 	 */
-	public String getLine(int nr) {
-		return lines.get(nr - 1);
+	public ISourceFileCoverage getCoverage() {
+		return coverage;
 	}
 
 	/**
-	 * Returns the line number with the given tag
+	 * Loads the source file which holds the given target class.
 	 * 
-	 * @param tag
-	 *            tag from a <code>//$line-<i>tag</i>$ marker
-	 * @return line number (first line is 1)
-	 * @throws NoSuchElementException
-	 *             if there is no such tag
+	 * @param target
+	 *            the target class we want the source for
+	 * @param bundle
+	 *            the bundle containing the analyzed class and its source file
+	 * @return a {@link Source} instance
 	 */
-	public int getLineNumber(String tag) throws NoSuchElementException {
-		final Integer nr = tags.get(tag);
-		if (nr == null) {
-			throw new NoSuchElementException("Unknown tag: " + tag);
+	public static Source load(Class<?> target, IBundleCoverage bundle)
+			throws IOException {
+		final IPackageCoverage pkgCov = findByName(bundle.getPackages(),
+				vm(target.getPackage().getName()));
+		final IClassCoverage clsCov = findByName(pkgCov.getClasses(),
+				vm(target.getName()));
+		final ISourceFileCoverage srcCov = findByName(pkgCov.getSourceFiles(),
+				clsCov.getSourceFileName());
+		return new Source(open(SRC_LOCATION + pkgCov.getName() + "/"
+				+ clsCov.getSourceFileName()), srcCov);
+	}
+
+	private static <T extends ICoverageNode> T findByName(Collection<T> nodes,
+			String name) {
+		for (T node : nodes) {
+			if (name.equals(node.getName())) {
+				return node;
+			}
 		}
-		return nr.intValue();
+		throw new AssertionError("Node not found: " + name);
+	}
+
+	private static String vm(String javaname) {
+		return javaname.replace('.', '/');
+	}
+
+	private static Reader open(String file) throws IOException {
+		return new InputStreamReader(new FileInputStream(file), SRC_ENCODING);
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/SourceTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/SourceTest.java
index 6432c39..45d5434 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/SourceTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/SourceTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,13 +12,15 @@
 package org.jacoco.core.test.validation;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
 
 import java.io.IOException;
 import java.io.StringReader;
-import java.util.Arrays;
-import java.util.NoSuchElementException;
+import java.util.List;
 
+import org.jacoco.core.internal.analysis.CounterImpl;
+import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
+import org.jacoco.core.test.validation.Source.Line;
 import org.junit.Test;
 
 /**
@@ -27,61 +29,108 @@
 public class SourceTest {
 
 	@Test
-	public void testGetLines1() throws IOException {
-		String src = "\na\nbb\n";
-		final Source s = new Source(new StringReader(src));
-		assertEquals(Arrays.asList("", "a", "bb"), s.getLines());
+	public void should_parse_lines() throws IOException {
+		String src = "aaa\nbbb\n;";
+
+		final Source s = new Source(new StringReader(src),
+				new SourceFileCoverageImpl("Foo", "foo"));
+
+		List<Line> lines = s.getLines();
+		assertEquals(3, lines.size());
+		assertEquals("aaa", lines.get(0).getText());
+		assertEquals("bbb", lines.get(1).getText());
+		assertEquals(";", lines.get(2).getText());
 	}
 
 	@Test
-	public void testGetLines2() throws IOException {
-		String src = "aa\nbb\n;";
-		final Source s = new Source(new StringReader(src));
-		assertEquals(Arrays.asList("aa", "bb", ";"), s.getLines());
+	public void should_parse_empty_lines() throws IOException {
+		String src = "\naaa\n\nbbb\n";
+
+		final Source s = new Source(new StringReader(src),
+				new SourceFileCoverageImpl("Foo", "foo"));
+
+		List<Line> lines = s.getLines();
+		assertEquals(4, lines.size());
+		assertEquals("", lines.get(0).getText());
+		assertEquals("aaa", lines.get(1).getText());
+		assertEquals("", lines.get(2).getText());
+		assertEquals("bbb", lines.get(3).getText());
 	}
 
 	@Test
-	public void testGetLines3() throws IOException {
-		String src = "xx\r\nyy";
-		final Source s = new Source(new StringReader(src));
-		assertEquals(Arrays.asList("xx", "yy"), s.getLines());
+	public void should_parse_crnl_separator() throws IOException {
+		String src = "aaa\r\nbbb";
+
+		final Source s = new Source(new StringReader(src),
+				new SourceFileCoverageImpl("Foo", "foo"));
+
+		List<Line> lines = s.getLines();
+		assertEquals(2, lines.size());
+		assertEquals("aaa", lines.get(0).getText());
+		assertEquals("bbb", lines.get(1).getText());
 	}
 
 	@Test
-	public void testGetLine() throws IOException {
-		String src = "Hello\n\nWorld!";
-		final Source s = new Source(new StringReader(src));
-		assertEquals("Hello", s.getLine(1));
-		assertEquals("", s.getLine(2));
-		assertEquals("World!", s.getLine(3));
+	public void should_calculate_line_numbers() throws IOException {
+		String src = "a\nb\nc";
+
+		final Source s = new Source(new StringReader(src),
+				new SourceFileCoverageImpl("Foo", "foo"));
+
+		List<Line> lines = s.getLines();
+		assertEquals(3, lines.size());
+		assertEquals(1, lines.get(0).getNr());
+		assertEquals(2, lines.get(1).getNr());
+		assertEquals(3, lines.get(2).getNr());
 	}
 
 	@Test
-	public void testGetLineNumber() throws IOException {
-		String src = "a\nb$line-tag$\nc\nd\ne$line-tagx$\nf";
-		final Source s = new Source(new StringReader(src));
-		assertEquals(2, s.getLineNumber("tag"), 0.0);
-	}
+	public void line_should_implement_toString() throws IOException {
+		String src = "a\nb";
 
-	@Test(expected = NoSuchElementException.class)
-	public void testGetLineNumberNegative() throws IOException {
-		String src = "a\nb$line-tag$\nc\nd\ne\nf";
-		final Source s = new Source(new StringReader(src));
-		s.getLineNumber("ag");
-	}
+		final Source s = new Source(new StringReader(src),
+				new SourceFileCoverageImpl("Foo", "foo"));
 
-	@Test(expected = IllegalArgumentException.class)
-	public void testDuplicateTag() throws IOException {
-		String src = "a\nb$line-tag$\nc\nd\ne$line-tag$\nf";
-		new Source(new StringReader(src));
+		List<Line> lines = s.getLines();
+		assertEquals(2, lines.size());
+		assertEquals("Foo:1", lines.get(0).toString());
+		assertEquals("Foo:2", lines.get(1).toString());
 	}
 
 	@Test
-	public void testGetSourceFor() throws IOException {
-		final Source s = Source.getSourceFor("src", SourceTest.class);
-		// Here we are. $line-testGetSourceFor$
-		final String l = s.getLine(s.getLineNumber("testGetSourceFor"));
-		assertTrue(l, l.contains("Here we are."));
+	public void line_should_provide_corresponding_coverage()
+			throws IOException {
+		String src = "a\nb\nc";
+		SourceFileCoverageImpl sc = new SourceFileCoverageImpl("Foo", "foo");
+		sc.increment(CounterImpl.getInstance(1, 0), CounterImpl.COUNTER_0_0, 1);
+		sc.increment(CounterImpl.getInstance(2, 0), CounterImpl.COUNTER_0_0, 2);
+		sc.increment(CounterImpl.getInstance(3, 0), CounterImpl.COUNTER_0_0, 3);
+
+		final Source s = new Source(new StringReader(src), sc);
+
+		List<Line> lines = s.getLines();
+		assertEquals(3, lines.size());
+		assertEquals(1, lines.get(0).getCoverage().getInstructionCounter()
+				.getMissedCount());
+		assertEquals(2, lines.get(1).getCoverage().getInstructionCounter()
+				.getMissedCount());
+		assertEquals(3, lines.get(2).getCoverage().getInstructionCounter()
+				.getMissedCount());
+	}
+
+	@Test
+	public void line_should_return_comment() throws IOException {
+		String src = "aaa\nbbb // test()\n}//nospaces()\n/* http://jacoco.org/ */";
+
+		final Source s = new Source(new StringReader(src),
+				new SourceFileCoverageImpl("Foo", "foo"));
+
+		List<Line> lines = s.getLines();
+		assertEquals(4, lines.size());
+		assertNull(lines.get(0).getComment());
+		assertEquals(" test()", lines.get(1).getComment());
+		assertEquals("nospaces()", lines.get(2).getComment());
+		assertNull(lines.get(3).getComment());
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementExecutor.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementExecutor.java
new file mode 100644
index 0000000..52bd95e
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementExecutor.java
@@ -0,0 +1,65 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ *******************************************************************************/

+package org.jacoco.core.test.validation;

+

+import java.lang.reflect.InvocationTargetException;

+

+/**

+ * Executes statements against a given Java object instance.

+ */

+class StatementExecutor implements StatementParser.IStatementVisitor {

+

+	private final Object target;

+	private final Object[] prefixArgs;

+

+	StatementExecutor(Object target, Object... prefixArgs) {

+		this.target = target;

+		this.prefixArgs = prefixArgs;

+	}

+

+	public void visitInvocation(String ctx, String name, Object... args) {

+		args = concat(prefixArgs, args);

+		try {

+			target.getClass().getMethod(name, getTypes(args)).invoke(target,

+					args);

+		} catch (InvocationTargetException e) {

+			Throwable te = e.getTargetException();

+			if (te instanceof AssertionError) {

+				throw (AssertionError) te;

+			}

+			throw new RuntimeException("Invocation error (" + ctx + ")", te);

+		} catch (Exception e) {

+			throw new RuntimeException("Invocation error (" + ctx + ")", e);

+		}

+	}

+

+	private static Object[] concat(Object[] a, Object[] b) {

+		final Object[] result = new Object[a.length + b.length];

+		System.arraycopy(a, 0, result, 0, a.length);

+		System.arraycopy(b, 0, result, a.length, b.length);

+		return result;

+	}

+

+	private static Class<?>[] getTypes(Object[] instances) {

+		final Class<?>[] classes = new Class[instances.length];

+		for (int i = 0; i < instances.length; i++) {

+			Class<? extends Object> c = instances[i].getClass();

+			if (c == Integer.class) {

+				// We always use primitive int parameters:

+				c = Integer.TYPE;

+			}

+			classes[i] = c;

+		}

+		return classes;

+	}

+

+}

diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementExecutorTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementExecutorTest.java
new file mode 100644
index 0000000..b71c605
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementExecutorTest.java
@@ -0,0 +1,106 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ *******************************************************************************/

+package org.jacoco.core.test.validation;

+

+import static org.junit.Assert.assertEquals;

+

+import java.io.IOException;

+import java.util.Arrays;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import org.junit.Before;

+import org.junit.Rule;

+import org.junit.Test;

+import org.junit.rules.ExpectedException;

+

+/**

+ * Unit tests for {@link StatementExecutor}.

+ */

+public class StatementExecutorTest {

+

+	@Rule

+	public ExpectedException exception = ExpectedException.none();

+

+	private Map<String, List<?>> invocations;

+

+	@Before

+	public void setup() {

+		invocations = new HashMap<String, List<?>>();

+	}

+

+	@Test

+	public void should_prefix_arguments() {

+		StatementExecutor executor = new StatementExecutor(this,

+				"Hello", "world");

+

+		executor.visitInvocation("ctx", "target1", "!");

+

+		assertEquals(Arrays.asList("Hello", "world", "!"),

+				invocations.get("target1"));

+	}

+

+	@Test

+	public void should_call_method_with_int_argument() {

+		StatementExecutor executor = new StatementExecutor(this);

+

+		executor.visitInvocation("ctx", "target2", Integer.valueOf(42));

+

+		assertEquals(Arrays.asList(Integer.valueOf(42)),

+				invocations.get("target2"));

+	}

+

+	@Test

+	public void should_preserve_AssertionError() {

+		exception.expect(AssertionError.class);

+		exception.expectMessage("Original AssertionError.");

+		StatementExecutor executor = new StatementExecutor(this);

+

+		executor.visitInvocation("ctx", "target3");

+	}

+

+	@Test

+	public void should_wrap_other_exceptions() {

+		exception.expect(RuntimeException.class);

+		exception.expectMessage("Invocation error (ctx)");

+		StatementExecutor executor = new StatementExecutor(this);

+

+		executor.visitInvocation("ctx", "target4");

+	}

+

+	@Test

+	public void should_throw_RuntimeException_when_method_cannot_be_invoked() {

+		exception.expect(RuntimeException.class);

+		exception.expectMessage("Invocation error (ctx)");

+		StatementExecutor executor = new StatementExecutor(this);

+

+		executor.visitInvocation("ctx", "doesNotExist");

+	}

+

+	public void target1(String a, String b, String c) {

+		invocations.put("target1", Arrays.asList(a, b, c));

+	}

+

+	public void target2(int i) {

+		invocations.put("target2", Arrays.asList(Integer.valueOf(i)));

+	}

+

+	public void target3() {

+		throw new AssertionError("Original AssertionError.");

+	}

+

+	public void target4() throws IOException {

+		throw new IOException("Original IOException.");

+	}

+

+}

diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementParser.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementParser.java
new file mode 100644
index 0000000..4008fc8
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementParser.java
@@ -0,0 +1,132 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ *******************************************************************************/

+package org.jacoco.core.test.validation;

+

+import java.io.IOException;

+import java.io.StreamTokenizer;

+import java.io.StringReader;

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * Simple parser for Java like method invocation statements. For example:

+ * 

+ * <pre>

+ * foo("BAR", 42)

+ * </pre>

+ * 

+ * Method parameters can only be String or int literals.

+ */

+class StatementParser {

+

+	/**

+	 * Call-back interface for parsed statements.

+	 */

+	public interface IStatementVisitor {

+

+		/**

+		 * Called when a method invocation has been paresed.

+		 * 

+		 * @param ctx

+		 *            context information for error messages

+		 * @param name

+		 *            local method name

+		 * @param args

+		 *            argument values

+		 */

+		void visitInvocation(String ctx, String name, Object... args);

+

+	}

+

+	/**

+	 * Parses the given source.

+	 * 

+	 * @param source

+	 *            source string to parse

+	 * @param visitor

+	 *            visitor to emit parsed statements

+	 * @param ctx

+	 *            context information to include in error messages

+	 */

+	public static void parse(String source, IStatementVisitor visitor,

+			String ctx) throws IOException {

+		new StatementParser(source, visitor, ctx).parse();

+	}

+

+	private final IStatementVisitor visitor;

+	private final StreamTokenizer tokenizer;

+	private final String ctx;

+

+	private StatementParser(String source, IStatementVisitor visitor,

+			String ctx) {

+		this.visitor = visitor;

+		this.ctx = ctx;

+		tokenizer = new StreamTokenizer(new StringReader(source));

+		tokenizer.resetSyntax();

+		tokenizer.whitespaceChars(' ', ' ');

+		tokenizer.whitespaceChars('\t', '\t');

+		tokenizer.wordChars('a', 'z');

+		tokenizer.wordChars('A', 'Z');

+		tokenizer.quoteChar('"');

+		tokenizer.parseNumbers();

+	}

+

+	private void parse() throws IOException {

+		while (!accept(StreamTokenizer.TT_EOF)) {

+			invocation();

+		}

+	}

+

+	private void invocation() throws IOException {

+		final String name = expect(StreamTokenizer.TT_WORD).sval;

+		final List<Object> args = new ArrayList<Object>();

+		expect('(');

+		if (!accept(')')) {

+			args.add(argument());

+			while (!accept(')')) {

+				expect(',');

+				args.add(argument());

+			}

+		}

+		visitor.visitInvocation(ctx, name, args.toArray());

+	}

+

+	private Object argument() throws IOException {

+		if (accept(StreamTokenizer.TT_NUMBER)) {

+			return Integer.valueOf((int) tokenizer.nval);

+		}

+		if (accept('"')) {

+			return tokenizer.sval;

+		}

+		throw syntaxError();

+	}

+

+	private boolean accept(final int type) throws IOException {

+		final boolean match = tokenizer.nextToken() == type;

+		if (!match) {

+			tokenizer.pushBack();

+		}

+		return match;

+	}

+

+	private StreamTokenizer expect(final int type) throws IOException {

+		if (tokenizer.nextToken() != type) {

+			throw syntaxError();

+		}

+		return tokenizer;

+	}

+

+	private IOException syntaxError() {

+		return new IOException("Invalid syntax (" + ctx + ")");

+	}

+

+}

diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementParserTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementParserTest.java
new file mode 100644
index 0000000..7e7b780
--- /dev/null
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/StatementParserTest.java
@@ -0,0 +1,140 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ *******************************************************************************/

+package org.jacoco.core.test.validation;

+

+import static org.junit.Assert.assertEquals;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.List;

+

+import org.jacoco.core.test.validation.StatementParser.IStatementVisitor;

+import org.junit.After;

+import org.junit.Before;

+import org.junit.Rule;

+import org.junit.Test;

+import org.junit.rules.ExpectedException;

+

+/**

+ * Unit tests for {@link StatementParser}

+ */

+public class StatementParserTest {

+

+	private IStatementVisitor visitor;

+

+	private List<String> actualInvocations;

+	private List<String> expectedInvocations;

+

+	@Rule

+	public ExpectedException exception = ExpectedException.none();

+

+	@Before

+	public void setup() {

+		actualInvocations = new ArrayList<String>();

+		expectedInvocations = new ArrayList<String>();

+		visitor = new IStatementVisitor() {

+			public void visitInvocation(String ctx, String name,

+					Object... args) {

+				actualInvocations.add(invocationStr(ctx, name, args));

+			}

+		};

+	}

+

+	@After

+	public void teardown() {

+		assertEquals(expectedInvocations, actualInvocations);

+	}

+

+	@Test

+	public void should_parse_empty_string() throws IOException {

+		StatementParser.parse("", visitor, "Foo.java");

+	}

+

+	@Test

+	public void should_parse_invocation_without_params() throws IOException {

+		StatementParser.parse("run()", visitor, "Foo.java");

+		expectInvocation("Foo.java", "run");

+	}

+

+	@Test

+	public void should_parse_invocation_with_one_int_parameter()

+			throws IOException {

+		StatementParser.parse("ask(42)", visitor, "Foo.java");

+		expectInvocation("Foo.java", "ask", Integer.valueOf(42));

+	}

+

+	@Test

+	public void should_parse_invocation_with_one_string_parameter()

+			throws IOException {

+		StatementParser.parse("say(\"hello\")", visitor, "Foo.java");

+		expectInvocation("Foo.java", "say", "hello");

+	}

+

+	@Test

+	public void should_parse_invocation_with_two_parameters()

+			throws IOException {

+		StatementParser.parse("add(1000, 234)", visitor, "Foo.java");

+		expectInvocation("Foo.java", "add", Integer.valueOf(1000),

+				Integer.valueOf(234));

+	}

+

+	@Test

+	public void should_parse_invocation_with_mixed_parameter_types()

+			throws IOException {

+		StatementParser.parse("mix(1, \"two\", 3)", visitor, "Foo.java");

+		expectInvocation("Foo.java", "mix", Integer.valueOf(1), "two",

+				Integer.valueOf(3));

+	}

+

+	@Test

+	public void should_parse_multiple_invocations() throws IOException {

+		StatementParser.parse("start() stop()", visitor, "Foo.java");

+		expectInvocation("Foo.java", "start");

+		expectInvocation("Foo.java", "stop");

+	}

+

+	@Test

+	public void should_fail_when_parenthesis_is_missing() throws IOException {

+		exception.expect(IOException.class);

+		StatementParser.parse("bad(", visitor, "Foo.java");

+	}

+

+	@Test

+	public void should_fail_when_argument1_is_missing() throws IOException {

+		exception.expect(IOException.class);

+		StatementParser.parse("bad(,2)", visitor, "Foo.java");

+	}

+

+	@Test

+	public void should_fail_when_argument2_is_missing() throws IOException {

+		exception.expect(IOException.class);

+		StatementParser.parse("bad(1,)", visitor, "Foo.java");

+	}

+

+	@Test

+	public void should_give_context_info_when_parsing_fails()

+			throws IOException {

+		exception.expect(IOException.class);

+		exception.expectMessage("Invalid syntax (Foo.java:32)");

+		StatementParser.parse("bad", visitor, "Foo.java:32");

+	}

+

+	private void expectInvocation(String ctx, String name, Object... args) {

+		expectedInvocations.add(invocationStr(ctx, name, args));

+	}

+

+	private String invocationStr(String ctx, String name, Object... args) {

+		return String.format("%s:%s%s", ctx, name, Arrays.asList(args));

+	}

+

+}

diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java
index d7a2fd0..bf96bbc 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,7 +12,7 @@
 package org.jacoco.core.test.validation;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.lang.reflect.Method;
@@ -22,14 +22,15 @@
 import org.jacoco.core.analysis.CoverageBuilder;
 import org.jacoco.core.analysis.ICounter;
 import org.jacoco.core.analysis.ILine;
-import org.jacoco.core.analysis.ISourceFileCoverage;
 import org.jacoco.core.data.ExecutionData;
 import org.jacoco.core.data.ExecutionDataStore;
 import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.core.test.InstrumentingLoader;
 import org.jacoco.core.test.TargetLoader;
+import org.jacoco.core.test.validation.Source.Line;
 import org.jacoco.core.test.validation.targets.Stubs;
 import org.junit.Before;
+import org.junit.Test;
 
 /**
  * Base class for validation tests. It executes the given class under code
@@ -39,6 +40,9 @@
 
 	protected static final boolean isJDKCompiler = Compiler.DETECT.isJDK();
 
+	protected static final JavaVersion JAVA_VERSION = new JavaVersion(
+			System.getProperty("java.version"));
+
 	private static final String[] STATUS_NAME = new String[4];
 
 	{
@@ -48,30 +52,20 @@
 		STATUS_NAME[ICounter.PARTLY_COVERED] = "PARTLY_COVERED";
 	}
 
-	private final String srcFolder;
-
 	private final Class<?> target;
 
-	private ISourceFileCoverage sourceCoverage;
-
 	private Source source;
 
 	private InstrumentingLoader loader;
 
-	protected ValidationTestBase(final String srcFolder, final Class<?> target) {
-		this.srcFolder = srcFolder;
-		this.target = target;
-	}
-
 	protected ValidationTestBase(final Class<?> target) {
-		this("src", target);
+		this.target = target;
 	}
 
 	@Before
 	public void setup() throws Exception {
 		final ExecutionDataStore store = execute();
 		analyze(store);
-		source = Source.getSourceFor(srcFolder, target);
 	}
 
 	private ExecutionDataStore execute() throws Exception {
@@ -91,54 +85,106 @@
 		for (ExecutionData data : store.getContents()) {
 			analyze(analyzer, data);
 		}
-
-		String srcName = target.getName().replace('.', '/') + ".java";
-		for (ISourceFileCoverage file : builder.getSourceFiles()) {
-			if (srcName.equals(file.getPackageName() + "/" + file.getName())) {
-				sourceCoverage = file;
-				return;
-			}
-		}
-		fail("No source node found for " + srcName);
+		source = Source.load(target, builder.getBundle("Test"));
 	}
 
 	private void analyze(final Analyzer analyzer, final ExecutionData data)
 			throws IOException {
-		final byte[] bytes = TargetLoader.getClassDataAsBytes(
-				target.getClassLoader(), data.getName());
+		final byte[] bytes = TargetLoader
+				.getClassDataAsBytes(target.getClassLoader(), data.getName());
 		analyzer.analyzeClass(bytes, data.getName());
 	}
 
+	/**
+	 * All single line comments are interpreted as statements in the following
+	 * format:
+	 * 
+	 * <pre>
+	 * // statement1() statement2()
+	 * </pre>
+	 */
+	@Test
+	public void execute_assertions_in_comments() throws IOException {
+		for (Line line : source.getLines()) {
+			String exec = line.getComment();
+			if (exec != null) {
+				StatementParser.parse(exec, new StatementExecutor(this, line),
+						line.toString());
+			}
+		}
+	}
+
+	@Test
+	public void last_line_in_coverage_data_should_be_less_or_equal_to_number_of_lines_in_source_file() {
+		assertTrue(String.format(
+				"Last line in coverage data (%d) should be less or equal to number of lines in source file (%d)",
+				Integer.valueOf(source.getCoverage().getLastLine()),
+				Integer.valueOf(source.getLines().size())),
+				source.getCoverage().getLastLine() <= source.getLines().size());
+	}
+
+	/*
+	 * Predefined assertion methods:
+	 */
+
+	private void assertCoverage(final Line line, final int insnStatus,
+			final int missedBranches, final int coveredBranches) {
+		final ILine coverage = line.getCoverage();
+
+		String msg = String.format("Instructions (%s)", line);
+		final int actualStatus = coverage.getInstructionCounter().getStatus();
+		assertEquals(msg, STATUS_NAME[insnStatus], STATUS_NAME[actualStatus]);
+
+		msg = String.format("Branches (%s)", line);
+		assertEquals(msg,
+				CounterImpl.getInstance(missedBranches, coveredBranches),
+				coverage.getBranchCounter());
+	}
+
+	public void assertFullyCovered(final Line line, final int missedBranches,
+			final int coveredBranches) {
+		assertCoverage(line, ICounter.FULLY_COVERED, missedBranches,
+				coveredBranches);
+	}
+
+	public void assertFullyCovered(final Line line) {
+		assertFullyCovered(line, 0, 0);
+	}
+
+	public void assertPartlyCovered(final Line line, final int missedBranches,
+			final int coveredBranches) {
+		assertCoverage(line, ICounter.PARTLY_COVERED, missedBranches,
+				coveredBranches);
+	}
+
+	public void assertPartlyCovered(final Line line) {
+		assertPartlyCovered(line, 0, 0);
+	}
+
+	public void assertNotCovered(final Line line, final int missedBranches,
+			final int coveredBranches) {
+		assertCoverage(line, ICounter.NOT_COVERED, missedBranches,
+				coveredBranches);
+	}
+
+	public void assertNotCovered(final Line line) {
+		assertNotCovered(line, 0, 0);
+	}
+
+	public void assertEmpty(final Line line) {
+		assertCoverage(line, ICounter.EMPTY, 0, 0);
+	}
+
+	protected void assertLogEvents(String... events) throws Exception {
+		final Method getter = Class
+				.forName(Stubs.class.getName(), false, loader)
+				.getMethod("getLogEvents");
+		assertEquals("Log events", Arrays.asList(events), getter.invoke(null));
+	}
+
 	protected void assertMethodCount(final int expectedTotal) {
 		assertEquals(expectedTotal,
-				sourceCoverage.getMethodCounter().getTotalCount());
-	}
-
-	protected void assertLine(final String tag, final int status) {
-		final int nr = source.getLineNumber(tag);
-		final ILine line = sourceCoverage.getLine(nr);
-		final String msg = String.format("Status in line %s: %s",
-				Integer.valueOf(nr), source.getLine(nr));
-		final int insnStatus = line.getInstructionCounter().getStatus();
-		assertEquals(msg, STATUS_NAME[status], STATUS_NAME[insnStatus]);
-	}
-
-	protected void assertLine(final String tag, final int status,
-			final int missedBranches, final int coveredBranches) {
-		assertLine(tag, status);
-		final int nr = source.getLineNumber(tag);
-		final ILine line = sourceCoverage.getLine(nr);
-		final String msg = String.format("Branches in line %s: %s",
-				Integer.valueOf(nr), source.getLine(nr));
-		assertEquals(msg + " branches",
-				CounterImpl.getInstance(missedBranches, coveredBranches),
-				line.getBranchCounter());
-	}
-
-	protected void assertLogEvents(String... events) throws Exception {
-		final Method getter = Class.forName(Stubs.class.getName(), false,
-				loader).getMethod("getLogEvents");
-		assertEquals("Log events", Arrays.asList(events), getter.invoke(null));
+				source.getCoverage().getMethodCounter().getTotalCount());
 	}
 
 }
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java
index 372af22..d5c1cbe 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Stubs.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target01.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target01.java
deleted file mode 100644
index 81d00fa..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target01.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.f;
-import static org.jacoco.core.test.validation.targets.Stubs.i2;
-import static org.jacoco.core.test.validation.targets.Stubs.nop;
-import static org.jacoco.core.test.validation.targets.Stubs.t;
-
-import java.util.Collections;
-
-/**
- * This target exercises a set of common Java control structures.
- */
-public class Target01 {
-
-	public static void main(String[] args) {
-
-		unconditionalExecution();
-		missedIfBlock();
-		executedIfBlock();
-		missedWhileBlock();
-		alwaysExecutedWhileBlock();
-		executedWhileBlock();
-		executedDoWhileBlock();
-		missedForBlock();
-		executedForBlock();
-		missedForEachBlock();
-		executedForEachBlock();
-		tableSwitchWithHit();
-		continuedTableSwitchWithHit();
-		tableSwitchWithoutHit();
-		lookupSwitchWithHit();
-		continuedLookupSwitchWithHit();
-		lookupSwitchWithoutHit();
-		breakStatement();
-		continueStatement();
-		conditionalReturn();
-		implicitReturn();
-		explicitReturn();
-
-	}
-
-	private static void unconditionalExecution() {
-
-		nop(); // $line-unconditional$
-
-	}
-
-	private static void missedIfBlock() {
-
-		if (f()) { // $line-iffalse$
-			nop(); // $line-missedif$
-		} else {
-			nop(); // $line-executedelse$
-		}
-
-	}
-
-	private static void executedIfBlock() {
-
-		if (t()) { // $line-iftrue$
-			nop(); // $line-executedif$
-		} else {
-			nop(); // $line-missedelse$
-		}
-
-	}
-
-	private static void missedWhileBlock() {
-
-		while (f()) { // $line-whilefalse$
-			nop(); // $line-missedwhile$
-		}
-
-	}
-
-	private static void alwaysExecutedWhileBlock() {
-
-		while (t()) { // $line-whiletrue$
-			if (t()) {
-				break;
-			}
-		}
-
-	}
-
-	private static void executedWhileBlock() {
-
-		int i = 0;
-		while (i++ < 3) { // $line-whiletruefalse$
-			nop(); // $line-executedwhile$
-		}
-
-	}
-
-	private static void executedDoWhileBlock() {
-
-		do {
-			nop(); // $line-executeddowhile$
-		} while (f()); // $line-executeddowhilefalse$
-
-	}
-
-	private static void missedForBlock() {
-
-		for (nop(); f(); nop()) { // $line-missedforincrementer$
-			nop(); // $line-missedfor$
-		}
-
-	}
-
-	private static void executedForBlock() {
-
-		for (int j = 0; j < 1; j++) { // $line-executedforincrementer$
-			nop(); // $line-executedfor$
-		}
-
-	}
-
-	private static void missedForEachBlock() {
-
-		for (Object o : Collections.emptyList()) { // $line-missedforeachincrementer$
-			nop(o); // $line-missedforeach$
-		}
-
-	}
-
-	private static void executedForEachBlock() {
-
-		for (Object o : Collections.singleton(new Object())) { // $line-executedforeachincrementer$
-			nop(o); // $line-executedforeach$
-		}
-
-	}
-
-	private static void tableSwitchWithHit() {
-
-		switch (i2()) { // $line-tswitch1$
-		case 1:
-			nop(); // $line-tswitch1case1$
-			break;
-		case 2:
-			nop(); // $line-tswitch1case2$
-			break;
-		case 3:
-			nop(); // $line-tswitch1case3$
-			break;
-		default:
-			nop(); // $line-tswitch1default$
-			break;
-		}
-
-	}
-
-	private static void continuedTableSwitchWithHit() {
-
-		switch (i2()) { // $line-tswitch2$
-		case 1:
-			nop(); // $line-tswitch2case1$
-		case 2:
-			nop(); // $line-tswitch2case2$
-		case 3:
-			nop(); // $line-tswitch2case3$
-		default:
-			nop(); // $line-tswitch2default$
-		}
-
-	}
-
-	private static void tableSwitchWithoutHit() {
-
-		switch (i2()) { // $line-tswitch3$
-		case 3:
-			nop(); // $line-tswitch3case1$
-			break;
-		case 4:
-			nop(); // $line-tswitch3case2$
-			break;
-		case 5:
-			nop(); // $line-tswitch3case3$
-			break;
-		default:
-			nop(); // $line-tswitch3default$
-			break;
-		}
-
-	}
-
-	private static void lookupSwitchWithHit() {
-
-		switch (i2()) { // $line-lswitch1$
-		case -123:
-			nop(); // $line-lswitch1case1$
-			break;
-		case 2:
-			nop(); // $line-lswitch1case2$
-			break;
-		case 456:
-			nop(); // $line-lswitch1case3$
-			break;
-		default:
-			nop(); // $line-lswitch1default$
-			break;
-		}
-
-	}
-
-	private static void continuedLookupSwitchWithHit() {
-
-		switch (i2()) { // $line-lswitch2$
-		case -123:
-			nop(); // $line-lswitch2case1$
-		case 2:
-			nop(); // $line-lswitch2case2$
-		case 456:
-			nop(); // $line-lswitch2case3$
-		default:
-			nop(); // $line-lswitch2default$
-		}
-
-	}
-
-	private static void lookupSwitchWithoutHit() {
-
-		switch (i2()) { // $line-lswitch3$
-		case -123:
-			nop(); // $line-lswitch3case1$
-			break;
-		case 456:
-			nop(); // $line-lswitch3case2$
-			break;
-		case 789:
-			nop(); // $line-lswitch3case3$
-			break;
-		default:
-			nop(); // $line-lswitch3default$
-			break;
-		}
-
-	}
-
-	private static void breakStatement() {
-
-		while (true) {
-			if (t()) {
-				break; // $line-executedbreak$
-			}
-			nop(); // $line-missedafterbreak$
-		}
-
-	}
-
-	private static void continueStatement() {
-
-		for (int j = 0; j < 1; j++) {
-			if (t()) {
-				continue; // $line-executedcontinue$
-			}
-			nop(); // $line-missedaftercontinue$
-		}
-
-	}
-
-	private static void conditionalReturn() {
-
-		if (t()) {
-			return; // $line-conditionalreturn$
-		}
-		nop(); // $line-afterconditionalreturn$
-
-	}
-
-	private static void implicitReturn() {
-
-	} // $line-implicitreturn$
-
-	private static void explicitReturn() {
-
-		return; // $line-explicitreturn$
-
-	} // $line-afterexplicitreturn$
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target02.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target02.java
deleted file mode 100644
index 62e22ef..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target02.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.f;
-import static org.jacoco.core.test.validation.targets.Stubs.i1;
-import static org.jacoco.core.test.validation.targets.Stubs.i2;
-import static org.jacoco.core.test.validation.targets.Stubs.nop;
-import static org.jacoco.core.test.validation.targets.Stubs.t;
-
-/**
- * This target exercises boolean expressions.
- */
-public class Target02 {
-
-	public static void main(String[] args) {
-
-		// 1. Boolean comparison result (one case)
-		nop(i2() > 3); // $line-booleancmp1$
-
-		// 2. Boolean comparison result (both cases)
-		for (int i = 0; i < 2; i++) {
-			nop(i < 1); // $line-booleancmp2$
-		}
-
-		// 3. And
-		if (f() & f()) { // $line-andFF$
-			nop();
-		}
-		if (f() & t()) { // $line-andFT$
-			nop();
-		}
-		if (t() & f()) { // $line-andTF$
-			nop();
-		}
-		if (t() & t()) { // $line-andTT$
-			nop();
-		}
-
-		// 4. Conditional And
-		if (f() && f()) { // $line-conditionalandFF$
-			nop();
-		}
-		if (f() && t()) { // $line-conditionalandFT$
-			nop();
-		}
-		if (t() && f()) { // $line-conditionalandTF$
-			nop();
-		}
-		if (t() && t()) { // $line-conditionalandTT$
-			nop();
-		}
-
-		// 5. Or
-		if (f() | f()) { // $line-orFF$
-			nop();
-		}
-		if (f() | t()) { // $line-orFT$
-			nop();
-		}
-		if (t() | f()) { // $line-orTF$
-			nop();
-		}
-		if (t() | t()) { // $line-orTT$
-			nop();
-		}
-
-		// 6. Conditional Or
-		if (f() || f()) { // $line-conditionalorFF$
-			nop();
-		}
-		if (f() || t()) { // $line-conditionalorFT$
-			nop();
-		}
-		if (t() || f()) { // $line-conditionalorTF$
-			nop();
-		}
-		if (t() || t()) { // $line-conditionalorTT$
-			nop();
-		}
-
-		// 7. Exclusive Or
-		if (f() ^ f()) { // $line-xorFF$
-			nop();
-		}
-		if (f() ^ t()) { // $line-xorFT$
-			nop();
-		}
-		if (t() ^ f()) { // $line-xorTF$
-			nop();
-		}
-		if (t() ^ t()) { // $line-xorTT$
-			nop();
-		}
-
-		// 8. Conditional Operator
-		nop(t() ? i1() : i2()); // $line-condT$
-		nop(f() ? i1() : i2()); // $line-condF$
-
-		// 9. Not (one case)
-		nop(!t()); // $line-notT$
-		nop(!f()); // $line-notF$
-
-		// 10. Not (both cases)
-		for (boolean b : new boolean[] { true, false }) {
-			nop(!b); // $line-notTF$
-		}
-
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target03.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target03.java
deleted file mode 100644
index b4418ed..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target03.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.ex;
-import static org.jacoco.core.test.validation.targets.Stubs.f;
-import static org.jacoco.core.test.validation.targets.Stubs.nop;
-
-import org.jacoco.core.test.validation.targets.Stubs.StubException;
-
-/**
- * This target produces exception based control flow examples.
- */
-public class Target03 {
-
-	public static void main(String[] args) {
-
-		try {
-			implicitNullPointerException(null);
-		} catch (NullPointerException e) {
-		}
-		try {
-			implicitException();
-		} catch (StubException e) {
-		}
-		try {
-			explicitException();
-		} catch (StubException e) {
-		}
-		noExceptionTryCatch();
-		implicitExceptionTryCatch();
-		implicitExceptionTryCatchAfterCondition();
-		explicitExceptionTryCatch();
-		noExceptionFinally();
-		try {
-			explicitExceptionFinally();
-		} catch (StubException e) {
-		}
-		try {
-			implicitExceptionFinally();
-		} catch (StubException e) {
-		}
-	}
-
-	private static void implicitNullPointerException(int[] a) {
-		nop(); // $line-implicitNullPointerException.before$
-		a[0] = 0; // $line-implicitNullPointerException.exception$
-		nop(); // $line-implicitNullPointerException.after$
-	}
-
-	private static void implicitException() {
-		nop(); // $line-implicitException.before$
-		ex(); // $line-implicitException.exception$
-		nop(); // $line-implicitException.after$
-	}
-
-	private static void explicitException() {
-		nop(); // $line-explicitException.before$
-		throw new StubException(); // $line-explicitException.throw$
-	}
-
-	private static void noExceptionTryCatch() {
-		nop(); // $line-noExceptionTryCatch.beforeBlock$
-		try {
-			nop(); // $line-noExceptionTryCatch.tryBlock$
-		} catch (StubException e) { // $line-noExceptionTryCatch.catch$
-			nop(); // $line-noExceptionTryCatch.catchBlock$
-		} // $line-noExceptionTryCatch.catchBlockEnd$
-	} // $line-noExceptionTryCatch.afterBlock$
-
-	private static void implicitExceptionTryCatch() {
-		nop(); // $line-implicitExceptionTryCatch.beforeBlock$
-		try {
-			nop(); // $line-implicitExceptionTryCatch.before$
-			ex(); // $line-implicitExceptionTryCatch.exception$
-			nop(); // $line-implicitExceptionTryCatch.after$
-		} catch (StubException e) { // $line-implicitExceptionTryCatch.catch$
-			nop(); // $line-implicitExceptionTryCatch.catchBlock$
-		} // $line-implicitExceptionTryCatch.catchBlockEnd$
-	} // $line-implicitExceptionTryCatch.afterBlock$
-
-	private static void implicitExceptionTryCatchAfterCondition() {
-		if (f()) { // $line-implicitExceptionTryCatchAfterCondition.condition$
-			return;
-		}
-		try {
-			ex(); // $line-implicitExceptionTryCatchAfterCondition.exception$
-		} catch (StubException e) {
-			nop(); // $line-implicitExceptionTryCatchAfterCondition.catchBlock$
-		}
-	}
-
-	private static void explicitExceptionTryCatch() {
-		nop(); // $line-explicitExceptionTryCatch.beforeBlock$
-		try {
-			nop(); // $line-explicitExceptionTryCatch.before$
-			throw new StubException(); // $line-explicitExceptionTryCatch.throw$
-		} catch (StubException e) { // $line-explicitExceptionTryCatch.catch$
-			nop(); // $line-explicitExceptionTryCatch.catchBlock$
-		} // $line-explicitExceptionTryCatch.catchBlockEnd$
-	} // $line-explicitExceptionTryCatch.afterBlock$
-
-	private static void noExceptionFinally() {
-		nop(); // $line-noExceptionFinally.beforeBlock$
-		try {
-			nop(); // $line-noExceptionFinally.tryBlock$
-		} finally { // $line-noExceptionFinally.finally$
-			nop(); // $line-noExceptionFinally.finallyBlock$
-		} // $line-noExceptionFinally.finallyBlockEnd$
-	} // $line-noExceptionFinally.afterBlock$
-
-	private static void implicitExceptionFinally() {
-		nop(); // $line-implicitExceptionFinally.beforeBlock$
-		try {
-			nop(); // $line-implicitExceptionFinally.before$
-			ex(); // $line-implicitExceptionFinally.exception$
-			nop(); // $line-implicitExceptionFinally.after$
-		} finally { // $line-implicitExceptionFinally.finally$
-			nop(); // $line-implicitExceptionFinally.finallyBlock$
-		} // $line-implicitExceptionFinally.finallyBlockEnd$
-	} // $line-implicitExceptionFinally.afterBlock$
-
-	private static void explicitExceptionFinally() {
-		nop(); // $line-explicitExceptionFinally.beforeBlock$
-		try {
-			nop(); // $line-explicitExceptionFinally.before$
-			throw new StubException(); // $line-explicitExceptionFinally.throw$
-		} finally { // $line-explicitExceptionFinally.finally$
-			nop(); // $line-explicitExceptionFinally.finallyBlock$
-		} // $line-explicitExceptionFinally.finallyBlockEnd$
-	} // $line-explicitExceptionFinally.afterBlock$
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target04.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target04.java
deleted file mode 100644
index 8384744..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target04.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.i1;
-
-/**
- * This test target is an interface with a class initializer.
- */
-public interface Target04 {
-
-	// No code required to initialize these fields:
-
-	static final int CONST1 = 12345; // $line-const1$
-
-	static final String CONST2 = "const"; // $line-const2$
-
-	// These fields are initialized within <clinit>
-
-	static final int CONST3 = i1(); // $line-const3$
-
-	static final Object CONST4 = new Object(); // $line-const4$
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target05.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target05.java
deleted file mode 100644
index ef5c398..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target05.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-import static org.jacoco.core.test.validation.targets.Stubs.i1;
-
-/**
- * This test target is a class with a static initializer.
- */
-public class Target05 {
-
-	// No code required to initialize these fields:
-
-	public static final int CONST1 = 3; // $line-const1$
-
-	public static final String CONST2 = "Hello"; // $line-const2$
-
-	// These fields are initialized within <clinit>
-
-	public static final int CONST3 = i1(); // $line-const3$
-
-	public static final Object CONST4 = new Object(); // $line-const4$
-
-	public static int field1 = 3; // $line-field1$
-
-	public static String field2 = "Hello"; // $line-field2$
-
-	public static int field3 = i1(); // $line-field3$
-
-	public static Object field4 = new Object(); // $line-field4$
-
-	static {
-		Stubs.nop(); // $line-staticblock$
-	}
-
-	private Target05() {
-	}
-
-	public static void main(String[] args) {
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target06.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target06.java
deleted file mode 100644
index f6bc75e..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target06.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-/**
- * This test target is a class with a implicit default constructor.
- *
- * @see Target07 explicit constructor
- */
-public class Target06 { // $line-classdef$
-
-	public static void main(String[] args) {
-		new Target06();
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target07.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target07.java
deleted file mode 100644
index 18c3ba5..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target07.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-/**
- * This test target is a private empty default constructor.
- *
- * @see Target06 implicit constructor
- */
-public class Target07 { // $line-classdef$
-
-	private Target07() { // $line-super$
-	} // $line-constructor$
-
-	public static void main(String[] args) {
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target09.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target09.java
deleted file mode 100644
index a8589d1..0000000
--- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/targets/Target09.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.test.validation.targets;
-
-/**
- * This test target has instance members with initialization in two
- * constructors.
- */
-public class Target09 {
-
-	Object field1 = null; // $line-field1$
-
-	int field2 = 123; // $line-field2$
-
-	public Target09() {
-	} // $line-constr1$
-
-	public Target09(String arg) {
-	} // $line-constr2$
-
-	public static void main(String[] args) {
-		new Target09();
-	}
-
-}
diff --git a/org.jacoco.core.test/src/org/jacoco/core/tools/ExecDumpClientTest.java b/org.jacoco.core.test/src/org/jacoco/core/tools/ExecDumpClientTest.java
index 591d032..640f924 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/tools/ExecDumpClientTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/tools/ExecDumpClientTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core.test/src/org/jacoco/core/tools/ExecFileLoaderTest.java b/org.jacoco.core.test/src/org/jacoco/core/tools/ExecFileLoaderTest.java
index d825910..1214888 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/tools/ExecFileLoaderTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/tools/ExecFileLoaderTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/pom.xml b/org.jacoco.core/pom.xml
index d147c11..0bb5b2b 100644
--- a/org.jacoco.core/pom.xml
+++ b/org.jacoco.core/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
@@ -37,14 +37,6 @@
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm-tree</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.ow2.asm</groupId>
-      <artifactId>asm-analysis</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.ow2.asm</groupId>
-      <artifactId>asm-util</artifactId>
-    </dependency>
   </dependencies>
 
   <build>
diff --git a/org.jacoco.core/src/org/jacoco/core/JaCoCo.java b/org.jacoco.core/src/org/jacoco/core/JaCoCo.java
index cb3fb4d..ce9ec05 100644
--- a/org.jacoco.core/src/org/jacoco/core/JaCoCo.java
+++ b/org.jacoco.core/src/org/jacoco/core/JaCoCo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java b/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java
index 53dbf0c..76b7be3 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -30,8 +30,10 @@
 import org.jacoco.core.internal.analysis.StringPool;
 import org.jacoco.core.internal.data.CRC64;
 import org.jacoco.core.internal.flow.ClassProbesAdapter;
+import org.jacoco.core.internal.instr.InstrSupport;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Opcodes;
 
 /**
  * An {@link Analyzer} instance processes a set of Java class files and
@@ -99,15 +101,17 @@
 		return new ClassProbesAdapter(analyzer, false);
 	}
 
-	/**
-	 * Analyzes the class given as a ASM reader.
-	 * 
-	 * @param reader
-	 *            reader with class definitions
-	 */
-	public void analyzeClass(final ClassReader reader) {
-		final ClassVisitor visitor = createAnalyzingVisitor(
-				CRC64.classId(reader.b), reader.getClassName());
+	private void analyzeClass(final byte[] source) {
+		final long classId = CRC64.classId(source);
+		final ClassReader reader = InstrSupport.classReaderFor(source);
+		if ((reader.getAccess() & Opcodes.ACC_MODULE) != 0) {
+			return;
+		}
+		if ((reader.getAccess() & Opcodes.ACC_SYNTHETIC) != 0) {
+			return;
+		}
+		final ClassVisitor visitor = createAnalyzingVisitor(classId,
+				reader.getClassName());
 		reader.accept(visitor, 0);
 	}
 
@@ -124,7 +128,7 @@
 	public void analyzeClass(final byte[] buffer, final String location)
 			throws IOException {
 		try {
-			analyzeClass(new ClassReader(buffer));
+			analyzeClass(buffer);
 		} catch (final RuntimeException cause) {
 			throw analyzerError(location, cause);
 		}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java b/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java
index 1848c6f..8a67b97 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/CounterComparator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java b/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java
index a44afb7..784fbd8 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -95,26 +95,22 @@
 		return result;
 	}
 
-	// === IStructureVisitor ===
+	// === ICoverageVisitor ===
 
 	public void visitCoverage(final IClassCoverage coverage) {
-		// Only consider classes that actually contain code:
-		if (coverage.getInstructionCounter().getTotalCount() > 0) {
-			final String name = coverage.getName();
-			final IClassCoverage dup = classes.put(name, coverage);
-			if (dup != null) {
-				if (dup.getId() != coverage.getId()) {
-					throw new IllegalStateException(
-							"Can't add different class with same name: "
-									+ name);
-				}
-			} else {
-				final String source = coverage.getSourceFileName();
-				if (source != null) {
-					final SourceFileCoverageImpl sourceFile = getSourceFile(
-							source, coverage.getPackageName());
-					sourceFile.increment(coverage);
-				}
+		final String name = coverage.getName();
+		final IClassCoverage dup = classes.put(name, coverage);
+		if (dup != null) {
+			if (dup.getId() != coverage.getId()) {
+				throw new IllegalStateException(
+						"Can't add different class with same name: " + name);
+			}
+		} else {
+			final String source = coverage.getSourceFileName();
+			if (source != null) {
+				final SourceFileCoverageImpl sourceFile = getSourceFile(source,
+						coverage.getPackageName());
+				sourceFile.increment(coverage);
 			}
 		}
 	}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/CoverageNodeImpl.java b/org.jacoco.core/src/org/jacoco/core/analysis/CoverageNodeImpl.java
index c1bcb26..6be3bb6 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/CoverageNodeImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/CoverageNodeImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -143,6 +143,10 @@
 		throw new AssertionError(entity);
 	}
 
+	public boolean containsCode() {
+		return getInstructionCounter().getTotalCount() != 0;
+	}
+
 	public ICoverageNode getPlainCopy() {
 		final CoverageNodeImpl copy = new CoverageNodeImpl(elementType, name);
 		copy.instructionCounter = CounterImpl.getInstance(instructionCounter);
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/IBundleCoverage.java b/org.jacoco.core/src/org/jacoco/core/analysis/IBundleCoverage.java
index afcdc1a..d488f47 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/IBundleCoverage.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/IBundleCoverage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -25,6 +25,6 @@
 	 * 
 	 * @return all packages
 	 */
-	public Collection<IPackageCoverage> getPackages();
+	Collection<IPackageCoverage> getPackages();
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/IClassCoverage.java b/org.jacoco.core/src/org/jacoco/core/analysis/IClassCoverage.java
index f72b7a8..81cc6fe 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/IClassCoverage.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/IClassCoverage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -27,7 +27,7 @@
 	 * 
 	 * @return class identifier
 	 */
-	public long getId();
+	long getId();
 
 	/**
 	 * Returns if the the analyzed class does match the execution data provided.
@@ -37,14 +37,14 @@
 	 * @return <code>true</code> if this class does not match to the provided
 	 *         execution data.
 	 */
-	public boolean isNoMatch();
+	boolean isNoMatch();
 
 	/**
 	 * Returns the VM signature of the class.
 	 * 
 	 * @return VM signature of the class (may be <code>null</code>)
 	 */
-	public String getSignature();
+	String getSignature();
 
 	/**
 	 * Returns the VM name of the superclass.
@@ -52,34 +52,34 @@
 	 * @return VM name of the super class (may be <code>null</code>, i.e.
 	 *         <code>java/lang/Object</code>)
 	 */
-	public String getSuperName();
+	String getSuperName();
 
 	/**
 	 * Returns the VM names of implemented/extended interfaces.
 	 * 
 	 * @return VM names of implemented/extended interfaces
 	 */
-	public String[] getInterfaceNames();
+	String[] getInterfaceNames();
 
 	/**
 	 * Returns the VM name of the package this class belongs to.
 	 * 
 	 * @return VM name of the package
 	 */
-	public String getPackageName();
+	String getPackageName();
 
 	/**
 	 * Returns the optional name of the corresponding source file.
 	 * 
 	 * @return name of the corresponding source file
 	 */
-	public String getSourceFileName();
+	String getSourceFileName();
 
 	/**
 	 * Returns the methods included in this class.
 	 * 
 	 * @return methods of this class
 	 */
-	public Collection<IMethodCoverage> getMethods();
+	Collection<IMethodCoverage> getMethods();
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/ICounter.java b/org.jacoco.core/src/org/jacoco/core/analysis/ICounter.java
index 5f30e02..60c8dcc 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/ICounter.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/ICounter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -20,7 +20,7 @@
 	/**
 	 * Different values provided by a counter.
 	 */
-	public enum CounterValue {
+	enum CounterValue {
 
 		/** Total number of items */
 		TOTALCOUNT,
@@ -41,22 +41,22 @@
 	/**
 	 * Status flag for no items (value is 0x00).
 	 */
-	public static final int EMPTY = 0x00;
+	int EMPTY = 0x00;
 
 	/**
 	 * Status flag when all items are not covered (value is 0x01).
 	 */
-	public static final int NOT_COVERED = 0x01;
+	int NOT_COVERED = 0x01;
 
 	/**
 	 * Status flag when all items are covered (value is 0x02).
 	 */
-	public static final int FULLY_COVERED = 0x02;
+	int FULLY_COVERED = 0x02;
 
 	/**
 	 * Status flag when items are partly covered (value is 0x03).
 	 */
-	public static final int PARTLY_COVERED = NOT_COVERED | FULLY_COVERED;
+	int PARTLY_COVERED = NOT_COVERED | FULLY_COVERED;
 
 	/**
 	 * Returns the counter value of the given type.
@@ -65,28 +65,28 @@
 	 *            value type to return
 	 * @return counter value
 	 */
-	public double getValue(CounterValue value);
+	double getValue(CounterValue value);
 
 	/**
 	 * Returns the total count of items.
 	 * 
 	 * @return total count of items
 	 */
-	public int getTotalCount();
+	int getTotalCount();
 
 	/**
 	 * Returns the count of covered items.
 	 * 
 	 * @return count of covered items
 	 */
-	public int getCoveredCount();
+	int getCoveredCount();
 
 	/**
 	 * Returns the count of missed items.
 	 * 
 	 * @return count of missed items
 	 */
-	public int getMissedCount();
+	int getMissedCount();
 
 	/**
 	 * Calculates the ratio of covered to total count items. If total count
@@ -94,7 +94,7 @@
 	 * 
 	 * @return ratio of covered to total count items
 	 */
-	public double getCoveredRatio();
+	double getCoveredRatio();
 
 	/**
 	 * Calculates the ratio of missed to total count items. If total count items
@@ -102,7 +102,7 @@
 	 * 
 	 * @return ratio of missed to total count items
 	 */
-	public double getMissedRatio();
+	double getMissedRatio();
 
 	/**
 	 * Returns the coverage status of this counter.
@@ -114,6 +114,6 @@
 	 * 
 	 * @return status of this line
 	 */
-	public int getStatus();
+	int getStatus();
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageNode.java b/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageNode.java
index 0756f41..20b107d 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageNode.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageNode.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -20,7 +20,7 @@
 	/**
 	 * Type of a Java element represented by a {@link ICoverageNode} instance.
 	 */
-	public enum ElementType {
+	enum ElementType {
 
 		/** Method */
 		METHOD,
@@ -45,7 +45,7 @@
 	/**
 	 * Different counter types supported by JaCoCo.
 	 */
-	public enum CounterEntity {
+	enum CounterEntity {
 
 		/** Counter for instructions */
 		INSTRUCTION,
@@ -71,56 +71,56 @@
 	 * 
 	 * @return type of this node
 	 */
-	public abstract ElementType getElementType();
+	ElementType getElementType();
 
 	/**
 	 * Returns the name of this node.
 	 * 
 	 * @return name of this node
 	 */
-	public String getName();
+	String getName();
 
 	/**
 	 * Returns the counter for byte code instructions.
 	 * 
 	 * @return counter for instructions
 	 */
-	public abstract ICounter getInstructionCounter();
+	ICounter getInstructionCounter();
 
 	/**
 	 * Returns the counter for branches.
 	 * 
 	 * @return counter for branches
 	 */
-	public ICounter getBranchCounter();
+	ICounter getBranchCounter();
 
 	/**
 	 * Returns the counter for lines.
 	 * 
 	 * @return counter for lines
 	 */
-	public ICounter getLineCounter();
+	ICounter getLineCounter();
 
 	/**
 	 * Returns the counter for cyclomatic complexity.
 	 * 
 	 * @return counter for complexity
 	 */
-	public ICounter getComplexityCounter();
+	ICounter getComplexityCounter();
 
 	/**
 	 * Returns the counter for methods.
 	 * 
 	 * @return counter for methods
 	 */
-	public ICounter getMethodCounter();
+	ICounter getMethodCounter();
 
 	/**
 	 * Returns the counter for classes.
 	 * 
 	 * @return counter for classes
 	 */
-	public ICounter getClassCounter();
+	ICounter getClassCounter();
 
 	/**
 	 * Generic access to the the counters.
@@ -129,7 +129,14 @@
 	 *            entity we're we want to have the counter for
 	 * @return counter for the given entity
 	 */
-	public ICounter getCounter(CounterEntity entity);
+	ICounter getCounter(CounterEntity entity);
+
+	/**
+	 * Checks whether this node contains code relevant for code coverage.
+	 *
+	 * @return <code>true</code> if this node contains code relevant for code coverage
+	 */
+	boolean containsCode();
 
 	/**
 	 * Creates a plain copy of this node. While {@link ICoverageNode}
@@ -139,6 +146,6 @@
 	 * 
 	 * @return copy with counters only
 	 */
-	public ICoverageNode getPlainCopy();
+	ICoverageNode getPlainCopy();
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageVisitor.java b/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageVisitor.java
index 5a71859..3f70290 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageVisitor.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/ICoverageVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -23,6 +23,6 @@
 	 * @param coverage
 	 *            coverage data for a class
 	 */
-	public void visitCoverage(IClassCoverage coverage);
+	void visitCoverage(IClassCoverage coverage);
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/ILine.java b/org.jacoco.core/src/org/jacoco/core/analysis/ILine.java
index cdd91eb..ef65dc0 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/ILine.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/ILine.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,14 +22,14 @@
 	 * 
 	 * @return instruction counter
 	 */
-	public ICounter getInstructionCounter();
+	ICounter getInstructionCounter();
 
 	/**
 	 * Returns the branches counter for this line.
 	 * 
 	 * @return branches counter
 	 */
-	public ICounter getBranchCounter();
+	ICounter getBranchCounter();
 
 	/**
 	 * Returns the coverage status of this line, calculated from the
@@ -42,6 +42,6 @@
 	 * 
 	 * @return status of this line
 	 */
-	public int getStatus();
+	int getStatus();
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/IMethodCoverage.java b/org.jacoco.core/src/org/jacoco/core/analysis/IMethodCoverage.java
index 3bd7516..b675517 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/IMethodCoverage.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/IMethodCoverage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,13 +22,13 @@
 	 * 
 	 * @return descriptor
 	 */
-	public String getDesc();
+	String getDesc();
 
 	/**
 	 * Returns the generic signature of the method if defined.
 	 * 
 	 * @return generic signature or <code>null</code>
 	 */
-	public String getSignature();
+	String getSignature();
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/IPackageCoverage.java b/org.jacoco.core/src/org/jacoco/core/analysis/IPackageCoverage.java
index 8ff1a18..3212162 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/IPackageCoverage.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/IPackageCoverage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,13 +28,13 @@
 	 * 
 	 * @return all classes
 	 */
-	public Collection<IClassCoverage> getClasses();
+	Collection<IClassCoverage> getClasses();
 
 	/**
 	 * Returns all source files in this package.
 	 * 
 	 * @return all source files
 	 */
-	public Collection<ISourceFileCoverage> getSourceFiles();
+	Collection<ISourceFileCoverage> getSourceFiles();
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/ISourceFileCoverage.java b/org.jacoco.core/src/org/jacoco/core/analysis/ISourceFileCoverage.java
index 6a49490..5f01160 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/ISourceFileCoverage.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/ISourceFileCoverage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,6 @@
 	 * 
 	 * @return package name
 	 */
-	public String getPackageName();
+	String getPackageName();
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java b/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java
index d6c90e5..d64b2cc 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/ISourceNode.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -18,7 +18,7 @@
 public interface ISourceNode extends ICoverageNode {
 
 	/** Place holder for unknown lines (no debug information) */
-	public static int UNKNOWN_LINE = -1;
+	int UNKNOWN_LINE = -1;
 
 	/**
 	 * The number of the first line coverage information is available for. If no
@@ -26,7 +26,7 @@
 	 * 
 	 * @return number of the first line or {@link #UNKNOWN_LINE}
 	 */
-	public int getFirstLine();
+	int getFirstLine();
 
 	/**
 	 * The number of the last line coverage information is available for. If no
@@ -34,7 +34,7 @@
 	 * 
 	 * @return number of the last line or {@link #UNKNOWN_LINE}
 	 */
-	public int getLastLine();
+	int getLastLine();
 
 	/**
 	 * Returns the line information for given line.
@@ -43,6 +43,6 @@
 	 *            line number of interest
 	 * @return line information
 	 */
-	public ILine getLine(int nr);
+	ILine getLine(int nr);
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java b/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java
index da94e07..3fea25f 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/NodeComparator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/package-info.java b/org.jacoco.core/src/org/jacoco/core/analysis/package-info.java
index afee23c..d1a5e73 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/package-info.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -34,4 +34,4 @@
  *                     +-- {@linkplain org.jacoco.core.analysis.ICoverageNode.ElementType#METHOD Method}
  * </pre>
  */
-package org.jacoco.core.analysis;
\ No newline at end of file
+package org.jacoco.core.analysis;
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java
index 6c4b2e0..d98775e 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java
index bdb9860..dd8519b 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataReader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
index 89d9dc6..3e567a3 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java
index 259f1c1..e697dda 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java b/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java
index b2bccd6..6cea7c5 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,6 @@
 	 * @param data
 	 *            execution data for a class
 	 */
-	public void visitClassExecution(ExecutionData data);
+	void visitClassExecution(ExecutionData data);
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ISessionInfoVisitor.java b/org.jacoco.core/src/org/jacoco/core/data/ISessionInfoVisitor.java
index 23e7711..b80797a 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ISessionInfoVisitor.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ISessionInfoVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -25,6 +25,6 @@
 	 * @param info
 	 *            session information
 	 */
-	public void visitSessionInfo(final SessionInfo info);
+	void visitSessionInfo(SessionInfo info);
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java b/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java
index b51b821..cc508e7 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/IncompatibleExecDataVersionException.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -55,4 +55,4 @@
 		return actualVersion;
 	}
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/data/SessionInfo.java b/org.jacoco.core/src/org/jacoco/core/data/SessionInfo.java
index 42a0d89..31f7b5e 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/SessionInfo.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/SessionInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/data/SessionInfoStore.java b/org.jacoco.core/src/org/jacoco/core/data/SessionInfoStore.java
index 0e8d667..568dcc9 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/SessionInfoStore.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/SessionInfoStore.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/data/package-info.java b/org.jacoco.core/src/org/jacoco/core/data/package-info.java
index 4fb179c..6e2f37b 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/package-info.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Representation and persistence of execution data and session information.
  */
-package org.jacoco.core.data;
\ No newline at end of file
+package org.jacoco.core.data;
diff --git a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
index c824978..561b09c 100644
--- a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
+++ b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,9 +24,11 @@
 import org.jacoco.core.internal.ContentTypeDetector;
 import org.jacoco.core.internal.InputStreams;
 import org.jacoco.core.internal.Pack200Streams;
+import org.jacoco.core.internal.data.CRC64;
 import org.jacoco.core.internal.flow.ClassProbesAdapter;
 import org.jacoco.core.internal.instr.ClassInstrumenter;
 import org.jacoco.core.internal.instr.IProbeArrayStrategy;
+import org.jacoco.core.internal.instr.InstrSupport;
 import org.jacoco.core.internal.instr.ProbeArrayStrategyFactory;
 import org.jacoco.core.internal.instr.SignatureRemover;
 import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
@@ -67,15 +69,9 @@
 		signatureRemover.setActive(flag);
 	}
 
-	/**
-	 * Creates a instrumented version of the given class if possible.
-	 * 
-	 * @param reader
-	 *            definition of the class as ASM reader
-	 * @return instrumented definition
-	 * 
-	 */
-	public byte[] instrument(final ClassReader reader) {
+	private byte[] instrument(final byte[] source) {
+		final long classId = CRC64.classId(source);
+		final ClassReader reader = InstrSupport.classReaderFor(source);
 		final ClassWriter writer = new ClassWriter(reader, 0) {
 			@Override
 			protected String getCommonSuperClass(final String type1,
@@ -84,9 +80,11 @@
 			}
 		};
 		final IProbeArrayStrategy strategy = ProbeArrayStrategyFactory
-				.createFor(reader, accessorGenerator);
+				.createFor(classId, reader, accessorGenerator);
+		final int version = InstrSupport.getMajorVersion(reader);
 		final ClassVisitor visitor = new ClassProbesAdapter(
-				new ClassInstrumenter(strategy, writer), true);
+				new ClassInstrumenter(strategy, writer),
+				InstrSupport.needsFrames(version));
 		reader.accept(visitor, ClassReader.EXPAND_FRAMES);
 		return writer.toByteArray();
 	}
@@ -105,7 +103,7 @@
 	public byte[] instrument(final byte[] buffer, final String name)
 			throws IOException {
 		try {
-			return instrument(new ClassReader(buffer));
+			return instrument(buffer);
 		} catch (final RuntimeException e) {
 			throw instrumentError(name, e);
 		}
diff --git a/org.jacoco.core/src/org/jacoco/core/instr/package-info.java b/org.jacoco.core/src/org/jacoco/core/instr/package-info.java
index 2f47403..1da3ef1 100644
--- a/org.jacoco.core/src/org/jacoco/core/instr/package-info.java
+++ b/org.jacoco.core/src/org/jacoco/core/instr/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -16,4 +16,4 @@
  *  is the class {@link org.jacoco.core.instr.Instrumenter}.
  * </p>
  */
-package org.jacoco.core.instr;
\ No newline at end of file
+package org.jacoco.core.instr;
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java
index ae66562..74574ec 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -83,6 +83,13 @@
 			case Opcodes.V1_7:
 			case Opcodes.V1_8:
 			case Opcodes.V9:
+			case Opcodes.V10:
+			case Opcodes.V11:
+			case Opcodes.V11 | Opcodes.V_PREVIEW:
+			case Opcodes.V12:
+			case Opcodes.V12 | Opcodes.V_PREVIEW:
+			case (Opcodes.V12 + 1):
+			case (Opcodes.V12 + 1) | Opcodes.V_PREVIEW:
 				return CLASSFILE;
 			}
 		}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/InputStreams.java b/org.jacoco.core/src/org/jacoco/core/internal/InputStreams.java
index 7a77dd7..93f86f6 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/InputStreams.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/InputStreams.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/Pack200Streams.java b/org.jacoco.core/src/org/jacoco/core/internal/Pack200Streams.java
index abcbe98..eae4fdf 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/Pack200Streams.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/Pack200Streams.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors

+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/BundleCoverageImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/BundleCoverageImpl.java
index 5c1e39f..9c6fcef 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/BundleCoverageImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/BundleCoverageImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java
index afcf387..a18ee7e 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,22 +11,36 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis;
 
-import org.jacoco.core.analysis.IMethodCoverage;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.jacoco.core.internal.analysis.filter.Filters;
+import org.jacoco.core.internal.analysis.filter.IFilter;
+import org.jacoco.core.internal.analysis.filter.IFilterContext;
 import org.jacoco.core.internal.flow.ClassProbesVisitor;
 import org.jacoco.core.internal.flow.MethodProbesVisitor;
 import org.jacoco.core.internal.instr.InstrSupport;
+import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.tree.MethodNode;
 
 /**
  * Analyzes the structure of a class.
  */
-public class ClassAnalyzer extends ClassProbesVisitor {
+public class ClassAnalyzer extends ClassProbesVisitor
+		implements IFilterContext {
 
 	private final ClassCoverageImpl coverage;
 	private final boolean[] probes;
 	private final StringPool stringPool;
 
+	private final Set<String> classAnnotations = new HashSet<String>();
+
+	private String sourceDebugExtension;
+
+	private final IFilter filter;
+
 	/**
 	 * Creates a new analyzer that builds coverage data for a class.
 	 * 
@@ -42,6 +56,7 @@
 		this.coverage = coverage;
 		this.probes = probes;
 		this.stringPool = stringPool;
+		this.filter = Filters.all();
 	}
 
 	@Override
@@ -54,31 +69,57 @@
 	}
 
 	@Override
+	public AnnotationVisitor visitAnnotation(final String desc,
+			final boolean visible) {
+		classAnnotations.add(desc);
+		return super.visitAnnotation(desc, visible);
+	}
+
+	@Override
 	public void visitSource(final String source, final String debug) {
 		coverage.setSourceFileName(stringPool.get(source));
+		sourceDebugExtension = debug;
 	}
 
 	@Override
 	public MethodProbesVisitor visitMethod(final int access, final String name,
-			final String desc, final String signature, final String[] exceptions) {
+			final String desc, final String signature,
+			final String[] exceptions) {
 
 		InstrSupport.assertNotInstrumented(name, coverage.getName());
 
-		return new MethodAnalyzer(coverage.getName(), coverage.getSuperName(),
-				stringPool.get(name), stringPool.get(desc),
-				stringPool.get(signature), probes, Filters.ALL) {
+		final InstructionsBuilder builder = new InstructionsBuilder(probes);
+
+		return new MethodAnalyzer(builder) {
+
 			@Override
-			public void visitEnd() {
-				super.visitEnd();
-				final IMethodCoverage methodCoverage = getCoverage();
-				if (methodCoverage.getInstructionCounter().getTotalCount() > 0) {
-					// Only consider methods that actually contain code
-					coverage.addMethod(methodCoverage);
-				}
+			public void accept(final MethodNode methodNode,
+					final MethodVisitor methodVisitor) {
+				super.accept(methodNode, methodVisitor);
+				addMethodCoverage(stringPool.get(name), stringPool.get(desc),
+						stringPool.get(signature), builder, methodNode);
 			}
 		};
 	}
 
+	private void addMethodCoverage(final String name, final String desc,
+			final String signature, final InstructionsBuilder icc,
+			final MethodNode methodNode) {
+		final MethodCoverageCalculator mcc = new MethodCoverageCalculator(
+				icc.getInstructions());
+		filter.filter(methodNode, this, mcc);
+
+		final MethodCoverageImpl mc = new MethodCoverageImpl(name, desc,
+				signature);
+		mcc.calculate(mc);
+
+		if (mc.containsCode()) {
+			// Only consider methods that actually contain code
+			coverage.addMethod(mc);
+		}
+
+	}
+
 	@Override
 	public FieldVisitor visitField(final int access, final String name,
 			final String desc, final String signature, final Object value) {
@@ -91,4 +132,26 @@
 		// nothing to do
 	}
 
+	// IFilterContext implementation
+
+	public String getClassName() {
+		return coverage.getName();
+	}
+
+	public String getSuperClassName() {
+		return coverage.getSuperName();
+	}
+
+	public Set<String> getClassAnnotations() {
+		return classAnnotations;
+	}
+
+	public String getSourceFileName() {
+		return coverage.getSourceFileName();
+	}
+
+	public String getSourceDebugExtension() {
+		return sourceDebugExtension;
+	}
+
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java
index cb45604..444a81e 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -47,7 +47,6 @@
 		this.id = id;
 		this.noMatch = noMatch;
 		this.methods = new ArrayList<IMethodCoverage>();
-		this.classCounter = CounterImpl.COUNTER_1_0;
 	}
 
 	/**
@@ -59,10 +58,11 @@
 	public void addMethod(final IMethodCoverage method) {
 		this.methods.add(method);
 		increment(method);
-		// As class is considered as covered when at least one method is
-		// covered:
+		// Class is considered as covered when at least one method is covered:
 		if (methodCounter.getCoveredCount() > 0) {
 			this.classCounter = CounterImpl.COUNTER_0_1;
+		} else {
+			this.classCounter = CounterImpl.COUNTER_1_0;
 		}
 	}
 
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/CounterImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/CounterImpl.java
index 5d0317c..e166c62 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/CounterImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/CounterImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/Instruction.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/Instruction.java
new file mode 100644
index 0000000..c5a1aaa
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/Instruction.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import java.util.BitSet;
+import java.util.Collection;
+
+import org.jacoco.core.analysis.ICounter;
+
+/**
+ * Execution status of a single bytecode instruction internally used for
+ * coverage analysis. The execution status is recorded separately for each
+ * outgoing branch. Each instruction has at least one branch, for example in
+ * case of a simple sequence of instructions (by convention branch 0). Instances
+ * of this class are used in two steps:
+ * 
+ * <h3>Step 1: Building the CFG</h3>
+ * 
+ * For each bytecode instruction of a method a {@link Instruction} instance is
+ * created. In correspondence with the CFG these instances are linked with each
+ * other with the <code>addBranch()</code> methods. The executions status is
+ * either directly derived from a probe which has been inserted in the execution
+ * flow ({@link #addBranch(boolean, int)}) or indirectly propagated along the
+ * CFG edges ({@link #addBranch(Instruction, int)}).
+ * 
+ * <h3>Step 2: Querying the Coverage Status</h3>
+ * 
+ * After all instructions have been created and linked each instruction knows
+ * its execution status and can be queried with:
+ * 
+ * <ul>
+ * <li>{@link #getLine()}</li>
+ * <li>{@link #getInstructionCounter()}</li>
+ * <li>{@link #getBranchCounter()}</li>
+ * </ul>
+ * 
+ * For the purpose of filtering instructions can be combined to new
+ * instructions. Note that these methods create new {@link Instruction}
+ * instances and do not modify the existing ones.
+ * 
+ * <ul>
+ * <li>{@link #merge(Instruction)}</li>
+ * <li>{@link #replaceBranches(Collection)}</li>
+ * </ul>
+ */
+public class Instruction {
+
+	private final int line;
+
+	private int branches;
+
+	private final BitSet coveredBranches;
+
+	private Instruction predecessor;
+
+	private int predecessorBranch;
+
+	/**
+	 * New instruction at the given line.
+	 * 
+	 * @param line
+	 *            source line this instruction belongs to
+	 */
+	public Instruction(final int line) {
+		this.line = line;
+		this.branches = 0;
+		this.coveredBranches = new BitSet();
+	}
+
+	/**
+	 * Adds a branch to this instruction which execution status is indirectly
+	 * derived from the execution status of the target instruction. In case the
+	 * branch is covered the status is propagated also to the predecessors of
+	 * this instruction.
+	 * 
+	 * Note: This method is not idempotent and must be called exactly once for
+	 * every branch.
+	 * 
+	 * @param target
+	 *            target instruction of this branch
+	 * @param branch
+	 *            branch identifier unique for this instruction
+	 */
+	public void addBranch(final Instruction target, final int branch) {
+		branches++;
+		target.predecessor = this;
+		target.predecessorBranch = branch;
+		if (!target.coveredBranches.isEmpty()) {
+			propagateExecutedBranch(this, branch);
+		}
+	}
+
+	/**
+	 * Adds a branch to this instruction which execution status is directly
+	 * derived from a probe. In case the branch is covered the status is
+	 * propagated also to the predecessors of this instruction.
+	 * 
+	 * Note: This method is not idempotent and must be called exactly once for
+	 * every branch.
+	 * 
+	 * @param executed
+	 *            whether the corresponding probe has been executed
+	 * @param branch
+	 *            branch identifier unique for this instruction
+	 */
+	public void addBranch(final boolean executed, final int branch) {
+		branches++;
+		if (executed) {
+			propagateExecutedBranch(this, branch);
+		}
+	}
+
+	private static void propagateExecutedBranch(Instruction insn, int branch) {
+		// No recursion here, as there can be very long chains of instructions
+		while (insn != null) {
+			if (!insn.coveredBranches.isEmpty()) {
+				insn.coveredBranches.set(branch);
+				break;
+			}
+			insn.coveredBranches.set(branch);
+			branch = insn.predecessorBranch;
+			insn = insn.predecessor;
+		}
+	}
+
+	/**
+	 * Returns the source line this instruction belongs to.
+	 * 
+	 * @return corresponding source line
+	 */
+	public int getLine() {
+		return line;
+	}
+
+	/**
+	 * Merges information about covered branches of this instruction with
+	 * another instruction.
+	 * 
+	 * @param other
+	 *            instruction to merge with
+	 * @return new instance with merged branches
+	 */
+	public Instruction merge(final Instruction other) {
+		final Instruction result = new Instruction(this.line);
+		result.branches = this.branches;
+		result.coveredBranches.or(this.coveredBranches);
+		result.coveredBranches.or(other.coveredBranches);
+		return result;
+	}
+
+	/**
+	 * Creates a copy of this instruction where all outgoing branches are
+	 * replaced with the given instructions. The coverage status of the new
+	 * instruction is derived from the status of the given instructions.
+	 * 
+	 * @param newBranches
+	 *            new branches to consider
+	 * @return new instance with replaced branches
+	 */
+	public Instruction replaceBranches(
+			final Collection<Instruction> newBranches) {
+		final Instruction result = new Instruction(this.line);
+		result.branches = newBranches.size();
+		int idx = 0;
+		for (final Instruction b : newBranches) {
+			if (!b.coveredBranches.isEmpty()) {
+				result.coveredBranches.set(idx++);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Returns the instruction coverage counter of this instruction. It is
+	 * always 1 instruction which is covered or not.
+	 * 
+	 * @return the instruction coverage counter
+	 */
+	public ICounter getInstructionCounter() {
+		return coveredBranches.isEmpty() ? CounterImpl.COUNTER_1_0
+				: CounterImpl.COUNTER_0_1;
+	}
+
+	/**
+	 * Returns the branch coverage counter of this instruction. Only
+	 * instructions with at least 2 outgoing edges report branches.
+	 * 
+	 * @return the branch coverage counter
+	 */
+	public ICounter getBranchCounter() {
+		if (branches < 2) {
+			return CounterImpl.COUNTER_0_0;
+		}
+		final int covered = coveredBranches.cardinality();
+		return CounterImpl.getInstance(branches - covered, covered);
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/InstructionsBuilder.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/InstructionsBuilder.java
new file mode 100644
index 0000000..b22d872
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/InstructionsBuilder.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jacoco.core.analysis.ISourceNode;
+import org.jacoco.core.internal.flow.LabelInfo;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.tree.AbstractInsnNode;
+
+/**
+ * Stateful builder for the {@link Instruction}s of a method. All instructions
+ * of a method must be added in their original sequence along with additional
+ * information like line numbers. Afterwards the instructions can be obtained
+ * with the <code>getInstructions()</code> method.
+ */
+class InstructionsBuilder {
+
+	/** Probe array of the class the analyzed method belongs to. */
+	private final boolean[] probes;
+
+	/** The line which belong to subsequently added instructions. */
+	private int currentLine;
+
+	/** The last instruction which has been added. */
+	private Instruction currentInsn;
+
+	/**
+	 * All instructions of a method mapped from the ASM node to the
+	 * corresponding {@link Instruction} instance.
+	 */
+	private final Map<AbstractInsnNode, Instruction> instructions;
+
+	/**
+	 * The labels which mark the subsequent instructions.
+	 * 
+	 * Due to ASM issue #315745 there can be more than one label per instruction
+	 */
+	private final List<Label> currentLabel;
+
+	/**
+	 * List of all jumps within the control flow. We need to store jumps
+	 * temporarily as the target {@link Instruction} may not been known yet.
+	 */
+	private final List<Jump> jumps;
+
+	/**
+	 * Creates a new builder instance which can be used to analyze a single
+	 * method.
+	 * 
+	 * @param probes
+	 *            probe array of the corresponding class used to determine the
+	 *            coverage status of every instruction.
+	 */
+	InstructionsBuilder(final boolean[] probes) {
+		this.probes = probes;
+		this.currentLine = ISourceNode.UNKNOWN_LINE;
+		this.currentInsn = null;
+		this.instructions = new HashMap<AbstractInsnNode, Instruction>();
+		this.currentLabel = new ArrayList<Label>(2);
+		this.jumps = new ArrayList<Jump>();
+	}
+
+	/**
+	 * Sets the current source line. All subsequently added instructions will be
+	 * assigned to this line. If no line is set (e.g. for classes compiled
+	 * without debug information) {@link ISourceNode#UNKNOWN_LINE} is assigned
+	 * to the instructions.
+	 */
+	void setCurrentLine(final int line) {
+		currentLine = line;
+	}
+
+	/**
+	 * Adds a label which applies to the subsequently added instruction. Due to
+	 * ASM internals multiple {@link Label}s can be added to an instruction.
+	 */
+	void addLabel(final Label label) {
+		currentLabel.add(label);
+		if (!LabelInfo.isSuccessor(label)) {
+			noSuccessor();
+		}
+	}
+
+	/**
+	 * Adds a new instruction. Instructions are by default linked with the
+	 * previous instruction unless specified otherwise.
+	 */
+	void addInstruction(final AbstractInsnNode node) {
+		final Instruction insn = new Instruction(currentLine);
+		final int labelCount = currentLabel.size();
+		if (labelCount > 0) {
+			for (int i = labelCount; --i >= 0;) {
+				LabelInfo.setInstruction(currentLabel.get(i), insn);
+			}
+			currentLabel.clear();
+		}
+		if (currentInsn != null) {
+			currentInsn.addBranch(insn, 0);
+		}
+		currentInsn = insn;
+		instructions.put(node, insn);
+	}
+
+	/**
+	 * Declares that the next instruction will not be a successor of the current
+	 * instruction. This is the case with an unconditional jump or technically
+	 * when a probe was inserted before.
+	 */
+	void noSuccessor() {
+		currentInsn = null;
+	}
+
+	/**
+	 * Adds a jump from the last added instruction.
+	 * 
+	 * @param target
+	 *            jump target
+	 * @param branch
+	 *            unique branch number
+	 */
+	void addJump(final Label target, final int branch) {
+		jumps.add(new Jump(currentInsn, target, branch));
+	}
+
+	/**
+	 * Adds a new probe for the last instruction.
+	 * 
+	 * @param probeId
+	 *            index in the probe array
+	 * @param branch
+	 *            unique branch number for the last instruction
+	 */
+	void addProbe(final int probeId, final int branch) {
+		final boolean executed = probes != null && probes[probeId];
+		currentInsn.addBranch(executed, branch);
+	}
+
+	/**
+	 * Returns the status for all instructions of this method. This method must
+	 * be called exactly once after the instructions have been added.
+	 * 
+	 * @return map of ASM instruction nodes to corresponding {@link Instruction}
+	 *         instances
+	 */
+	Map<AbstractInsnNode, Instruction> getInstructions() {
+		// Wire jumps:
+		for (final Jump j : jumps) {
+			j.wire();
+		}
+
+		return instructions;
+	}
+
+	private static class Jump {
+
+		private final Instruction source;
+		private final Label target;
+		private final int branch;
+
+		Jump(final Instruction source, final Label target, final int branch) {
+			this.source = source;
+			this.target = target;
+			this.branch = branch;
+		}
+
+		void wire() {
+			source.addBranch(LabelInfo.getInstruction(target), branch);
+		}
+
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java
index 9c03ea7..908bcb6 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/LineImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java
index e10e5d9..1aaadf2 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodAnalyzer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,20 +11,7 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.jacoco.core.analysis.ICounter;
-import org.jacoco.core.analysis.IMethodCoverage;
-import org.jacoco.core.analysis.ISourceNode;
-import org.jacoco.core.internal.analysis.filter.IFilter;
-import org.jacoco.core.internal.analysis.filter.IFilterOutput;
 import org.jacoco.core.internal.flow.IFrame;
-import org.jacoco.core.internal.flow.Instruction;
 import org.jacoco.core.internal.flow.LabelInfo;
 import org.jacoco.core.internal.flow.MethodProbesVisitor;
 import org.objectweb.asm.Handle;
@@ -35,91 +22,26 @@
 import org.objectweb.asm.tree.TryCatchBlockNode;
 
 /**
- * A {@link MethodProbesVisitor} that analyzes which statements and branches of
- * a method have been executed based on given probe data.
+ * A {@link MethodProbesVisitor} that builds the {@link Instruction}s of a
+ * method to calculate the detailed execution status.
  */
-public class MethodAnalyzer extends MethodProbesVisitor
-		implements IFilterOutput {
+public class MethodAnalyzer extends MethodProbesVisitor {
 
-	private final String className;
+	private final InstructionsBuilder builder;
 
-	private final String superClassName;
-
-	private final boolean[] probes;
-
-	private final IFilter filter;
-
-	private final MethodCoverageImpl coverage;
-
-	private int currentLine = ISourceNode.UNKNOWN_LINE;
-
-	private int firstLine = ISourceNode.UNKNOWN_LINE;
-
-	private int lastLine = ISourceNode.UNKNOWN_LINE;
-
-	// Due to ASM issue #315745 there can be more than one label per instruction
-	private final List<Label> currentLabel = new ArrayList<Label>(2);
-
-	/** List of all analyzed instructions */
-	private final List<Instruction> instructions = new ArrayList<Instruction>();
-
-	/** List of all predecessors of covered probes */
-	private final List<CoveredProbe> coveredProbes = new ArrayList<CoveredProbe>();
-
-	/** List of all jumps encountered */
-	private final List<Jump> jumps = new ArrayList<Jump>();
-
-	/** Last instruction in byte code sequence */
-	private Instruction lastInsn;
+	/** Current node of the ASM tree API */
+	private AbstractInsnNode currentNode;
 
 	/**
-	 * New Method analyzer for the given probe data.
-	 * 
-	 * @param className
-	 *            class name
-	 * @param superClassName
-	 *            superclass name
-	 * @param name
-	 *            method name
-	 * @param desc
-	 *            method descriptor
-	 * @param signature
-	 *            optional parameterized signature
-	 * @param probes
-	 *            recorded probe date of the containing class or
-	 *            <code>null</code> if the class is not executed at all
-	 * @param filter
-	 *            filter
+	 * New instance that uses the given builder.
 	 */
-	MethodAnalyzer(final String className, final String superClassName,
-			final String name, final String desc, final String signature,
-			final boolean[] probes, final IFilter filter) {
-		super();
-		this.className = className;
-		this.superClassName = superClassName;
-		this.probes = probes;
-		this.filter = filter;
-		this.coverage = new MethodCoverageImpl(name, desc, signature);
+	MethodAnalyzer(final InstructionsBuilder builder) {
+		this.builder = builder;
 	}
 
-	/**
-	 * Returns the coverage data for this method after this visitor has been
-	 * processed.
-	 * 
-	 * @return coverage data for this method
-	 */
-	public IMethodCoverage getCoverage() {
-		return coverage;
-	}
-
-	/**
-	 * {@link MethodNode#accept(MethodVisitor)}
-	 */
 	@Override
 	public void accept(final MethodNode methodNode,
 			final MethodVisitor methodVisitor) {
-		filter.filter(className, superClassName, methodNode, this);
-
 		methodVisitor.visitCode();
 		for (final TryCatchBlockNode n : methodNode.tryCatchBlocks) {
 			n.accept(methodVisitor);
@@ -132,139 +54,68 @@
 		methodVisitor.visitEnd();
 	}
 
-	private final Set<AbstractInsnNode> ignored = new HashSet<AbstractInsnNode>();
-
-	/**
-	 * Instructions that should be merged form disjoint sets. Coverage
-	 * information from instructions of one set will be merged into
-	 * representative instruction of set.
-	 * 
-	 * Each such set is represented as a singly linked list: each element except
-	 * one references another element from the same set, element without
-	 * reference - is a representative of this set.
-	 * 
-	 * This map stores reference (value) for elements of sets (key).
-	 */
-	private final Map<AbstractInsnNode, AbstractInsnNode> merged = new HashMap<AbstractInsnNode, AbstractInsnNode>();
-
-	private final Map<AbstractInsnNode, Instruction> nodeToInstruction = new HashMap<AbstractInsnNode, Instruction>();
-
-	private AbstractInsnNode currentNode;
-
-	public void ignore(final AbstractInsnNode fromInclusive,
-			final AbstractInsnNode toInclusive) {
-		for (AbstractInsnNode i = fromInclusive; i != toInclusive; i = i
-				.getNext()) {
-			ignored.add(i);
-		}
-		ignored.add(toInclusive);
-	}
-
-	private AbstractInsnNode findRepresentative(AbstractInsnNode i) {
-		AbstractInsnNode r = merged.get(i);
-		while (r != null) {
-			i = r;
-			r = merged.get(i);
-		}
-		return i;
-	}
-
-	public void merge(AbstractInsnNode i1, AbstractInsnNode i2) {
-		i1 = findRepresentative(i1);
-		i2 = findRepresentative(i2);
-		if (i1 != i2) {
-			merged.put(i2, i1);
-		}
-	}
-
 	@Override
 	public void visitLabel(final Label label) {
-		currentLabel.add(label);
-		if (!LabelInfo.isSuccessor(label)) {
-			lastInsn = null;
-		}
+		builder.addLabel(label);
 	}
 
 	@Override
 	public void visitLineNumber(final int line, final Label start) {
-		currentLine = line;
-		if (firstLine > line || lastLine == ISourceNode.UNKNOWN_LINE) {
-			firstLine = line;
-		}
-		if (lastLine < line) {
-			lastLine = line;
-		}
-	}
-
-	private void visitInsn() {
-		final Instruction insn = new Instruction(currentNode, currentLine);
-		nodeToInstruction.put(currentNode, insn);
-		instructions.add(insn);
-		if (lastInsn != null) {
-			insn.setPredecessor(lastInsn, 0);
-		}
-		final int labelCount = currentLabel.size();
-		if (labelCount > 0) {
-			for (int i = labelCount; --i >= 0;) {
-				LabelInfo.setInstruction(currentLabel.get(i), insn);
-			}
-			currentLabel.clear();
-		}
-		lastInsn = insn;
+		builder.setCurrentLine(line);
 	}
 
 	@Override
 	public void visitInsn(final int opcode) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitIntInsn(final int opcode, final int operand) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitVarInsn(final int opcode, final int var) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitTypeInsn(final int opcode, final String type) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitFieldInsn(final int opcode, final String owner,
 			final String name, final String desc) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitMethodInsn(final int opcode, final String owner,
 			final String name, final String desc, final boolean itf) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitInvokeDynamicInsn(final String name, final String desc,
 			final Handle bsm, final Object... bsmArgs) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitJumpInsn(final int opcode, final Label label) {
-		visitInsn();
-		jumps.add(new Jump(lastInsn, label, 1));
+		builder.addInstruction(currentNode);
+		builder.addJump(label, 1);
 	}
 
 	@Override
 	public void visitLdcInsn(final Object cst) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitIincInsn(final int var, final int increment) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
@@ -280,15 +131,15 @@
 	}
 
 	private void visitSwitchInsn(final Label dflt, final Label[] labels) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 		LabelInfo.resetDone(labels);
 		int branch = 0;
-		jumps.add(new Jump(lastInsn, dflt, branch));
+		builder.addJump(dflt, branch);
 		LabelInfo.setDone(dflt);
 		for (final Label l : labels) {
 			if (!LabelInfo.isDone(l)) {
 				branch++;
-				jumps.add(new Jump(lastInsn, l, branch));
+				builder.addJump(l, branch);
 				LabelInfo.setDone(l);
 			}
 		}
@@ -296,26 +147,26 @@
 
 	@Override
 	public void visitMultiANewArrayInsn(final String desc, final int dims) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 	}
 
 	@Override
 	public void visitProbe(final int probeId) {
-		addProbe(probeId, 0);
-		lastInsn = null;
+		builder.addProbe(probeId, 0);
+		builder.noSuccessor();
 	}
 
 	@Override
 	public void visitJumpInsnWithProbe(final int opcode, final Label label,
 			final int probeId, final IFrame frame) {
-		visitInsn();
-		addProbe(probeId, 1);
+		builder.addInstruction(currentNode);
+		builder.addProbe(probeId, 1);
 	}
 
 	@Override
 	public void visitInsnWithProbe(final int opcode, final int probeId) {
-		visitInsn();
-		addProbe(probeId, 0);
+		builder.addInstruction(currentNode);
+		builder.addProbe(probeId, 0);
 	}
 
 	@Override
@@ -332,7 +183,7 @@
 
 	private void visitSwitchInsnWithProbes(final Label dflt,
 			final Label[] labels) {
-		visitInsn();
+		builder.addInstruction(currentNode);
 		LabelInfo.resetDone(dflt);
 		LabelInfo.resetDone(labels);
 		int branch = 0;
@@ -347,81 +198,12 @@
 		final int id = LabelInfo.getProbeId(label);
 		if (!LabelInfo.isDone(label)) {
 			if (id == LabelInfo.NO_PROBE) {
-				jumps.add(new Jump(lastInsn, label, branch));
+				builder.addJump(label, branch);
 			} else {
-				addProbe(id, branch);
+				builder.addProbe(id, branch);
 			}
 			LabelInfo.setDone(label);
 		}
 	}
 
-	@Override
-	public void visitEnd() {
-		// Wire jumps:
-		for (final Jump j : jumps) {
-			LabelInfo.getInstruction(j.target).setPredecessor(j.source,
-					j.branch);
-		}
-		// Propagate probe values:
-		for (final CoveredProbe p : coveredProbes) {
-			p.instruction.setCovered(p.branch);
-		}
-		// Merge:
-		for (final Instruction i : instructions) {
-			final AbstractInsnNode m = i.getNode();
-			final AbstractInsnNode r = findRepresentative(m);
-			if (r != m) {
-				ignored.add(m);
-				nodeToInstruction.get(r).merge(i);
-			}
-		}
-		// Report result:
-		coverage.ensureCapacity(firstLine, lastLine);
-		for (final Instruction i : instructions) {
-			if (ignored.contains(i.getNode())) {
-				continue;
-			}
-
-			final int total = i.getBranches();
-			final int covered = i.getCoveredBranches();
-			final ICounter instrCounter = covered == 0 ? CounterImpl.COUNTER_1_0
-					: CounterImpl.COUNTER_0_1;
-			final ICounter branchCounter = total > 1
-					? CounterImpl.getInstance(total - covered, covered)
-					: CounterImpl.COUNTER_0_0;
-			coverage.increment(instrCounter, branchCounter, i.getLine());
-		}
-		coverage.incrementMethodCounter();
-	}
-
-	private void addProbe(final int probeId, final int branch) {
-		lastInsn.addBranch();
-		if (probes != null && probes[probeId]) {
-			coveredProbes.add(new CoveredProbe(lastInsn, branch));
-		}
-	}
-
-	private static class CoveredProbe {
-		final Instruction instruction;
-		final int branch;
-
-		private CoveredProbe(final Instruction instruction, final int branch) {
-			this.instruction = instruction;
-			this.branch = branch;
-		}
-	}
-
-	private static class Jump {
-
-		final Instruction source;
-		final Label target;
-		final int branch;
-
-		Jump(final Instruction source, final Label target, final int branch) {
-			this.source = source;
-			this.target = target;
-			this.branch = branch;
-		}
-	}
-
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageCalculator.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageCalculator.java
new file mode 100644
index 0000000..ebe167a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageCalculator.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.jacoco.core.analysis.ISourceFileCoverage;
+import org.jacoco.core.analysis.ISourceNode;
+import org.jacoco.core.internal.analysis.filter.IFilterOutput;
+import org.objectweb.asm.tree.AbstractInsnNode;
+
+/**
+ * Calculates the filtered coverage of a single method. A instance of this class
+ * can be first used as {@link IFilterOutput} before the coverage result is
+ * calculated.
+ */
+class MethodCoverageCalculator implements IFilterOutput {
+
+	private final Map<AbstractInsnNode, Instruction> instructions;
+
+	private final Set<AbstractInsnNode> ignored;
+
+	/**
+	 * Instructions that should be merged form disjoint sets. Coverage
+	 * information from instructions of one set will be merged into
+	 * representative instruction of set.
+	 * 
+	 * Each such set is represented as a singly linked list: each element except
+	 * one references another element from the same set, element without
+	 * reference - is a representative of this set.
+	 * 
+	 * This map stores reference (value) for elements of sets (key).
+	 */
+	private final Map<AbstractInsnNode, AbstractInsnNode> merged;
+
+	private final Map<AbstractInsnNode, Set<AbstractInsnNode>> replacements;
+
+	MethodCoverageCalculator(
+			final Map<AbstractInsnNode, Instruction> instructions) {
+		this.instructions = instructions;
+		this.ignored = new HashSet<AbstractInsnNode>();
+		this.merged = new HashMap<AbstractInsnNode, AbstractInsnNode>();
+		this.replacements = new HashMap<AbstractInsnNode, Set<AbstractInsnNode>>();
+	}
+
+	/**
+	 * Applies all specified filtering commands and calculates the resulting
+	 * coverage.
+	 * 
+	 * @param coverage
+	 *            the result is added to this coverage node
+	 */
+	void calculate(final MethodCoverageImpl coverage) {
+		applyMerges();
+		applyReplacements();
+		ensureCapacity(coverage);
+
+		for (final Entry<AbstractInsnNode, Instruction> entry : instructions
+				.entrySet()) {
+			if (!ignored.contains(entry.getKey())) {
+				final Instruction instruction = entry.getValue();
+				coverage.increment(instruction.getInstructionCounter(),
+						instruction.getBranchCounter(), instruction.getLine());
+			}
+		}
+
+		coverage.incrementMethodCounter();
+	}
+
+	private void applyMerges() {
+		// Merge to the representative:
+		for (final Entry<AbstractInsnNode, AbstractInsnNode> entry : merged
+				.entrySet()) {
+			final AbstractInsnNode node = entry.getKey();
+			final Instruction instruction = instructions.get(node);
+			final AbstractInsnNode representativeNode = findRepresentative(
+					node);
+			ignored.add(node);
+			instructions.put(representativeNode,
+					instructions.get(representativeNode).merge(instruction));
+			entry.setValue(representativeNode);
+		}
+
+		// Get merged value back from representative
+		for (final Entry<AbstractInsnNode, AbstractInsnNode> entry : merged
+				.entrySet()) {
+			instructions.put(entry.getKey(),
+					instructions.get(entry.getValue()));
+		}
+	}
+
+	private void applyReplacements() {
+		for (final Entry<AbstractInsnNode, Set<AbstractInsnNode>> entry : replacements
+				.entrySet()) {
+			final Set<AbstractInsnNode> replacements = entry.getValue();
+			final List<Instruction> newBranches = new ArrayList<Instruction>(
+					replacements.size());
+			for (final AbstractInsnNode b : replacements) {
+				newBranches.add(instructions.get(b));
+			}
+			final AbstractInsnNode node = entry.getKey();
+			instructions.put(node,
+					instructions.get(node).replaceBranches(newBranches));
+		}
+	}
+
+	private void ensureCapacity(final MethodCoverageImpl coverage) {
+		// Determine line range:
+		int firstLine = ISourceFileCoverage.UNKNOWN_LINE;
+		int lastLine = ISourceFileCoverage.UNKNOWN_LINE;
+		for (final Entry<AbstractInsnNode, Instruction> entry : instructions
+				.entrySet()) {
+			if (!ignored.contains(entry.getKey())) {
+				final int line = entry.getValue().getLine();
+				if (line != ISourceNode.UNKNOWN_LINE) {
+					if (firstLine > line
+							|| lastLine == ISourceNode.UNKNOWN_LINE) {
+						firstLine = line;
+					}
+					if (lastLine < line) {
+						lastLine = line;
+					}
+				}
+			}
+		}
+
+		// Performance optimization to avoid incremental increase of line array:
+		coverage.ensureCapacity(firstLine, lastLine);
+	}
+
+	private AbstractInsnNode findRepresentative(AbstractInsnNode i) {
+		AbstractInsnNode r;
+		while ((r = merged.get(i)) != null) {
+			i = r;
+		}
+		return i;
+	}
+
+	// === IFilterOutput API ===
+
+	public void ignore(final AbstractInsnNode fromInclusive,
+			final AbstractInsnNode toInclusive) {
+		for (AbstractInsnNode i = fromInclusive; i != toInclusive; i = i
+				.getNext()) {
+			ignored.add(i);
+		}
+		ignored.add(toInclusive);
+	}
+
+	public void merge(AbstractInsnNode i1, AbstractInsnNode i2) {
+		i1 = findRepresentative(i1);
+		i2 = findRepresentative(i2);
+		if (i1 != i2) {
+			merged.put(i2, i1);
+		}
+	}
+
+	public void replaceBranches(final AbstractInsnNode source,
+			final Set<AbstractInsnNode> newTargets) {
+		replacements.put(source, newTargets);
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java
index 1e09129..aa7dccf 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/MethodCoverageImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/PackageCoverageImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/PackageCoverageImpl.java
index 4f92fc7..285ddd3 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/PackageCoverageImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/PackageCoverageImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceFileCoverageImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceFileCoverageImpl.java
index e689e5b..dc4483f 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceFileCoverageImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceFileCoverageImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
index 6aa241c..3fa3d69 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/SourceNodeImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/StringPool.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/StringPool.java
index a2e8d70..97e25aa 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/StringPool.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/StringPool.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractAnnotatedMethodFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractAnnotatedMethodFilter.java
deleted file mode 100644
index 76b6b2f..0000000
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractAnnotatedMethodFilter.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.internal.analysis.filter;
-
-import java.util.List;
-
-import org.objectweb.asm.tree.AnnotationNode;
-import org.objectweb.asm.tree.MethodNode;
-
-/**
- * Filters annotated methods.
- */
-abstract class AbstractAnnotatedMethodFilter implements IFilter {
-	private final String descType;
-
-	/**
-	 * Configures a new filter instance.
-	 * 
-	 * @param annotationType
-	 *            VM type of the annotation
-	 */
-	protected AbstractAnnotatedMethodFilter(final String annotationType) {
-		this.descType = "L" + annotationType + ";";
-	}
-
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
-		if (hasAnnotation(methodNode)) {
-			output.ignore(methodNode.instructions.getFirst(),
-					methodNode.instructions.getLast());
-		}
-	}
-
-	private boolean hasAnnotation(final MethodNode methodNode) {
-		final List<AnnotationNode> annotations = getAnnotations(methodNode);
-		if (annotations != null) {
-			for (final AnnotationNode annotation : annotations) {
-				if (descType.equals(annotation.desc)) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Retrieves the annotations to search from a method. Depending on the
-	 * retention of the annotation this is either
-	 * <code>visibleAnnotations</code> or <code>invisibleAnnotations</code>.
-	 * 
-	 * @param methodNode
-	 *            method to retrieve annotations from
-	 * @return list of annotations
-	 */
-	abstract List<AnnotationNode> getAnnotations(final MethodNode methodNode);
-
-}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractMatcher.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractMatcher.java
index b5aea72..38860a8 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractMatcher.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AbstractMatcher.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -17,6 +17,8 @@
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TypeInsnNode;
 import org.objectweb.asm.tree.VarInsnNode;
 
 abstract class AbstractMatcher {
@@ -25,13 +27,49 @@
 
 	AbstractInsnNode cursor;
 
-	final void nextIsInvokeVirtual(final String owner, final String name) {
-		nextIs(Opcodes.INVOKEVIRTUAL);
+	/**
+	 * Sets {@link #cursor} to first instruction of method if it is
+	 * <code>ALOAD 0</code>, otherwise sets it to <code>null</code>.
+	 */
+	final void firstIsALoad0(final MethodNode methodNode) {
+		cursor = methodNode.instructions.getFirst();
+		skipNonOpcodes();
+		if (cursor.getOpcode() == Opcodes.ALOAD
+				&& ((VarInsnNode) cursor).var == 0) {
+			return;
+		}
+		cursor = null;
+	}
+
+	/**
+	 * Moves {@link #cursor} to next instruction if it is {@link TypeInsnNode}
+	 * with given opcode and operand, otherwise sets it to <code>null</code>.
+	 */
+	final void nextIsType(final int opcode, final String desc) {
+		nextIs(opcode);
+		if (cursor == null) {
+			return;
+		}
+		if (((TypeInsnNode) cursor).desc.equals(desc)) {
+			return;
+		}
+		cursor = null;
+	}
+
+	/**
+	 * Moves {@link #cursor} to next instruction if it is {@link MethodInsnNode}
+	 * with given opcode, owner, name and descriptor, otherwise sets it to
+	 * <code>null</code>.
+	 */
+	final void nextIsInvoke(final int opcode, final String owner,
+			final String name, final String descriptor) {
+		nextIs(opcode);
 		if (cursor == null) {
 			return;
 		}
 		final MethodInsnNode m = (MethodInsnNode) cursor;
-		if (owner.equals(m.owner) && name.equals(m.name)) {
+		if (owner.equals(m.owner) && name.equals(m.name)
+				&& descriptor.equals(m.desc)) {
 			return;
 		}
 		cursor = null;
@@ -52,6 +90,25 @@
 	}
 
 	/**
+	 * Moves {@link #cursor} to next instruction if it is
+	 * <code>TABLESWITCH</code> or <code>LOOKUPSWITCH</code>, otherwise sets it
+	 * to <code>null</code>.
+	 */
+	final void nextIsSwitch() {
+		next();
+		if (cursor == null) {
+			return;
+		}
+		switch (cursor.getOpcode()) {
+		case Opcodes.TABLESWITCH:
+		case Opcodes.LOOKUPSWITCH:
+			return;
+		default:
+			cursor = null;
+		}
+	}
+
+	/**
 	 * Moves {@link #cursor} to next instruction if it has given opcode,
 	 * otherwise sets it to <code>null</code>.
 	 */
@@ -76,12 +133,26 @@
 		skipNonOpcodes();
 	}
 
+	/**
+	 * Moves {@link #cursor} through {@link AbstractInsnNode#FRAME},
+	 * {@link AbstractInsnNode#LABEL}, {@link AbstractInsnNode#LINE}.
+	 */
 	final void skipNonOpcodes() {
+		cursor = skipNonOpcodes(cursor);
+	}
+
+	/**
+	 * Returns first instruction from given and following it that is not
+	 * {@link AbstractInsnNode#FRAME}, {@link AbstractInsnNode#LABEL},
+	 * {@link AbstractInsnNode#LINE}.
+	 */
+	static AbstractInsnNode skipNonOpcodes(AbstractInsnNode cursor) {
 		while (cursor != null && (cursor.getType() == AbstractInsnNode.FRAME
 				|| cursor.getType() == AbstractInsnNode.LABEL
 				|| cursor.getType() == AbstractInsnNode.LINE)) {
 			cursor = cursor.getNext();
 		}
+		return cursor;
 	}
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java
new file mode 100644
index 0000000..d78444c
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/AnnotationGeneratedFilter.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.List;
+
+import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters classes and methods annotated with
+ * {@link java.lang.annotation.RetentionPolicy#RUNTIME runtime visible} and
+ * {@link java.lang.annotation.RetentionPolicy#CLASS invisible} annotation whose
+ * simple name contains <code>Generated</code>.
+ */
+public final class AnnotationGeneratedFilter implements IFilter {
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+
+		for (String annotation : context.getClassAnnotations()) {
+			if (matches(annotation)) {
+				output.ignore(methodNode.instructions.getFirst(),
+						methodNode.instructions.getLast());
+				return;
+			}
+		}
+
+		if (presentIn(methodNode.invisibleAnnotations)
+				|| presentIn(methodNode.visibleAnnotations)) {
+			output.ignore(methodNode.instructions.getFirst(),
+					methodNode.instructions.getLast());
+		}
+
+	}
+
+	private static boolean matches(final String annotation) {
+		final String name = annotation
+				.substring(Math.max(annotation.lastIndexOf('/'),
+						annotation.lastIndexOf('$')) + 1);
+		return name.contains("Generated");
+	}
+
+	private static boolean presentIn(final List<AnnotationNode> annotations) {
+		if (annotations != null) {
+			for (AnnotationNode annotation : annotations) {
+				if (matches(annotation.desc)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilter.java
new file mode 100644
index 0000000..4a39d1e
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumEmptyConstructorFilter.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters empty enum constructors.
+ *
+ * Constructor of enum is invoked from static initialization block to create
+ * instance of each enum constant. So it won't be executed if number of enum
+ * constants is zero. Such enums are sometimes used as alternative to classes
+ * with static utilities and private empty constructor. Implicit constructor of
+ * enum created by compiler doesn't have a synthetic flag and refers to a line
+ * of enum definition. Therefore in order to not have partial coverage of enum
+ * definition line in enums without enum constants and similarly to
+ * {@link PrivateEmptyNoArgConstructorFilter filter of private empty
+ * constructors} - empty constructor in enums without additional parameters
+ * should be filtered out even if it is not implicit.
+ */
+public final class EnumEmptyConstructorFilter implements IFilter {
+
+	private static final String CONSTRUCTOR_NAME = "<init>";
+	private static final String CONSTRUCTOR_DESC = "(Ljava/lang/String;I)V";
+
+	private static final String ENUM_TYPE = "java/lang/Enum";
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		if (ENUM_TYPE.equals(context.getSuperClassName())
+				&& CONSTRUCTOR_NAME.equals(methodNode.name)
+				&& CONSTRUCTOR_DESC.equals(methodNode.desc)
+				&& new Matcher().match(methodNode)) {
+			output.ignore(methodNode.instructions.getFirst(),
+					methodNode.instructions.getLast());
+		}
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		private boolean match(final MethodNode methodNode) {
+			firstIsALoad0(methodNode);
+			nextIs(Opcodes.ALOAD);
+			nextIs(Opcodes.ILOAD);
+			nextIsInvoke(Opcodes.INVOKESPECIAL, ENUM_TYPE, CONSTRUCTOR_NAME,
+					CONSTRUCTOR_DESC);
+			nextIs(Opcodes.RETURN);
+			return cursor != null;
+		}
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java
index c5f1784..0c2eef5 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/EnumFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -19,9 +19,10 @@
  */
 public final class EnumFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
-		if (isMethodFiltered(className, superClassName, methodNode.name,
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		if (isMethodFiltered(context.getClassName(),
+				context.getSuperClassName(), methodNode.name,
 				methodNode.desc)) {
 			output.ignore(methodNode.instructions.getFirst(),
 					methodNode.instructions.getLast());
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java
index 0f34418..7a1053b 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -23,26 +23,38 @@
 	 */
 	public static final IFilter NONE = new Filters();
 
-	/**
-	 * Filter that combines all other filters.
-	 */
-	public static final IFilter ALL = new Filters(new EnumFilter(),
-			new SyntheticFilter(), new SynchronizedFilter(),
-			new TryWithResourcesJavacFilter(), new TryWithResourcesEcjFilter(),
-			new FinallyFilter(), new PrivateEmptyNoArgConstructorFilter(),
-			new StringSwitchJavacFilter(), new LombokGeneratedFilter(),
-			new GroovyGeneratedFilter());
-
 	private final IFilter[] filters;
 
+	/**
+	 * Creates filter that combines all other filters.
+	 * 
+	 * @return filter that combines all other filters
+	 */
+	public static IFilter all() {
+		return new Filters(new EnumFilter(), new SyntheticFilter(),
+				new SynchronizedFilter(), new TryWithResourcesJavac11Filter(),
+				new TryWithResourcesJavacFilter(),
+				new TryWithResourcesEcjFilter(), new FinallyFilter(),
+				new PrivateEmptyNoArgConstructorFilter(),
+				new StringSwitchJavacFilter(), new StringSwitchEcjFilter(),
+				new EnumEmptyConstructorFilter(),
+				new AnnotationGeneratedFilter(), new KotlinGeneratedFilter(),
+				new KotlinLateinitFilter(), new KotlinWhenFilter(),
+				new KotlinWhenStringFilter(),
+				new KotlinUnsafeCastOperatorFilter(),
+				new KotlinNotNullOperatorFilter(),
+				new KotlinDefaultArgumentsFilter(), new KotlinInlineFilter(),
+				new KotlinCoroutineFilter());
+	}
+
 	private Filters(final IFilter... filters) {
 		this.filters = filters;
 	}
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
 		for (final IFilter filter : filters) {
-			filter.filter(className, superClassName, methodNode, output);
+			filter.filter(methodNode, context, output);
 		}
 	}
 
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java
index 830d0c2..b2e0b14 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/FinallyFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -67,8 +67,8 @@
  */
 public final class FinallyFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
 		for (final TryCatchBlockNode tryCatchBlock : methodNode.tryCatchBlocks) {
 			if (tryCatchBlock.type == null) {
 				filter(output, methodNode.tryCatchBlocks, tryCatchBlock);
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilter.java
deleted file mode 100644
index 816cc4c..0000000
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/GroovyGeneratedFilter.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.internal.analysis.filter;
-
-import java.util.List;
-
-import org.objectweb.asm.tree.AnnotationNode;
-import org.objectweb.asm.tree.MethodNode;
-
-/**
- * Filters methods annotated with <code>@groovy.transform.Generated</code>.
- */
-public final class GroovyGeneratedFilter extends AbstractAnnotatedMethodFilter {
-
-	/**
-	 * New filter.
-	 */
-	public GroovyGeneratedFilter() {
-		super("groovy/transform/Generated");
-	}
-
-	@Override
-	List<AnnotationNode> getAnnotations(final MethodNode methodNode) {
-		return methodNode.visibleAnnotations;
-	}
-
-}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilter.java
index 82b7959..b662ba4 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,8 +14,8 @@
 import org.objectweb.asm.tree.MethodNode;
 
 /**
- * Interface for filter implementations. Instances of filters are reused and so
- * must be stateless.
+ * Interface for filter implementations. Instances of filters are created for
+ * analysis of each class and so can have per-class state.
  */
 public interface IFilter {
 
@@ -24,16 +24,13 @@
 	 * expected to inspect the provided method and report its result to the
 	 * given {@link IFilterOutput} instance.
 	 *
-	 * @param className
-	 *            class name
-	 * @param superClassName
-	 *            superclass name
 	 * @param methodNode
 	 *            method to inspect
+	 * @param context
+	 *            context information for the method
 	 * @param output
 	 *            callback to report filtering results to
 	 */
-	void filter(String className, String superClassName, MethodNode methodNode,
+	void filter(MethodNode methodNode, IFilterContext context,
 			IFilterOutput output);
-
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterContext.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterContext.java
new file mode 100644
index 0000000..8b97654
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterContext.java
@@ -0,0 +1,48 @@
+/*******************************************************************************

+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *

+ *******************************************************************************/

+package org.jacoco.core.internal.analysis.filter;

+

+import java.util.Set;

+

+/**

+ * Context information provided to filters.

+ */

+public interface IFilterContext {

+

+	/**

+	 * @return vm name of the enclosing class

+	 */

+	String getClassName();

+

+	/**

+	 * @return vm name of the super class of the enclosing class

+	 */

+	String getSuperClassName();

+

+	/**

+	 * @return vm names of the class annotations of the enclosing class

+	 */

+	Set<String> getClassAnnotations();

+

+	/**

+	 * @return file name of the corresponding source file or <code>null</code>

+	 *         if not available

+	 */

+	String getSourceFileName();

+

+	/**

+	 * @return value of SourceDebugExtension attribute or <code>null</code> if

+	 *         not available

+	 */

+	String getSourceDebugExtension();

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java
index 4ca9b81..0f02220 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/IFilterOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,8 @@
  *******************************************************************************/
 package org.jacoco.core.internal.analysis.filter;
 
+import java.util.Set;
+
 import org.objectweb.asm.tree.AbstractInsnNode;
 
 /**
@@ -41,4 +43,16 @@
 	 */
 	void merge(AbstractInsnNode i1, AbstractInsnNode i2);
 
+	/**
+	 * Marks instruction whose outgoing branches should be replaced during
+	 * computation of coverage.
+	 *
+	 * @param source
+	 *            instruction which branches should be replaced
+	 * @param newTargets
+	 *            new targets of branches
+	 */
+	void replaceBranches(AbstractInsnNode source,
+			Set<AbstractInsnNode> newTargets);
+
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
new file mode 100644
index 0000000..66d450a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TableSwitchInsnNode;
+
+/**
+ * Filters branches that Kotlin compiler generates for coroutines.
+ */
+public final class KotlinCoroutineFilter implements IFilter {
+
+	static boolean isLastArgumentContinuation(final MethodNode methodNode) {
+		final Type methodType = Type.getMethodType(methodNode.desc);
+		final int lastArgument = methodType.getArgumentTypes().length - 1;
+		return lastArgument >= 0 && "kotlin.coroutines.Continuation".equals(
+				methodType.getArgumentTypes()[lastArgument].getClassName());
+	}
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+
+		if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+			return;
+		}
+
+		new Matcher().match(methodNode, output);
+
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		private void match(final MethodNode methodNode,
+				final IFilterOutput output) {
+			cursor = methodNode.instructions.getFirst();
+			nextIsInvoke(Opcodes.INVOKESTATIC,
+					"kotlin/coroutines/intrinsics/IntrinsicsKt",
+					"getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;");
+
+			if (cursor == null) {
+				cursor = skipNonOpcodes(methodNode.instructions.getFirst());
+
+				nextIsCreateStateInstance();
+
+				nextIsInvoke(Opcodes.INVOKESTATIC,
+						"kotlin/coroutines/intrinsics/IntrinsicsKt",
+						"getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;");
+			}
+
+			nextIsVar(Opcodes.ASTORE, "COROUTINE_SUSPENDED");
+			nextIsVar(Opcodes.ALOAD, "this");
+			nextIs(Opcodes.GETFIELD);
+			nextIs(Opcodes.TABLESWITCH);
+			if (cursor == null) {
+				return;
+			}
+			final TableSwitchInsnNode s = (TableSwitchInsnNode) cursor;
+			final List<AbstractInsnNode> ignore = new ArrayList<AbstractInsnNode>(
+					s.labels.size() * 2);
+
+			nextIs(Opcodes.ALOAD);
+			nextIsThrowOnFailure();
+
+			if (cursor == null) {
+				return;
+			}
+			ignore.add(methodNode.instructions.getFirst());
+			ignore.add(cursor);
+
+			int suspensionPoint = 1;
+			for (AbstractInsnNode i = cursor; i != null
+					&& suspensionPoint < s.labels.size(); i = i.getNext()) {
+				cursor = i;
+				nextIsVar(Opcodes.ALOAD, "COROUTINE_SUSPENDED");
+				nextIs(Opcodes.IF_ACMPNE);
+				if (cursor == null) {
+					continue;
+				}
+				final AbstractInsnNode continuationAfterLoadedResult = skipNonOpcodes(
+						((JumpInsnNode) cursor).label);
+				nextIsVar(Opcodes.ALOAD, "COROUTINE_SUSPENDED");
+				nextIs(Opcodes.ARETURN);
+				if (cursor == null
+						|| skipNonOpcodes(cursor.getNext()) != skipNonOpcodes(
+								s.labels.get(suspensionPoint))) {
+					continue;
+				}
+
+				for (AbstractInsnNode j = i; j != null; j = j.getNext()) {
+					cursor = j;
+					nextIs(Opcodes.ALOAD);
+					nextIsThrowOnFailure();
+
+					nextIs(Opcodes.ALOAD);
+					if (cursor != null && skipNonOpcodes(cursor
+							.getNext()) == continuationAfterLoadedResult) {
+						ignore.add(i);
+						ignore.add(cursor);
+						suspensionPoint++;
+						break;
+					}
+				}
+			}
+
+			cursor = s.dflt;
+			nextIsType(Opcodes.NEW, "java/lang/IllegalStateException");
+			nextIs(Opcodes.DUP);
+			nextIs(Opcodes.LDC);
+			if (cursor == null) {
+				return;
+			}
+			if (!((LdcInsnNode) cursor).cst.equals(
+					"call to 'resume' before 'invoke' with coroutine")) {
+				return;
+			}
+			nextIsInvoke(Opcodes.INVOKESPECIAL,
+					"java/lang/IllegalStateException", "<init>",
+					"(Ljava/lang/String;)V");
+			nextIs(Opcodes.ATHROW);
+			if (cursor == null) {
+				return;
+			}
+
+			output.ignore(s.dflt, cursor);
+			for (int i = 0; i < ignore.size(); i += 2) {
+				output.ignore(ignore.get(i), ignore.get(i + 1));
+			}
+		}
+
+		private void nextIsThrowOnFailure() {
+			final AbstractInsnNode c = cursor;
+			nextIsInvoke(Opcodes.INVOKESTATIC, "kotlin/ResultKt",
+					"throwOnFailure", "(Ljava/lang/Object;)V");
+			if (cursor == null) {
+				cursor = c;
+				// Before resolution of
+				// https://youtrack.jetbrains.com/issue/KT-28015 in
+				// Kotlin 1.3.30
+				nextIs(Opcodes.DUP);
+				nextIsType(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
+				nextIs(Opcodes.IFEQ);
+				nextIsType(Opcodes.CHECKCAST, "kotlin/Result$Failure");
+				nextIs(Opcodes.GETFIELD);
+				nextIs(Opcodes.ATHROW);
+				nextIs(Opcodes.POP);
+			}
+		}
+
+		private void nextIsCreateStateInstance() {
+			nextIs(Opcodes.INSTANCEOF);
+
+			nextIs(Opcodes.IFEQ);
+			if (cursor == null) {
+				return;
+			}
+			final AbstractInsnNode createStateInstance = skipNonOpcodes(
+					((JumpInsnNode) cursor).label);
+
+			nextIs(Opcodes.ALOAD);
+			nextIs(Opcodes.CHECKCAST);
+			nextIs(Opcodes.ASTORE);
+
+			nextIs(Opcodes.ALOAD);
+			nextIs(Opcodes.GETFIELD);
+
+			nextIs(Opcodes.LDC);
+			nextIs(Opcodes.IAND);
+			nextIs(Opcodes.IFEQ);
+			if (cursor == null || skipNonOpcodes(
+					((JumpInsnNode) cursor).label) != createStateInstance) {
+				return;
+			}
+
+			nextIs(Opcodes.ALOAD);
+			nextIs(Opcodes.DUP);
+			nextIs(Opcodes.GETFIELD);
+
+			nextIs(Opcodes.LDC);
+			nextIs(Opcodes.ISUB);
+			nextIs(Opcodes.PUTFIELD);
+
+			nextIs(Opcodes.GOTO);
+			if (cursor == null) {
+				return;
+			}
+			final AbstractInsnNode afterCoroutineStateCreated = skipNonOpcodes(
+					((JumpInsnNode) cursor).label);
+
+			if (skipNonOpcodes(cursor.getNext()) != createStateInstance) {
+				return;
+			}
+
+			cursor = afterCoroutineStateCreated;
+			nextIs(Opcodes.GETFIELD);
+			nextIs(Opcodes.ASTORE);
+		}
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
new file mode 100644
index 0000000..ef19844
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.VarInsnNode;
+
+/**
+ * Filters branches that Kotlin compiler generates for default arguments.
+ * 
+ * For each default argument Kotlin compiler generates following bytecode to
+ * determine if it should be used or not:
+ * 
+ * <pre>
+ * ILOAD maskVar
+ * ICONST_x, BIPUSH, SIPUSH, LDC or LDC_W
+ * IAND
+ * IFEQ label
+ * default argument
+ * label:
+ * </pre>
+ * 
+ * Where <code>maskVar</code> is penultimate argument of synthetic method with
+ * suffix "$default". And its value can't be zero - invocation with all
+ * arguments uses original non synthetic method, thus <code>IFEQ</code>
+ * instructions should be ignored.
+ */
+public final class KotlinDefaultArgumentsFilter implements IFilter {
+
+	static boolean isDefaultArgumentsMethodName(final String methodName) {
+		return methodName.endsWith("$default");
+	}
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) {
+			return;
+		}
+		if (!isDefaultArgumentsMethodName(methodNode.name)) {
+			return;
+		}
+		if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+			return;
+		}
+
+		new Matcher().match(methodNode, output);
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		public void match(final MethodNode methodNode,
+				final IFilterOutput output) {
+			cursor = methodNode.instructions.getFirst();
+
+			final Set<AbstractInsnNode> ignore = new HashSet<AbstractInsnNode>();
+			final int maskVar = Type.getMethodType(methodNode.desc)
+					.getArgumentTypes().length - 2;
+			while (true) {
+				if (cursor.getOpcode() != Opcodes.ILOAD) {
+					break;
+				}
+				if (((VarInsnNode) cursor).var != maskVar) {
+					break;
+				}
+				next();
+				nextIs(Opcodes.IAND);
+				nextIs(Opcodes.IFEQ);
+				if (cursor == null) {
+					return;
+				}
+				ignore.add(cursor);
+				cursor = ((JumpInsnNode) cursor).label;
+				skipNonOpcodes();
+			}
+
+			for (AbstractInsnNode i : ignore) {
+				output.ignore(i, i);
+			}
+		}
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
new file mode 100644
index 0000000..129580a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinGeneratedFilter.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Nikolay Krasko - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters methods generated by the Kotlin compiler. Kotlin classes are
+ * identified by the <code>@kotlin.Metadata</code> annotations. In such classes
+ * generated methods do not have line numbers.
+ */
+public class KotlinGeneratedFilter implements IFilter {
+
+	static final String KOTLIN_METADATA_DESC = "Lkotlin/Metadata;";
+
+	static boolean isKotlinClass(final IFilterContext context) {
+		return context.getClassAnnotations().contains(KOTLIN_METADATA_DESC);
+	}
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+
+		if (context.getSourceFileName() == null) {
+			// probably full debug information is missing
+			// disabled filtering as all methods might be erroneously skipped
+			return;
+		}
+
+		if (!isKotlinClass(context)) {
+			return;
+		}
+
+		if (hasLineNumber(methodNode)) {
+			return;
+		}
+
+		output.ignore(methodNode.instructions.getFirst(),
+				methodNode.instructions.getLast());
+	}
+
+	private boolean hasLineNumber(final MethodNode methodNode) {
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			if (AbstractInsnNode.LINE == i.getType()) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
new file mode 100644
index 0000000..5666de2
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinInlineFilter.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.BitSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.LineNumberNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters out instructions that were inlined by Kotlin compiler.
+ */
+public final class KotlinInlineFilter implements IFilter {
+
+	private int firstGeneratedLineNumber = -1;
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		if (context.getSourceDebugExtension() == null) {
+			return;
+		}
+
+		if (!KotlinGeneratedFilter.isKotlinClass(context)) {
+			return;
+		}
+
+		if (firstGeneratedLineNumber == -1) {
+			firstGeneratedLineNumber = getFirstGeneratedLineNumber(
+					context.getSourceFileName(),
+					context.getSourceDebugExtension());
+		}
+
+		int line = 0;
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			if (AbstractInsnNode.LINE == i.getType()) {
+				line = ((LineNumberNode) i).line;
+			}
+			if (line >= firstGeneratedLineNumber) {
+				output.ignore(i, i);
+			}
+		}
+	}
+
+	private static int getFirstGeneratedLineNumber(final String sourceFileName,
+			final String smap) {
+		try {
+			final BufferedReader br = new BufferedReader(
+					new StringReader(smap));
+			expectLine(br, "SMAP");
+			// OutputFileName
+			expectLine(br, sourceFileName);
+			// DefaultStratumId
+			expectLine(br, "Kotlin");
+			// StratumSection
+			expectLine(br, "*S Kotlin");
+			// FileSection
+			expectLine(br, "*F");
+			final BitSet sourceFileIds = new BitSet();
+			String line;
+			while (!"*L".equals(line = br.readLine())) {
+				// AbsoluteFileName
+				br.readLine();
+
+				final Matcher m = FILE_INFO_PATTERN.matcher(line);
+				if (!m.matches()) {
+					throw new IllegalStateException(
+							"Unexpected SMAP line: " + line);
+				}
+				final String fileName = m.group(2);
+				if (fileName.equals(sourceFileName)) {
+					sourceFileIds.set(Integer.parseInt(m.group(1)));
+				}
+			}
+			if (sourceFileIds.isEmpty()) {
+				throw new IllegalStateException("Unexpected SMAP FileSection");
+			}
+			// LineSection
+			int min = Integer.MAX_VALUE;
+			while (!"*E".equals(line = br.readLine())) {
+				final Matcher m = LINE_INFO_PATTERN.matcher(line);
+				if (!m.matches()) {
+					throw new IllegalStateException(
+							"Unexpected SMAP line: " + line);
+				}
+				final int inputStartLine = Integer.parseInt(m.group(1));
+				final int lineFileID = Integer
+						.parseInt(m.group(2).substring(1));
+				final int outputStartLine = Integer.parseInt(m.group(4));
+				if (sourceFileIds.get(lineFileID)
+						&& inputStartLine == outputStartLine) {
+					continue;
+				}
+				min = Math.min(outputStartLine, min);
+			}
+			return min;
+		} catch (final IOException e) {
+			// Must not happen with StringReader
+			throw new AssertionError(e);
+		}
+	}
+
+	private static void expectLine(final BufferedReader br,
+			final String expected) throws IOException {
+		final String line = br.readLine();
+		if (!expected.equals(line)) {
+			throw new IllegalStateException("Unexpected SMAP line: " + line);
+		}
+	}
+
+	private static final Pattern LINE_INFO_PATTERN = Pattern.compile("" //
+			+ "([0-9]++)" // InputStartLine
+			+ "(#[0-9]++)?+" // LineFileID
+			+ "(,[0-9]++)?+" // RepeatCount
+			+ ":([0-9]++)" // OutputStartLine
+			+ "(,[0-9]++)?+" // OutputLineIncrement
+	);
+
+	private static final Pattern FILE_INFO_PATTERN = Pattern.compile("" //
+			+ "\\+ ([0-9]++)" // FileID
+			+ " (.++)" // FileName
+	);
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java
new file mode 100644
index 0000000..12fe926
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Fabian Mastenbroek - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters branch in bytecode that Kotlin compiler generates for reading from
+ * <code>lateinit</code> properties.
+ */
+public class KotlinLateinitFilter implements IFilter {
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		final Matcher matcher = new Matcher();
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			matcher.match(i, output);
+		}
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		public void match(final AbstractInsnNode start,
+				final IFilterOutput output) {
+
+			if (Opcodes.IFNONNULL != start.getOpcode()) {
+				return;
+			}
+			cursor = start;
+
+			nextIs(Opcodes.LDC);
+			nextIsInvoke(Opcodes.INVOKESTATIC, "kotlin/jvm/internal/Intrinsics",
+					"throwUninitializedPropertyAccessException",
+					"(Ljava/lang/String;)V");
+
+			if (cursor != null) {
+				output.ignore(start, cursor);
+			}
+		}
+	}
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilter.java
new file mode 100644
index 0000000..4dd223a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinNotNullOperatorFilter.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters branch in bytecode that Kotlin compiler generates for not-null
+ * assertion operator.
+ */
+public final class KotlinNotNullOperatorFilter implements IFilter {
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		final Matcher matcher = new Matcher();
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			matcher.match(i, output);
+		}
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		public void match(final AbstractInsnNode start,
+				final IFilterOutput output) {
+			if (Opcodes.IFNONNULL != start.getOpcode()) {
+				return;
+			}
+			cursor = start;
+			nextIsInvoke(Opcodes.INVOKESTATIC, "kotlin/jvm/internal/Intrinsics",
+					"throwNpe", "()V");
+			if (cursor == null) {
+				return;
+			}
+			output.ignore(start, cursor);
+		}
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java
new file mode 100644
index 0000000..c298e94
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * Filters branch in bytecode that Kotlin compiler generates for "unsafe" cast
+ * operator.
+ */
+public final class KotlinUnsafeCastOperatorFilter implements IFilter {
+
+	private static final String KOTLIN_TYPE_CAST_EXCEPTION = "kotlin/TypeCastException";
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		final Matcher matcher = new Matcher();
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			matcher.match(i, output);
+		}
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		public void match(final AbstractInsnNode start,
+				final IFilterOutput output) {
+
+			if (Opcodes.IFNONNULL != start.getOpcode()) {
+				return;
+			}
+			cursor = start;
+
+			nextIsType(Opcodes.NEW, KOTLIN_TYPE_CAST_EXCEPTION);
+			nextIs(Opcodes.DUP);
+			nextIs(Opcodes.LDC);
+			if (cursor == null) {
+				return;
+			}
+			final LdcInsnNode ldc = (LdcInsnNode) cursor;
+			if (!(ldc.cst instanceof String && ((String) ldc.cst)
+					.startsWith("null cannot be cast to non-null type"))) {
+				return;
+			}
+			nextIsInvoke(Opcodes.INVOKESPECIAL, KOTLIN_TYPE_CAST_EXCEPTION,
+					"<init>", "(Ljava/lang/String;)V");
+			nextIs(Opcodes.ATHROW);
+			if (cursor == null) {
+				return;
+			}
+			if (cursor.getNext() != ((JumpInsnNode) start).label) {
+				return;
+			}
+
+			output.ignore(start, cursor);
+		}
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
new file mode 100644
index 0000000..a229aa0
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenFilter.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LookupSwitchInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TableSwitchInsnNode;
+
+/**
+ * Filters bytecode that Kotlin compiler generates for <code>when</code>
+ * expressions which list all cases of <code>enum</code> or
+ * <code>sealed class</code>, i.e. which don't require explicit
+ * <code>else</code>.
+ */
+public final class KotlinWhenFilter implements IFilter {
+
+	private static final String EXCEPTION = "kotlin/NoWhenBranchMatchedException";
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		final Matcher matcher = new Matcher();
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			matcher.match(i, output);
+		}
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		void match(final AbstractInsnNode start, final IFilterOutput output) {
+			if (start.getType() != InsnNode.LABEL) {
+				return;
+			}
+			cursor = start;
+
+			nextIsType(Opcodes.NEW, EXCEPTION);
+			nextIs(Opcodes.DUP);
+			nextIsInvoke(Opcodes.INVOKESPECIAL, EXCEPTION, "<init>", "()V");
+			nextIs(Opcodes.ATHROW);
+
+			for (AbstractInsnNode i = cursor; i != null; i = i.getPrevious()) {
+				if (i.getOpcode() == Opcodes.IFEQ
+						&& ((JumpInsnNode) i).label == start) {
+					output.ignore(i, i);
+					output.ignore(start, cursor);
+					return;
+
+				} else if (getDefaultLabel(i) == start) {
+					ignoreDefaultBranch(i, output);
+					output.ignore(start, cursor);
+					return;
+
+				}
+			}
+		}
+	}
+
+	private static LabelNode getDefaultLabel(final AbstractInsnNode i) {
+		switch (i.getOpcode()) {
+		case Opcodes.LOOKUPSWITCH:
+			return ((LookupSwitchInsnNode) i).dflt;
+		case Opcodes.TABLESWITCH:
+			return ((TableSwitchInsnNode) i).dflt;
+		default:
+			return null;
+		}
+	}
+
+	private static void ignoreDefaultBranch(final AbstractInsnNode switchNode,
+			final IFilterOutput output) {
+		final List<LabelNode> labels;
+		if (switchNode.getOpcode() == Opcodes.LOOKUPSWITCH) {
+			labels = ((LookupSwitchInsnNode) switchNode).labels;
+		} else {
+			labels = ((TableSwitchInsnNode) switchNode).labels;
+		}
+		final Set<AbstractInsnNode> newTargets = new HashSet<AbstractInsnNode>();
+		for (LabelNode label : labels) {
+			newTargets.add(AbstractMatcher.skipNonOpcodes(label));
+		}
+		output.replaceBranches(switchNode, newTargets);
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilter.java
new file mode 100644
index 0000000..fcccb55
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinWhenStringFilter.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LookupSwitchInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TableSwitchInsnNode;
+import org.objectweb.asm.tree.VarInsnNode;
+
+/**
+ * Filters bytecode that Kotlin compiler generates for <code>when</code>
+ * expressions with a <code>String</code>.
+ */
+public final class KotlinWhenStringFilter implements IFilter {
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		final Matcher matcher = new Matcher();
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			matcher.match(i, output);
+		}
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		public void match(final AbstractInsnNode start,
+				final IFilterOutput output) {
+
+			if (Opcodes.ALOAD != start.getOpcode()) {
+				return;
+			}
+			cursor = start;
+			nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
+					"()I");
+			nextIsSwitch();
+			if (cursor == null) {
+				return;
+			}
+			vars.put("s", (VarInsnNode) start);
+
+			final AbstractInsnNode s = cursor;
+			final int hashCodes;
+			final LabelNode defaultLabel;
+			if (s.getOpcode() == Opcodes.LOOKUPSWITCH) {
+				final LookupSwitchInsnNode lookupSwitch = (LookupSwitchInsnNode) cursor;
+				defaultLabel = lookupSwitch.dflt;
+				hashCodes = lookupSwitch.labels.size();
+			} else {
+				final TableSwitchInsnNode tableSwitch = (TableSwitchInsnNode) cursor;
+				defaultLabel = tableSwitch.dflt;
+				hashCodes = tableSwitch.labels.size();
+			}
+
+			final Set<AbstractInsnNode> replacements = new HashSet<AbstractInsnNode>();
+			replacements.add(skipNonOpcodes(defaultLabel));
+
+			for (int i = 0; i < hashCodes; i++) {
+				while (true) {
+					nextIsVar(Opcodes.ALOAD, "s");
+					nextIs(Opcodes.LDC);
+					nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/String",
+							"equals", "(Ljava/lang/Object;)Z");
+					// jump to next comparison or default case
+					nextIs(Opcodes.IFEQ);
+					final JumpInsnNode jump = (JumpInsnNode) cursor;
+					// jump to case
+					nextIs(Opcodes.GOTO);
+					if (cursor == null) {
+						return;
+					}
+
+					replacements
+							.add(skipNonOpcodes(((JumpInsnNode) cursor).label));
+
+					if (jump.label == defaultLabel) {
+						// end of comparisons for same hashCode
+						break;
+					}
+				}
+			}
+
+			output.ignore(s.getNext(), cursor);
+			output.replaceBranches(s, replacements);
+		}
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java
deleted file mode 100644
index b35e741..0000000
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/LombokGeneratedFilter.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *
- *******************************************************************************/
-package org.jacoco.core.internal.analysis.filter;
-
-import java.util.List;
-
-import org.objectweb.asm.tree.AnnotationNode;
-import org.objectweb.asm.tree.MethodNode;
-
-/**
- * Filters methods annotated with <code>@lombok.Generated</code>.
- */
-public final class LombokGeneratedFilter extends AbstractAnnotatedMethodFilter {
-
-	/**
-	 * New filter.
-	 */
-	public LombokGeneratedFilter() {
-		super("lombok/Generated");
-	}
-
-	@Override
-	List<AnnotationNode> getAnnotations(final MethodNode methodNode) {
-		return methodNode.invisibleAnnotations;
-	}
-
-}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java
index 08c654e..236ef71 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/PrivateEmptyNoArgConstructorFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,21 +12,22 @@
 package org.jacoco.core.internal.analysis.filter;
 
 import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.MethodInsnNode;
 import org.objectweb.asm.tree.MethodNode;
-import org.objectweb.asm.tree.VarInsnNode;
 
 /**
  * Filters private empty constructors that do not have arguments.
  */
 public final class PrivateEmptyNoArgConstructorFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
+	private static final String CONSTRUCTOR_NAME = "<init>";
+	private static final String CONSTRUCTOR_DESC = "()V";
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
 		if ((methodNode.access & Opcodes.ACC_PRIVATE) != 0
-				&& "<init>".equals(methodNode.name)
-				&& "()V".equals(methodNode.desc)
-				&& new Matcher().match(methodNode, superClassName)) {
+				&& CONSTRUCTOR_NAME.equals(methodNode.name)
+				&& CONSTRUCTOR_DESC.equals(methodNode.desc) && new Matcher()
+						.match(methodNode, context.getSuperClassName())) {
 			output.ignore(methodNode.instructions.getFirst(),
 					methodNode.instructions.getLast());
 		}
@@ -35,20 +36,11 @@
 	private static class Matcher extends AbstractMatcher {
 		private boolean match(final MethodNode methodNode,
 				final String superClassName) {
-			cursor = methodNode.instructions.getFirst();
-			skipNonOpcodes();
-			if (cursor.getOpcode() != Opcodes.ALOAD
-					|| ((VarInsnNode) cursor).var != 0) {
-				return false;
-			}
-			nextIs(Opcodes.INVOKESPECIAL);
-			MethodInsnNode m = (MethodInsnNode) cursor;
-			if (m != null && superClassName.equals(m.owner)
-					&& "<init>".equals(m.name) && ("()V").equals(m.desc)) {
-				nextIs(Opcodes.RETURN);
-				return cursor != null;
-			}
-			return false;
+			firstIsALoad0(methodNode);
+			nextIsInvoke(Opcodes.INVOKESPECIAL, superClassName,
+					CONSTRUCTOR_NAME, CONSTRUCTOR_DESC);
+			nextIs(Opcodes.RETURN);
+			return cursor != null;
 		}
 	}
 
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilter.java
new file mode 100644
index 0000000..e0aba35
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilter.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LookupSwitchInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TableSwitchInsnNode;
+import org.objectweb.asm.tree.VarInsnNode;
+
+/**
+ * Filters code that is generated by ECJ for a <code>switch</code> statement
+ * with a <code>String</code>.
+ */
+public final class StringSwitchEcjFilter implements IFilter {
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		final Matcher matcher = new Matcher();
+		for (AbstractInsnNode i = methodNode.instructions
+				.getFirst(); i != null; i = i.getNext()) {
+			matcher.match(i, output);
+		}
+	}
+
+	private static class Matcher extends AbstractMatcher {
+		public void match(final AbstractInsnNode start,
+				final IFilterOutput output) {
+
+			if (Opcodes.ASTORE != start.getOpcode()) {
+				return;
+			}
+			cursor = start;
+			nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
+					"()I");
+			nextIsSwitch();
+			if (cursor == null) {
+				return;
+			}
+			vars.put("s", (VarInsnNode) start);
+
+			final AbstractInsnNode s = cursor;
+			final int hashCodes;
+			final LabelNode defaultLabel;
+			if (s.getOpcode() == Opcodes.LOOKUPSWITCH) {
+				final LookupSwitchInsnNode lookupSwitch = (LookupSwitchInsnNode) cursor;
+				defaultLabel = lookupSwitch.dflt;
+				hashCodes = lookupSwitch.labels.size();
+			} else {
+				final TableSwitchInsnNode tableSwitch = (TableSwitchInsnNode) cursor;
+				defaultLabel = tableSwitch.dflt;
+				hashCodes = tableSwitch.labels.size();
+			}
+
+			final Set<AbstractInsnNode> replacements = new HashSet<AbstractInsnNode>();
+			replacements.add(skipNonOpcodes(defaultLabel));
+
+			for (int i = 0; i < hashCodes; i++) {
+				while (true) {
+					nextIsVar(Opcodes.ALOAD, "s");
+					nextIs(Opcodes.LDC);
+					nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/String",
+							"equals", "(Ljava/lang/Object;)Z");
+					// jump to case
+					nextIs(Opcodes.IFNE);
+					if (cursor == null) {
+						return;
+					}
+
+					replacements
+							.add(skipNonOpcodes(((JumpInsnNode) cursor).label));
+
+					if (cursor.getNext().getOpcode() == Opcodes.GOTO) {
+						// end of comparisons for same hashCode
+						// jump to default
+						nextIs(Opcodes.GOTO);
+						break;
+					} else if (cursor.getNext() == defaultLabel) {
+						break;
+					}
+				}
+			}
+
+			output.ignore(s.getNext(), cursor);
+			output.replaceBranches(s, replacements);
+		}
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java
index e1d7a1c..3033d9b 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/StringSwitchJavacFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,8 +24,8 @@
  */
 public final class StringSwitchJavacFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
 		AbstractInsnNode i = methodNode.instructions.getFirst();
 		while (i != null) {
 			filter(i, output);
@@ -68,12 +68,14 @@
 			// Even if expression is not a variable, its result will be
 			// precomputed before the previous two instructions:
 			nextIsVar(Opcodes.ALOAD, "s");
-			nextIsInvokeVirtual("java/lang/String", "hashCode");
+			nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode",
+					"()I");
 			next();
 			while (true) {
 				nextIsVar(Opcodes.ALOAD, "s");
 				nextIs(Opcodes.LDC);
-				nextIsInvokeVirtual("java/lang/String", "equals");
+				nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/String",
+						"equals", "(Ljava/lang/Object;)Z");
 				// jump to next comparison or second switch
 				nextIs(Opcodes.IFEQ);
 				// ICONST, BIPUSH or SIPUSH
@@ -91,7 +93,8 @@
 				}
 			}
 			nextIsVar(Opcodes.ILOAD, "c");
-			nextIs(Opcodes.TABLESWITCH);
+			// Can be TABLESWITCH or LOOKUPSWITCH depending on number of cases
+			nextIsSwitch();
 			return cursor != null;
 		}
 	}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
index 71ce0cf..6341328 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -21,9 +21,9 @@
  */
 public final class SynchronizedFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
-		for (TryCatchBlockNode tryCatch : methodNode.tryCatchBlocks) {
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		for (final TryCatchBlockNode tryCatch : methodNode.tryCatchBlocks) {
 			if (tryCatch.type != null) {
 				continue;
 			}
@@ -67,7 +67,7 @@
 			nextIs(Opcodes.ALOAD);
 			nextIs(Opcodes.MONITOREXIT);
 			nextIs(Opcodes.ATHROW);
-			return  cursor != null;
+			return cursor != null;
 		}
 	}
 
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SyntheticFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SyntheticFilter.java
index afba0f0..69c4092 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SyntheticFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SyntheticFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -19,13 +19,29 @@
  */
 public final class SyntheticFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
-		if ((methodNode.access & Opcodes.ACC_SYNTHETIC) != 0
-				&& !methodNode.name.startsWith("lambda$")) {
-			output.ignore(methodNode.instructions.getFirst(),
-					methodNode.instructions.getLast());
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) {
+			return;
 		}
+
+		if (methodNode.name.startsWith("lambda$")) {
+			return;
+		}
+
+		if (KotlinGeneratedFilter.isKotlinClass(context)) {
+			if (KotlinDefaultArgumentsFilter
+					.isDefaultArgumentsMethodName(methodNode.name)) {
+				return;
+			}
+
+			if (KotlinCoroutineFilter.isLastArgumentContinuation(methodNode)) {
+				return;
+			}
+		}
+
+		output.ignore(methodNode.instructions.getFirst(),
+				methodNode.instructions.getLast());
 	}
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java
index c25d61f..94dea56 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesEcjFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -27,13 +27,13 @@
  */
 public final class TryWithResourcesEcjFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
 		if (methodNode.tryCatchBlocks.isEmpty()) {
 			return;
 		}
 		final Matcher matcher = new Matcher(output);
-		for (TryCatchBlockNode t : methodNode.tryCatchBlocks) {
+		for (final TryCatchBlockNode t : methodNode.tryCatchBlocks) {
 			if (t.type == null) {
 				matcher.start(t.handler);
 				if (!matcher.matchEcj()) {
@@ -200,7 +200,8 @@
 			// "primaryExc.addSuppressed(suppressedExc)"
 			nextIsVar(Opcodes.ALOAD, "primaryExc");
 			nextIsVar(Opcodes.ALOAD, suppressedExc);
-			nextIsInvokeVirtual("java/lang/Throwable", "addSuppressed");
+			nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable",
+					"addSuppressed", "(Ljava/lang/Throwable;)V");
 			nextIsLabel(endLabel);
 			return cursor != null;
 		}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11Filter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11Filter.java
new file mode 100644
index 0000000..7a20f74
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavac11Filter.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+
+/**
+ * Filters code which is generated for try-with-resources statement by javac
+ * starting from version 11.
+ */
+public final class TryWithResourcesJavac11Filter implements IFilter {
+
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
+		if (methodNode.tryCatchBlocks.isEmpty()) {
+			return;
+		}
+		final Matcher matcher = new Matcher();
+		for (TryCatchBlockNode t : methodNode.tryCatchBlocks) {
+			if ("java/lang/Throwable".equals(t.type)) {
+				matcher.match(t.handler, output, true);
+				matcher.match(t.handler, output, false);
+			}
+		}
+	}
+
+	/**
+	 * <pre>
+	 *     r = ...;
+	 *     try {
+	 *         ...
+	 *     } body-only-finally {
+	 *         if (r != null)
+	 *             r.close();
+	 *     } catch (Throwable primaryExc) {
+	 *         if (r != null)
+	 *             try {
+	 *                 r.close();
+	 *             } catch (Throwable t) {
+	 *                 primaryExc.addSuppressed(t);
+	 *             }
+	 *         throw primaryExc;
+	 *     }
+	 * </pre>
+	 * 
+	 * <code>null</code> check for resource is omitted when it is initialized
+	 * using <code>new</code>
+	 */
+	private class Matcher extends AbstractMatcher {
+		private boolean withNullCheck;
+
+		private String expectedOwner;
+
+		void match(final AbstractInsnNode start, final IFilterOutput output,
+				final boolean withNullCheck) {
+			this.withNullCheck = withNullCheck;
+			vars.clear();
+			expectedOwner = null;
+
+			cursor = start.getPrevious();
+			nextIsVar(Opcodes.ASTORE, "primaryExc");
+			nextIsJavacClose();
+			nextIs(Opcodes.GOTO);
+			nextIsVar(Opcodes.ASTORE, "t");
+			nextIsVar(Opcodes.ALOAD, "primaryExc");
+			nextIsVar(Opcodes.ALOAD, "t");
+			nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable",
+					"addSuppressed", "(Ljava/lang/Throwable;)V"); // primaryExc.addSuppressed(t)
+			nextIsVar(Opcodes.ALOAD, "primaryExc");
+			nextIs(Opcodes.ATHROW);
+			if (cursor == null) {
+				return;
+			}
+			final AbstractInsnNode end = cursor;
+
+			AbstractInsnNode s = start.getPrevious();
+			cursor = start.getPrevious();
+			while (!nextIsJavacClose()) {
+				s = s.getPrevious();
+				cursor = s;
+				if (cursor == null) {
+					return;
+				}
+			}
+			s = s.getNext();
+
+			final AbstractInsnNode m = cursor;
+			next();
+			if (cursor.getOpcode() != Opcodes.GOTO) {
+				cursor = m;
+			}
+
+			output.ignore(s, cursor);
+			output.ignore(start, end);
+		}
+
+		private boolean nextIsJavacClose() {
+			if (withNullCheck) {
+				nextIsVar(Opcodes.ALOAD, "r");
+				nextIs(Opcodes.IFNULL);
+			}
+			nextIsClose();
+			return cursor != null;
+		}
+
+		private void nextIsClose() {
+			nextIsVar(Opcodes.ALOAD, "r");
+			next();
+			if (cursor == null) {
+				return;
+			}
+			if (cursor.getOpcode() != Opcodes.INVOKEINTERFACE
+					&& cursor.getOpcode() != Opcodes.INVOKEVIRTUAL) {
+				cursor = null;
+				return;
+			}
+			final MethodInsnNode m = (MethodInsnNode) cursor;
+			if (!"close".equals(m.name) || !"()V".equals(m.desc)) {
+				cursor = null;
+				return;
+			}
+			final String actual = m.owner;
+			if (expectedOwner == null) {
+				expectedOwner = actual;
+			} else if (!expectedOwner.equals(actual)) {
+				cursor = null;
+			}
+		}
+
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java
index f3b33bc..23ecb0e 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/TryWithResourcesJavacFilter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -18,19 +18,21 @@
 import org.objectweb.asm.tree.TryCatchBlockNode;
 
 /**
- * Filters code that javac generates for try-with-resources statement.
+ * Filters code which is generated for try-with-resources statement by javac
+ * versions from 7 to 10.
  */
 public final class TryWithResourcesJavacFilter implements IFilter {
 
-	public void filter(final String className, final String superClassName,
-			final MethodNode methodNode, final IFilterOutput output) {
+	public void filter(final MethodNode methodNode,
+			final IFilterContext context, final IFilterOutput output) {
 		if (methodNode.tryCatchBlocks.isEmpty()) {
 			return;
 		}
 		final Matcher matcher = new Matcher(output);
-		for (TryCatchBlockNode t : methodNode.tryCatchBlocks) {
+		for (final TryCatchBlockNode t : methodNode.tryCatchBlocks) {
 			if ("java/lang/Throwable".equals(t.type)) {
-				for (Matcher.JavacPattern p : Matcher.JavacPattern.values()) {
+				for (final Matcher.JavacPattern p : Matcher.JavacPattern
+						.values()) {
 					matcher.start(t.handler);
 					if (matcher.matchJavac(p)) {
 						break;
@@ -195,7 +197,7 @@
 					final MethodInsnNode m = (MethodInsnNode) cursor;
 					if ("$closeResource".equals(m.name)
 							&& "(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V"
-							.equals(m.desc)) {
+									.equals(m.desc)) {
 						return true;
 					}
 					cursor = null;
@@ -214,7 +216,8 @@
 				// "primaryExc.addSuppressed(t)"
 				nextIsVar(Opcodes.ALOAD, "primaryExc");
 				nextIsVar(Opcodes.ALOAD, ctx + "t");
-				nextIsInvokeVirtual("java/lang/Throwable", "addSuppressed");
+				nextIsInvoke(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable",
+						"addSuppressed", "(Ljava/lang/Throwable;)V");
 				nextIs(Opcodes.GOTO);
 				// "r.close()"
 				nextIsClose();
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/data/CRC64.java b/org.jacoco.core/src/org/jacoco/core/internal/data/CRC64.java
index 974269b..620a46f 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/data/CRC64.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/data/CRC64.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataInput.java b/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataInput.java
index 082c179..945b2b6 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataInput.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataInput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataOutput.java b/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataOutput.java
index 7852102..4d230f8 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataOutput.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/data/CompactDataOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesAdapter.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesAdapter.java
index 11ce434..876a135 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesAdapter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesAdapter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesVisitor.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesVisitor.java
index fc3b979..54817e8 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesVisitor.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/ClassProbesVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/FrameSnapshot.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/FrameSnapshot.java
index 94e24cc..a0c7449 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/FrameSnapshot.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/FrameSnapshot.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/IFrame.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/IFrame.java
index 09e9906..6079f44 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/IFrame.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/IFrame.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,6 @@
 	 * @param mv
 	 *            method visitor to emit frame event to
 	 */
-	void accept(final MethodVisitor mv);
+	void accept(MethodVisitor mv);
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/IProbeIdGenerator.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/IProbeIdGenerator.java
index 4baa4f0..6f3f197 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/IProbeIdGenerator.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/IProbeIdGenerator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java
deleted file mode 100644
index d1e7cbe..0000000
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/Instruction.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.core.internal.flow;
-
-import org.objectweb.asm.tree.AbstractInsnNode;
-
-import java.util.BitSet;
-
-/**
- * Representation of a byte code instruction for analysis. Internally used for
- * analysis.
- */
-public class Instruction {
-
-	private final AbstractInsnNode node;
-
-	private final int line;
-
-	private int branches;
-
-	private final BitSet coveredBranches;
-
-	private Instruction predecessor;
-
-	private int predecessorBranch;
-
-	/**
-	 * New instruction at the given line.
-	 * 
-	 * @param node
-	 *            corresponding node
-	 * @param line
-	 *            source line this instruction belongs to
-	 */
-	public Instruction(final AbstractInsnNode node, final int line) {
-		this.node = node;
-		this.line = line;
-		this.branches = 0;
-		this.coveredBranches = new BitSet();
-	}
-
-	/**
-	 * @return corresponding node
-	 */
-	public AbstractInsnNode getNode() {
-		return node;
-	}
-
-	/**
-	 * Adds an branch to this instruction.
-	 */
-	public void addBranch() {
-		branches++;
-	}
-
-	/**
-	 * Sets the given instruction as a predecessor of this instruction and adds
-	 * branch to the predecessor. Probes are inserted in a way that every
-	 * instruction has at most one direct predecessor.
-	 * 
-	 * @see #addBranch()
-	 * @param predecessor
-	 *            predecessor instruction
-	 * @param branch
-	 *            branch number in predecessor that should be marked as covered
-	 *            when this instruction marked as covered
-	 */
-	public void setPredecessor(final Instruction predecessor,
-			final int branch) {
-		this.predecessor = predecessor;
-		predecessor.addBranch();
-		this.predecessorBranch = branch;
-	}
-
-	/**
-	 * Marks one branch of this instruction as covered. Also recursively marks
-	 * all predecessor instructions as covered if this is the first covered
-	 * branch.
-	 *
-	 * @param branch
-	 *            branch number to mark as covered
-	 */
-	public void setCovered(final int branch) {
-		Instruction i = this;
-		int b = branch;
-		while (i != null) {
-			if (!i.coveredBranches.isEmpty()) {
-				i.coveredBranches.set(b);
-				break;
-			}
-			i.coveredBranches.set(b);
-			b = i.predecessorBranch;
-			i = i.predecessor;
-		}
-	}
-
-	/**
-	 * Returns the source line this instruction belongs to.
-	 * 
-	 * @return corresponding source line
-	 */
-	public int getLine() {
-		return line;
-	}
-
-	/**
-	 * Returns the total number of branches starting from this instruction.
-	 * 
-	 * @return total number of branches
-	 */
-	public int getBranches() {
-		return branches;
-	}
-
-	/**
-	 * Returns the number of covered branches starting from this instruction.
-	 * 
-	 * @return number of covered branches
-	 */
-	public int getCoveredBranches() {
-		return coveredBranches.cardinality();
-	}
-
-	/**
-	 * Merges information about covered branches of given instruction into this
-	 * instruction.
-	 * 
-	 * @param instruction
-	 *            instruction from which to merge
-	 */
-	public void merge(Instruction instruction) {
-		this.coveredBranches.or(instruction.coveredBranches);
-	}
-
-	@Override
-	public String toString() {
-		return coveredBranches.toString();
-	}
-
-}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelFlowAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelFlowAnalyzer.java
index f5b354f..0f0e4d3 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelFlowAnalyzer.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelFlowAnalyzer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java
index 1b65ae2..85dc1d8 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/LabelInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
  *******************************************************************************/
 package org.jacoco.core.internal.flow;
 
+import org.jacoco.core.internal.analysis.Instruction;
 import org.objectweb.asm.Label;
 
 /**
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesAdapter.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesAdapter.java
index 867ff93..40e20a3 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesAdapter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesAdapter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesVisitor.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesVisitor.java
index 7514193..75e6355 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesVisitor.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodProbesVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodSanitizer.java b/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodSanitizer.java
index f6aa2e9..92b0894 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodSanitizer.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/flow/MethodSanitizer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategy.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategy.java
index e805135..950be68 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategy.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassFieldProbeArrayStrategy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java
index 1117975..7d5e975 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategy.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategy.java
new file mode 100644
index 0000000..ca2fb60
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/CondyProbeArrayStrategy.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.instr;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ConstantDynamic;
+import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * This strategy for Java 11+ class files uses {@link ConstantDynamic} to hold
+ * the probe array and adds bootstrap method requesting the probe array from the
+ * runtime.
+ */
+public class CondyProbeArrayStrategy implements IProbeArrayStrategy {
+
+	/**
+	 * Descriptor of the bootstrap method.
+	 */
+	public static final String B_DESC = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)[Z";
+
+	private final String className;
+
+	private final boolean isInterface;
+
+	private final long classId;
+
+	private final IExecutionDataAccessorGenerator accessorGenerator;
+
+	CondyProbeArrayStrategy(final String className, final boolean isInterface,
+			final long classId,
+			final IExecutionDataAccessorGenerator accessorGenerator) {
+		this.className = className;
+		this.isInterface = isInterface;
+		this.classId = classId;
+		this.accessorGenerator = accessorGenerator;
+	}
+
+	public int storeInstance(final MethodVisitor mv, final boolean clinit,
+			final int variable) {
+		final Handle bootstrapMethod = new Handle(Opcodes.H_INVOKESTATIC,
+				className, InstrSupport.INITMETHOD_NAME, B_DESC, isInterface);
+		// As a workaround for https://bugs.openjdk.java.net/browse/JDK-8216970
+		// constant should have type Object
+		mv.visitLdcInsn(new ConstantDynamic(InstrSupport.DATAFIELD_NAME,
+				"Ljava/lang/Object;", bootstrapMethod));
+		mv.visitTypeInsn(Opcodes.CHECKCAST, "[Z");
+		mv.visitVarInsn(Opcodes.ASTORE, variable);
+		return 1;
+	}
+
+	public void addMembers(final ClassVisitor cv, final int probeCount) {
+		final MethodVisitor mv = cv.visitMethod(InstrSupport.INITMETHOD_ACC,
+				InstrSupport.INITMETHOD_NAME, B_DESC, null, null);
+		final int maxStack = accessorGenerator.generateDataAccessor(classId,
+				className, probeCount, mv);
+		mv.visitInsn(Opcodes.ARETURN);
+		mv.visitMaxs(maxStack, 3);
+		mv.visitEnd();
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/DuplicateFrameEliminator.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/DuplicateFrameEliminator.java
index 3470775..bc3e54b 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/DuplicateFrameEliminator.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/DuplicateFrameEliminator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeArrayStrategy.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeArrayStrategy.java
index e9ae4b6..5fe0cdc 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeArrayStrategy.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeArrayStrategy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -39,7 +39,7 @@
 	 * called after all original members of the class has been processed.
 	 * 
 	 * @param cv
-	 *            visitor to create fields and classes
+	 *            visitor to create fields and methods
 	 * @param probeCount
 	 *            total number of probes required for this class
 	 */
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeInserter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeInserter.java
index e6c8dc5..2f8dab6 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeInserter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/IProbeInserter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -23,6 +23,6 @@
 	 * @param id
 	 *            id of the probe to insert
 	 */
-	public void insertProbe(final int id);
+	void insertProbe(int id);
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
index b6632c6..85e83a3 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
 
 import static java.lang.String.format;
 
+import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
@@ -25,7 +26,7 @@
 	}
 
 	/** ASM API version */
-	public static final int ASM_API_VERSION = Opcodes.ASM6;
+	public static final int ASM_API_VERSION = Opcodes.ASM7;
 
 	// === Data Field ===
 
@@ -158,6 +159,66 @@
 	static final int CLINIT_ACC = Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC;
 
 	/**
+	 * Gets major version number from given bytes of class (unsigned two bytes
+	 * at offset 6).
+	 *
+	 * @param b
+	 *            bytes of class
+	 * @return major version of bytecode
+	 * @see <a href=
+	 *      "https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.1">Java
+	 *      Virtual Machine Specification §4 The class File Format</a>
+	 * @see #setMajorVersion(int, byte[])
+	 * @see #getMajorVersion(ClassReader)
+	 */
+	public static int getMajorVersion(final byte[] b) {
+		return ((b[6] & 0xFF) << 8) | (b[7] & 0xFF);
+	}
+
+	/**
+	 * Sets major version number in given bytes of class (unsigned two bytes at
+	 * offset 6).
+	 *
+	 * @param majorVersion
+	 *            major version of bytecode to set
+	 * @param b
+	 *            bytes of class
+	 * @see #getMajorVersion(byte[])
+	 */
+	public static void setMajorVersion(final int majorVersion, final byte[] b) {
+		b[6] = (byte) (majorVersion >>> 8);
+		b[7] = (byte) majorVersion;
+	}
+
+	/**
+	 * Gets major version number from given {@link ClassReader}.
+	 *
+	 * @param reader
+	 *            reader to get information about the class
+	 * @return major version of bytecode
+	 * @see ClassReader#ClassReader(byte[], int, int)
+	 * @see #getMajorVersion(byte[])
+	 */
+	public static int getMajorVersion(final ClassReader reader) {
+		// relative to the beginning of constant pool because ASM provides API
+		// to construct ClassReader which reads from the middle of array
+		final int firstConstantPoolEntryOffset = reader.getItem(1) - 1;
+		return reader.readUnsignedShort(firstConstantPoolEntryOffset - 4);
+	}
+
+	/**
+	 * Determines whether the given class file version requires stackmap frames.
+	 * 
+	 * @param version
+	 *            class file version
+	 * @return <code>true</code> if frames are required
+	 */
+	public static boolean needsFrames(final int version) {
+		// consider major version only (due to 1.1 anomaly)
+		return (version & 0xFFFF) >= Opcodes.V1_6;
+	}
+
+	/**
 	 * Ensures that the given member does not correspond to a internal member
 	 * created by the instrumentation process. This would mean that the class is
 	 * already instrumented.
@@ -174,7 +235,8 @@
 			final String owner) throws IllegalStateException {
 		if (member.equals(DATAFIELD_NAME) || member.equals(INITMETHOD_NAME)) {
 			throw new IllegalStateException(format(
-					"Class %s is already instrumented.", owner));
+					"Cannot process instrumented class %s. Please supply original non-instrumented classes.",
+					owner));
 		}
 	}
 
@@ -200,4 +262,23 @@
 		}
 	}
 
+	/**
+	 * Creates a {@link ClassReader} instance for given bytes of class even if
+	 * its version not yet supported by ASM.
+	 *
+	 * @param b
+	 *            bytes of class
+	 * @return {@link ClassReader}
+	 */
+	public static ClassReader classReaderFor(final byte[] b) {
+		final int originalVersion = getMajorVersion(b);
+		if (originalVersion == Opcodes.V12 + 1) {
+			// temporarily downgrade version to bypass check in ASM
+			setMajorVersion(Opcodes.V12, b);
+		}
+		final ClassReader classReader = new ClassReader(b);
+		setMajorVersion(originalVersion, b);
+		return classReader;
+	}
+
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/InterfaceFieldProbeArrayStrategy.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/InterfaceFieldProbeArrayStrategy.java
index 9325ddd..bf855fe 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/InterfaceFieldProbeArrayStrategy.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/InterfaceFieldProbeArrayStrategy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategy.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategy.java
index f9a506c..67068ed 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategy.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/LocalProbeArrayStrategy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -50,4 +50,4 @@
 		// nothing to do
 	}
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/MethodInstrumenter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/MethodInstrumenter.java
index 472ffb7..396368b 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/MethodInstrumenter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/MethodInstrumenter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/NoneProbeArrayStrategy.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/NoneProbeArrayStrategy.java
index 790a34a..b3a4186 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/NoneProbeArrayStrategy.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/NoneProbeArrayStrategy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -29,4 +29,4 @@
 		// nothing to do
 	}
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactory.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactory.java
index 349840b..d5756b7 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactory.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeArrayStrategyFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,7 +11,6 @@
  *******************************************************************************/
 package org.jacoco.core.internal.instr;
 
-import org.jacoco.core.internal.data.CRC64;
 import org.jacoco.core.internal.flow.ClassProbesAdapter;
 import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
 import org.objectweb.asm.ClassReader;
@@ -30,26 +29,31 @@
 	 * Creates a suitable strategy instance for the class described by the given
 	 * reader. Created instance must be used only to process a class or
 	 * interface for which it has been created and must be used only once.
-	 * 
+	 *
+	 * @param classId
+	 *            class identifier
 	 * @param reader
 	 *            reader to get information about the class
 	 * @param accessorGenerator
 	 *            accessor to the coverage runtime
 	 * @return strategy instance
 	 */
-	public static IProbeArrayStrategy createFor(final ClassReader reader,
+	public static IProbeArrayStrategy createFor(final long classId,
+			final ClassReader reader,
 			final IExecutionDataAccessorGenerator accessorGenerator) {
 
 		final String className = reader.getClassName();
-		final int version = getVersion(reader);
-		final long classId = CRC64.classId(reader.b);
-		final boolean withFrames = version >= Opcodes.V1_6;
+		final int version = InstrSupport.getMajorVersion(reader);
 
 		if (isInterfaceOrModule(reader)) {
 			final ProbeCounter counter = getProbeCounter(reader);
 			if (counter.getCount() == 0) {
 				return new NoneProbeArrayStrategy();
 			}
+			if (version >= Opcodes.V11 && counter.hasMethods()) {
+				return new CondyProbeArrayStrategy(className, true, classId,
+						accessorGenerator);
+			}
 			if (version >= Opcodes.V1_8 && counter.hasMethods()) {
 				return new InterfaceFieldProbeArrayStrategy(className, classId,
 						counter.getCount(), accessorGenerator);
@@ -58,8 +62,12 @@
 						counter.getCount(), accessorGenerator);
 			}
 		} else {
+			if (version >= Opcodes.V11) {
+				return new CondyProbeArrayStrategy(className, false, classId,
+						accessorGenerator);
+			}
 			return new ClassFieldProbeArrayStrategy(className, classId,
-					withFrames, accessorGenerator);
+					InstrSupport.needsFrames(version), accessorGenerator);
 		}
 	}
 
@@ -68,10 +76,6 @@
 				& (Opcodes.ACC_INTERFACE | Opcodes.ACC_MODULE)) != 0;
 	}
 
-	private static int getVersion(final ClassReader reader) {
-		return reader.readShort(6);
-	}
-
 	private static ProbeCounter getProbeCounter(final ClassReader reader) {
 		final ProbeCounter counter = new ProbeCounter();
 		reader.accept(new ClassProbesAdapter(counter, false), 0);
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeCounter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeCounter.java
index 2a32315..de22326 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeCounter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeCounter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java
index 6165714..63fbf76 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/SignatureRemover.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/SignatureRemover.java
index 29995ee..06994c0 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/SignatureRemover.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/SignatureRemover.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/package-info.java b/org.jacoco.core/src/org/jacoco/core/package-info.java
index 0af292d..84ebdf8 100644
--- a/org.jacoco.core/src/org/jacoco/core/package-info.java
+++ b/org.jacoco.core/src/org/jacoco/core/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Meta information about JaCoCo.
  */
-package org.jacoco.core;
\ No newline at end of file
+package org.jacoco.core;
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/AbstractRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/AbstractRuntime.java
index 9c41d6c..388e3e4 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/AbstractRuntime.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/AbstractRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
index 46c108e..60f03c0 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/CommandLineSupport.java b/org.jacoco.core/src/org/jacoco/core/runtime/CommandLineSupport.java
index 1493afb..1f7fafc 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/CommandLineSupport.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/CommandLineSupport.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -54,13 +54,13 @@
 	 */
 	static String quote(final List<String> args) {
 		final StringBuilder result = new StringBuilder();
-		boolean seperate = false;
+		boolean separate = false;
 		for (final String arg : args) {
-			if (seperate) {
+			if (separate) {
 				result.append(BLANK);
 			}
 			result.append(quote(arg));
-			seperate = true;
+			separate = true;
 		}
 		return result.toString();
 	}
@@ -70,7 +70,7 @@
 	 * present.
 	 * 
 	 * @param commandline
-	 *            combinded command line
+	 *            combined command line
 	 * @return list of arguments
 	 */
 	static List<String> split(final String commandline) {
@@ -79,11 +79,11 @@
 		}
 		final List<String> args = new ArrayList<String>();
 		final StringBuilder current = new StringBuilder();
-		int mode = M_STRIPWHITESPACE;
+		int mode = M_STRIP_WHITESPACE;
 		int endChar = BLANK;
 		for (final char c : commandline.toCharArray()) {
 			switch (mode) {
-			case M_STRIPWHITESPACE:
+			case M_STRIP_WHITESPACE:
 				if (!Character.isWhitespace(c)) {
 					if (c == QUOTE) {
 						endChar = QUOTE;
@@ -91,13 +91,13 @@
 						current.append(c);
 						endChar = BLANK;
 					}
-					mode = M_PARSEARGUMENT;
+					mode = M_PARSE_ARGUMENT;
 				}
 				break;
-			case M_PARSEARGUMENT:
+			case M_PARSE_ARGUMENT:
 				if (c == endChar) {
 					addArgument(args, current);
-					mode = M_STRIPWHITESPACE;
+					mode = M_STRIP_WHITESPACE;
 				} else if (c == SLASH) {
 					current.append(SLASH);
 					mode = M_ESCAPED;
@@ -110,11 +110,11 @@
 					current.setCharAt(current.length() - 1, c);
 				} else if (c == endChar) {
 					addArgument(args, current);
-					mode = M_STRIPWHITESPACE;
+					mode = M_STRIP_WHITESPACE;
 				} else {
 					current.append(c);
 				}
-				mode = M_PARSEARGUMENT;
+				mode = M_PARSE_ARGUMENT;
 				break;
 			}
 		}
@@ -130,8 +130,8 @@
 		}
 	}
 
-	private static final int M_STRIPWHITESPACE = 0;
-	private static final int M_PARSEARGUMENT = 1;
+	private static final int M_STRIP_WHITESPACE = 0;
+	private static final int M_PARSE_ARGUMENT = 1;
 	private static final int M_ESCAPED = 2;
 
 	private CommandLineSupport() {
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/IExecutionDataAccessorGenerator.java b/org.jacoco.core/src/org/jacoco/core/runtime/IExecutionDataAccessorGenerator.java
index 0078312..83df574 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/IExecutionDataAccessorGenerator.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/IExecutionDataAccessorGenerator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -45,7 +45,7 @@
 	 * @return additional stack size required by the implementation, including
 	 *         the instance pushed to the stack
 	 */
-	public int generateDataAccessor(final long classid, final String classname,
-			final int probecount, MethodVisitor mv);
+	int generateDataAccessor(long classid, String classname, int probecount,
+			MethodVisitor mv);
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/IRemoteCommandVisitor.java b/org.jacoco.core/src/org/jacoco/core/runtime/IRemoteCommandVisitor.java
index c4b12f1..9057a4e 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/IRemoteCommandVisitor.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/IRemoteCommandVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,7 +28,6 @@
 	 * @throws IOException
 	 *             in case of problems with the remote connection
 	 */
-	public void visitDumpCommand(final boolean dump, final boolean reset)
-			throws IOException;
+	void visitDumpCommand(boolean dump, boolean reset) throws IOException;
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java
index 9eee8fb..ea05563 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,12 +26,12 @@
 	 * @throws Exception
 	 *             any internal problem during startup
 	 */
-	public void startup(RuntimeData data) throws Exception;
+	void startup(RuntimeData data) throws Exception;
 
 	/**
 	 * Allows the coverage runtime to cleanup internals. This class should be
 	 * called when classes instrumented for this runtime are not used any more.
 	 */
-	public void shutdown();
+	void shutdown();
 
 }
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/InjectedClassRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/InjectedClassRuntime.java
new file mode 100644
index 0000000..ee7aa1a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/InjectedClassRuntime.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.runtime;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * {@link IRuntime} which defines a new class using
+ * {@code java.lang.invoke.MethodHandles.Lookup.defineClass} introduced in Java
+ * 9. Module where class will be defined must be opened to at least module of
+ * this class.
+ */
+public class InjectedClassRuntime extends AbstractRuntime {
+
+	private static final String FIELD_NAME = "data";
+
+	private static final String FIELD_TYPE = "Ljava/lang/Object;";
+
+	private final Class<?> locator;
+
+	private final String injectedClassName;
+
+	/**
+	 * Creates a new runtime which will define a class to the same class loader
+	 * and in the same package and protection domain as given class.
+	 *
+	 * @param locator
+	 *            class to identify the target class loader and package
+	 * @param simpleClassName
+	 *            simple name of the class to be defined
+	 */
+	public InjectedClassRuntime(final Class<?> locator,
+			final String simpleClassName) {
+		this.locator = locator;
+		this.injectedClassName = locator.getPackage().getName().replace('.',
+				'/') + '/' + simpleClassName;
+	}
+
+	@Override
+	public void startup(final RuntimeData data) throws Exception {
+		super.startup(data);
+		Lookup //
+				.privateLookupIn(locator, Lookup.lookup()) //
+				.defineClass(createClass(injectedClassName)) //
+				.getField(FIELD_NAME) //
+				.set(null, data);
+	}
+
+	public void shutdown() {
+		// nothing to do
+	}
+
+	public int generateDataAccessor(final long classid, final String classname,
+			final int probecount, final MethodVisitor mv) {
+		mv.visitFieldInsn(Opcodes.GETSTATIC, injectedClassName, FIELD_NAME,
+				FIELD_TYPE);
+
+		RuntimeData.generateAccessCall(classid, classname, probecount, mv);
+
+		return 6;
+	}
+
+	private static byte[] createClass(final String name) {
+		final ClassWriter cw = new ClassWriter(0);
+		cw.visit(Opcodes.V9, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PUBLIC,
+				name.replace('.', '/'), null, "java/lang/Object", null);
+		cw.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, FIELD_NAME,
+				FIELD_TYPE, null, null);
+		cw.visitEnd();
+		return cw.toByteArray();
+	}
+
+	/**
+	 * Provides access to classes {@code java.lang.invoke.MethodHandles} and
+	 * {@code java.lang.invoke.MethodHandles.Lookup} introduced in Java 8.
+	 */
+	private static class Lookup {
+
+		private final Object instance;
+
+		private Lookup(final Object instance) {
+			this.instance = instance;
+		}
+
+		/**
+		 * @return a lookup object for the caller of this method
+		 */
+		static Lookup lookup() throws Exception {
+			return new Lookup(Class //
+					.forName("java.lang.invoke.MethodHandles") //
+					.getMethod("lookup") //
+					.invoke(null));
+		}
+
+		/**
+		 * See corresponding method introduced in Java 9.
+		 *
+		 * @param targetClass
+		 *            the target class
+		 * @param lookup
+		 *            the caller lookup object
+		 * @return a lookup object for the target class, with private access
+		 */
+		static Lookup privateLookupIn(final Class<?> targetClass,
+				final Lookup lookup) throws Exception {
+			return new Lookup(Class //
+					.forName("java.lang.invoke.MethodHandles") //
+					.getMethod("privateLookupIn", Class.class,
+							Class.forName(
+									"java.lang.invoke.MethodHandles$Lookup")) //
+					.invoke(null, targetClass, lookup.instance));
+		}
+
+		/**
+		 * See corresponding method introduced in Java 9.
+		 *
+		 * @param bytes
+		 *            the class bytes
+		 * @return class
+		 */
+		Class<?> defineClass(final byte[] bytes) throws Exception {
+			return (Class<?>) Class //
+					.forName("java.lang.invoke.MethodHandles$Lookup")
+					.getMethod("defineClass", byte[].class)
+					.invoke(this.instance, new Object[] { bytes });
+		}
+
+	}
+
+}
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java
index 50cc7d7..7255395 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java
index 6d31358..5f2cc49 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -114,7 +114,7 @@
 	 * @return new runtime instance
 	 * 
 	 * @throws ClassNotFoundException
-	 *             id the given class can not be found
+	 *             if the given class can not be found
 	 */
 	public static IRuntime createFor(final Instrumentation inst,
 			final String className, final String accessFieldName)
@@ -153,7 +153,7 @@
 	 */
 	public static byte[] instrument(final byte[] source,
 			final String accessFieldName) {
-		final ClassReader reader = new ClassReader(source);
+		final ClassReader reader = InstrSupport.classReaderFor(source);
 		final ClassWriter writer = new ClassWriter(reader, 0);
 		reader.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION, writer) {
 
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java b/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java
index 4201c71..af6671e 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java b/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java
index b55c4ec..46fb6d2 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlReader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlWriter.java b/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlWriter.java
index f6a3693..8534471 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlWriter.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/RemoteControlWriter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
index 74a51dc..afb5b7f 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/SystemPropertiesRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/SystemPropertiesRuntime.java
index 5e86c9b..d7c338c 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/SystemPropertiesRuntime.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/SystemPropertiesRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/URLStreamHandlerRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/URLStreamHandlerRuntime.java
index afce724..55f9c87 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/URLStreamHandlerRuntime.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/URLStreamHandlerRuntime.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/WildcardMatcher.java b/org.jacoco.core/src/org/jacoco/core/runtime/WildcardMatcher.java
index 2b52d4b..91feaa6 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/WildcardMatcher.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/WildcardMatcher.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,9 +14,10 @@
 import java.util.regex.Pattern;
 
 /**
- * Matches strings against <code>?</code>/<code>*</code> wildcard expressions.
- * Multiple expressions can be separated with a colon (:). In this case the
- * expression matches if at least one part matches.
+ * Matches strings against glob like wildcard expressions where <code>?</code>
+ * matches any single character and <code>*</code> matches any number of any
+ * character. Multiple expressions can be separated with a colon (:). In this
+ * case the expression matches if at least one part matches.
  */
 public class WildcardMatcher {
 
@@ -47,7 +48,7 @@
 		for (final char c : expression.toCharArray()) {
 			switch (c) {
 			case '?':
-				regex.append(".?");
+				regex.append(".");
 				break;
 			case '*':
 				regex.append(".*");
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/package-info.java b/org.jacoco.core/src/org/jacoco/core/runtime/package-info.java
index 127b7a2..1ac7ccc 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/package-info.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Runtime control and execution data collection.
  */
-package org.jacoco.core.runtime;
\ No newline at end of file
+package org.jacoco.core.runtime;
diff --git a/org.jacoco.core/src/org/jacoco/core/tools/ExecDumpClient.java b/org.jacoco.core/src/org/jacoco/core/tools/ExecDumpClient.java
index c6a8007..35617b4 100644
--- a/org.jacoco.core/src/org/jacoco/core/tools/ExecDumpClient.java
+++ b/org.jacoco.core/src/org/jacoco/core/tools/ExecDumpClient.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/tools/ExecFileLoader.java b/org.jacoco.core/src/org/jacoco/core/tools/ExecFileLoader.java
index c5c4555..cf7b2e5 100644
--- a/org.jacoco.core/src/org/jacoco/core/tools/ExecFileLoader.java
+++ b/org.jacoco.core/src/org/jacoco/core/tools/ExecFileLoader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.core/src/org/jacoco/core/tools/package-info.java b/org.jacoco.core/src/org/jacoco/core/tools/package-info.java
index 7aa7e9f..c35c5f9 100644
--- a/org.jacoco.core/src/org/jacoco/core/tools/package-info.java
+++ b/org.jacoco.core/src/org/jacoco/core/tools/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,4 +14,4 @@
  * Collection of tools build on top of the JaCoCo core APIs. The tools offer
  * more high-level functionality useful for integrating JaCoCo.
  */
-package org.jacoco.core.tools;
\ No newline at end of file
+package org.jacoco.core.tools;
diff --git a/org.jacoco.doc/docroot/doc/build.html b/org.jacoco.doc/docroot/doc/build.html
index 89df34c..5764a3c 100644
--- a/org.jacoco.doc/docroot/doc/build.html
+++ b/org.jacoco.doc/docroot/doc/build.html
@@ -6,6 +6,24 @@
   <link rel="stylesheet" href="resources/doc.css" charset="UTF-8" type="text/css" />
   <link rel="stylesheet" href="../coverage/jacoco-resources/prettify.css" charset="UTF-8" type="text/css" />
   <link rel="shortcut icon" href="resources/report.gif" type="image/gif" />
+  <style>
+    table, th, td {
+      border-collapse: collapse;
+      padding: 3px;
+    }
+    table tbody tr td {
+      border-left: #b0b0b0 3px solid;
+    }
+    table tbody tr td:nth-child(2) {
+      border-left: none;
+    }
+    th {
+      background-color:#e0e0e0;
+    }
+    table tbody td:hover {
+      background: #f0f0d0;
+    }
+  </style>
   <script type="text/javascript" src="../coverage/jacoco-resources/prettify.js"></script>
   <title>JaCoCo - Build</title>
 </head>
@@ -23,10 +41,10 @@
 <p>
   The JaCoCo build is based on <a href="http://maven.apache.org/">Maven</a> and
   can be locally executed on every machine with a proper
-  <a href="environment.html">environment setup</a>. In particular you need a
-  <a href="http://maven.apache.org/">Maven 3</a> installation.  Developers are
-  encouraged to run the build before every commit to ensure consistency of the
-  source tree.
+  <a href="environment.html">environment setup</a>. In particular you need at
+  least <a href="http://maven.apache.org/">Maven 3.3.9</a> and JDK 8
+  installations. Developers are encouraged to run the build before every commit
+  to ensure consistency of the source tree.
 </p>
 
 
@@ -63,92 +81,74 @@
 </pre>
 
 
-<h2>Testing with different JDKs</h2>
+<h2>Compilation and testing with different JDKs</h2>
 
 <p>
-  Target Java version for JaCoCo builds is 1.5, however for verification
-  purposes you can execute tests using other versions. In order to do so, first
-  you should create file <code>toolchains.xml</code> in <code>~/.m2/</code>
-  directory. Here is an example of such file. For more information see
+  By default for compilation and execution of tests will be used JDK that runs
+  Maven. Alternatively you can use JDK from
   <a href="http://maven.apache.org/guides/mini/guide-using-toolchains.html">Maven
-  Guide to Using Toolchains</a>. 
+  Toolchains</a> by setting property <code>jdk.version</code>.
 </p>
 
-<pre class="source lang-xml linenums">
-&lt;?xml version="1.0" encoding="UTF8"?&gt;
-&lt;toolchains&gt;
-  &lt;toolchain&gt;
-    &lt;type&gt;jdk&lt;/type&gt;
-    &lt;provides&gt;
-      &lt;id&gt;java15&lt;/id&gt;
-      &lt;version&gt;1.5&lt;/version&gt;
-      &lt;vendor&gt;sun&lt;/vendor&gt;
-    &lt;/provides&gt;
-    &lt;configuration&gt;
-      &lt;jdkHome&gt;/usr/lib/jvm/sun-jdk-1.5&lt;/jdkHome&gt;
-    &lt;/configuration&gt;
-  &lt;/toolchain&gt;
-  &lt;toolchain&gt;
-    &lt;type&gt;jdk&lt;/type&gt;
-    &lt;provides&gt;
-      &lt;id&gt;java16&lt;/id&gt;
-      &lt;version&gt;1.6&lt;/version&gt;
-      &lt;vendor&gt;sun&lt;/vendor&gt;
-    &lt;/provides&gt;
-    &lt;configuration&gt;
-      &lt;jdkHome&gt;/usr/lib/jvm/sun-jdk-1.6&lt;/jdkHome&gt;
-    &lt;/configuration&gt;
-  &lt;/toolchain&gt;
-  &lt;toolchain&gt;
-    &lt;type&gt;jdk&lt;/type&gt;
-    &lt;provides&gt;
-      &lt;id&gt;java17&lt;/id&gt;
-      &lt;version&gt;1.7&lt;/version&gt;
-      &lt;vendor&gt;sun&lt;/vendor&gt;
-    &lt;/provides&gt;
-    &lt;configuration&gt;
-      &lt;jdkHome&gt;/usr/lib/jvm/sun-jdk-1.7&lt;/jdkHome&gt;
-    &lt;/configuration&gt;
-  &lt;/toolchain&gt;
-  &lt;toolchain&gt;
-    &lt;type&gt;jdk&lt;/type&gt;
-    &lt;provides&gt;
-      &lt;id&gt;java18&lt;/id&gt;
-      &lt;version&gt;1.8&lt;/version&gt;
-      &lt;vendor&gt;sun&lt;/vendor&gt;
-    &lt;/provides&gt;
-    &lt;configuration&gt;
-      &lt;jdkHome&gt;/usr/lib/jvm/sun-jdk-1.8&lt;/jdkHome&gt;
-    &lt;/configuration&gt;
-  &lt;/toolchain&gt;
-  &lt;toolchain&gt;
-    &lt;type&gt;jdk&lt;/type&gt;
-    &lt;provides&gt;
-      &lt;id&gt;java19&lt;/id&gt;
-      &lt;version&gt;1.9&lt;/version&gt;
-      &lt;vendor&gt;sun&lt;/vendor&gt;
-    &lt;/provides&gt;
-    &lt;configuration&gt;
-      &lt;jdkHome&gt;/usr/lib/jvm/sun-jdk-1.9&lt;/jdkHome&gt;
-    &lt;/configuration&gt;
-  &lt;/toolchain&gt;
-&lt;/toolchains&gt;
-</pre>
+<p>
+  Following table shows how modules will be compiled depending on version of JDK:
+</p>
+
+<table>
+  <thead>
+  <tr>
+    <th></th>
+    <th>JDK 5</th>
+    <th>JDK 6</th>
+    <th>JDK 7</th>
+    <th>JDK 8</th>
+    <th>JDK 9</th>
+    <th>JDK 10</th>
+    <th>JDK 11</th>
+    <th>JDK 12</th>
+  </tr>
+  </thead>
+  <tbody>
+  <tr>
+    <th>org.jacoco.core.test.validation.java8</th>
+    <td colspan="3">excluded from build</td>
+    <td colspan="5">compiled into bytecode version 52 (Java 8)</td>
+  </tr>
+  <tr>
+    <th>org.jacoco.core.test.validation.java7</th>
+    <td colspan="2">excluded from build</td>
+    <td colspan="6" rowspan="2">compiled into bytecode version 51 (Java 7)</td>
+  </tr>
+  <tr>
+    <th>org.jacoco.core.test.validation.groovy</th>
+    <td colspan="2">excluded from build</td>
+  </tr>
+  <tr>
+    <th>org.jacoco.core.test.validation.kotlin</th>
+    <td colspan="1">excluded from build</td>
+    <td colspan="6">compiled into bytecode version 50 (Java 6)</td>
+    <td rowspan="2">compiled into bytecode version 51 (Java 7)</td>
+  </tr>
+  <tr>
+    <th>all other modules</th>
+    <td colspan="4">compiled into bytecode version 49 (Java 5)</td>
+    <td colspan="3">compiled into bytecode version 50 (Java 6)</td>
+  </tr>
+  </tbody>
+</table>
 
 <p>
-  Now you should be able to execute maven build with specified version of JDK:
+  Alternatively you can specify bytecode version for all modules using property
+  <code>bytecode.version</code>.
+</p>
+
+<p>
+  For example to use JDK 10 from Maven Toolchains and compile all modules
+  into bytecode version 53 (Java 9):
 </p>
 
 <pre>
-  mvn clean install -Djdk.version=<i>version</i>
-</pre>
-
-<p>
-  Location of <code>toolchains.xml</code> can be set via an option:
-</p>
-
-<pre>
-  mvn --toolchains <i>path</i> clean install -Djdk.version=<i>version</i>
+  mvn clean install -Djdk.version=10 -Dbytecode.version=9
 </pre>
 
 <p>
@@ -160,20 +160,19 @@
 </pre>
 
 <p>
-  In addition JaCoCo can be compiled for higher class file versions than 1.5
-  specifying the property <code>bytecode.version</code>. Note that in this case
-  the version of the JVM running Maven must be at least the version of the
-  specified bytecode version as this JVM is also running the tests. Combining
-  these options JaCoCo is regularly tested with the following setups:
+  Combining these options JaCoCo is regularly tested with the following setups:
 </p>
 
 <ul>
-  <li>Maven with 1.5 JDK: <code>mvn clean install -Djdk.version=1.5 -Dbytecode.version=1.5</code></li>
-  <li>Maven with 1.6 JDK: <code>mvn clean install -Djdk.version=1.6 -Dbytecode.version=1.6</code></li>
-  <li>Maven with 1.7 JDK: <code>mvn clean install -Djdk.version=1.7 -Dbytecode.version=1.7</code></li>
-  <li>Maven with 1.8 JDK: <code>mvn clean install -Djdk.version=1.8 -Dbytecode.version=1.8</code></li>
-  <li>Maven with 1.8 JDK: <code>mvn clean install -Djdk.version=1.8 -Dbytecode.version=1.8 -Decj</code></li>
-  <li>Maven with 1.9 JDK: <code>mvn clean install -Djdk.version=1.9 -Dbytecode.version=1.9</code></li>
+  <li><code>mvn clean install -Djdk.version=5 -Dbytecode.version=5</code></li>
+  <li><code>mvn clean install -Djdk.version=6 -Dbytecode.version=6</code></li>
+  <li><code>mvn clean install -Djdk.version=7 -Dbytecode.version=7</code></li>
+  <li><code>mvn clean install -Djdk.version=8 -Dbytecode.version=8</code></li>
+  <li><code>mvn clean install -Djdk.version=8 -Dbytecode.version=8 -Decj</code></li>
+  <li><code>mvn clean install -Djdk.version=9 -Dbytecode.version=9</code></li>
+  <li><code>mvn clean install -Djdk.version=10 -Dbytecode.version=10</code></li>
+  <li><code>mvn clean install -Djdk.version=11 -Dbytecode.version=11</code></li>
+  <li><code>mvn clean install -Djdk.version=12 -Dbytecode.version=12</code></li>
 </ul>
 
 
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 37c9372..1dfa98d 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -18,6 +18,201 @@
 
 <h1>Change History</h1>
 
+<h2>Release 0.8.4 (2019/05/08)</h2>
+
+<h3>New Features</h3>
+<ul>
+  <li>JaCoCo now officially supports Java 12</li>
+  <li>Instrumentation does not add synthetic field to Java 11+ class files,
+      however still adds synthetic method
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/845">#845</a>).</li>
+  <li>Branches added by the Kotlin compiler version 1.3.30 for suspending lambdas
+      and functions are filtered out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/849">#849</a>).</li>
+</ul>
+
+<h3>Fixed bugs</h3>
+<ul>
+  <li>Fixed incorrect update of frames caused by bug in ASM library in case of
+      arrays with more than 7 dimensions
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/839">#839</a>).</li>
+  <li>Fixed regression, which was introduced in 0.8.3 -
+      <code>module-info.class</code> should be excluded from analysis to not cause
+      <code>IllegalStateException</code>
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/859">#859</a>).</li>
+</ul>
+
+<h3>API Changes</h3>
+<ul>
+    <li>Methods <code>Instrumenter.instrument(org.objectweb.asm.ClassReader)</code>
+        and <code>Analyzer.analyzeClass(org.objectweb.asm.ClassReader)</code>
+        were removed
+        (GitHub <a href="https://github.com/jacoco/jacoco/issues/850">#850</a>).</li>
+</ul>
+
+<h3>Non-functional Changes</h3>
+<ul>
+  <li>JaCoCo now depends on ASM 7.1
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/851">#851</a>).</li>
+</ul>
+
+<h2>Release 0.8.3 (2019/01/23)</h2>
+
+<h3>New Features</h3>
+<ul>
+  <li>jacoco-maven-plugin now requires at least Maven 3.0
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/821">#821</a>).</li>
+  <li>JaCoCo now officially supports Java 11
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/760">#760</a>).</li>
+  <li>Experimental support for Java 13 class files
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/835">#835</a>).</li>
+  <li>Branch added by the Kotlin compiler for "unsafe" cast operator is filtered
+      out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/761">#761</a>).</li>
+  <li>Branch added by the Kotlin compiler for not-null assertion operator is
+      filtered out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/815">#815</a>).</li>
+  <li>Instructions inlined by Kotlin compiler are filtered out during generation
+      of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/764">#764</a>).</li>
+  <li>Branches added by the Kotlin compiler for suspending lambdas and functions
+      are filtered out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/802">#802</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/803">#803</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/809">#809</a>).</li>
+  <li>Classes and methods annotated by annotation whose retention policy is
+      <code>runtime</code> or <code>class</code> and whose simple name contains
+      "Generated" (previously equality was required) are filtered out during
+      generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/822">#822</a>).</li>
+  <li>HTML report shows message when source file can't be found
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/801">#801</a>).</li>
+  <li>HTML report shows message when class has no debug information
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/818">#818</a>).</li>
+  <li>HTML report shows message when analyzed class does not match executed
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/819">#819</a>).</li>
+  <li>HTML report shows message when no class files specified and when
+      none of the analyzed classes contain code relevant for code coverage
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/833">#833</a>).</li>
+  <li>Empty class and sourcefile nodes are preserved and available in XML report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/817">#817</a>).</li>
+  <li>Agent avoids conflicts with other agents when running on Java 9+
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/829">#829</a>).</li>
+</ul>
+
+<h3>Fixed Bugs</h3>
+<ul>
+  <li><code>synthetic</code> methods that contain values of default arguments
+      in Kotlin should not be ignored
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/774">#774</a>).</li>
+  <li><code>synthetic</code> methods that represent <code>suspend</code>
+      functions in Kotlin should not be ignored
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/804">#804</a>).</li>
+  <li>Removed misleading parameters <code>includes</code> and
+      <code>excludes</code> from <code>dump</code>, <code>merge</code> and
+      <code>restore-instrumented-classes</code> goals of jacoco-maven-plugin,
+      because they have no effect
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/827">#827</a>).</li>
+</ul>
+
+<h3>Non-functional Changes</h3>
+<ul>
+  <li>JaCoCo now depends on ASM 7.0
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/760">#760</a>).</li>
+</ul>
+
+<h2>Release 0.8.2 (2018/08/21)</h2>
+
+<h3>New Features</h3>
+<ul>
+  <li>Experimental support for Java 11 and Java 12 class files, including
+      JEP 12 "preview features"
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/719">#719</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/738">#738</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/743">#743</a>).</li>
+  <li>Branches and instructions generated by javac 11 for try-with-resources
+      statement are filtered out
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/669">#669</a>).</li>
+  <li>Synthetic classes are filtered out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/668">#668</a>).</li>
+  <li>Part of bytecode generated by ECJ for <code>switch</code> statements on
+      <code>java.lang.String</code> values is filtered out during generation of
+      report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/735">#735</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/741">#741</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/746">#746</a>).</li>
+  <li>Methods added by the Kotlin compiler that do not have line numbers are
+      filtered out during generation of report. Idea and implementation by
+      Nikolay Krasko
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/689">#689</a>).</li>
+  <li>Branch added by the Kotlin compiler for reading from <code>lateinit</code>
+      property is filtered out during generation of report. Implementation by
+      Fabian Mastenbroek
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/707">#707</a>).</li>
+  <li>Bytecode generated by Kotlin compiler for implicit <code>else</code> of
+      <code>when</code> expressions that list all cases of <code>enum</code> or
+      <code>sealed class</code> is filtered out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/721">#721</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/729">#729</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/749">#749</a>).</li>
+  <li>Additional bytecode generated by Kotlin compiler for <code>when</code>
+      expressions on <code>kotlin.String</code> values is filtered out during
+      generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/737">#737</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/746">#746</a>).</li>
+  <li>Classes and methods annotated with annotation whose retention policy
+      is <code>runtime</code> or <code>class</code> and whose simple name
+      is <code>Generated</code> are filtered out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/731">#731</a>).</li>
+  <li>Maven goal <code>report-aggregate</code> now also considers dependencies
+      specified using version range. Idea and implementation by Lukas Krejc
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/658">#658</a>).</li>
+</ul>
+
+<h3>Fixed Bugs</h3>
+<ul>
+  <li>Don't insert stackmap frames into class files with version &lt; 1.6,
+      this fixes regression which was introduced in version 0.6.5
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/667">#667</a>).</li>
+  <li>Question mark in filter expressions now correctly matches exactly one character
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/672">#672</a>).</li>
+  <li>Part of bytecode that javac generates for <code>switch</code> statement on
+      <code>java.lang.String</code> values with a small number cases is now correctly
+      filtered out during generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/730">#730</a>).</li>
+</ul>
+
+<h3>Non-functional Changes</h3>
+<ul>
+  <li>JaCoCo now depends on ASM 6.2.1
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/706">#706</a>,
+      <a href="https://github.com/jacoco/jacoco/issues/725">#725</a>).</li>
+  <li>Improved error message when already instrumented classes are used for
+      instrumentation or analysis
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/703">#703</a>).</li>
+  <li>JaCoCo build now requires at least Maven 3.3.9 and JDK 8
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/711">#711</a>).</li>
+</ul>
+
+<h3>API Changes</h3>
+<ul>
+  <li>The XML report now has an optional attribute <code>sourcefilename</code>
+      on the <code>class</code> element to allow unambiguously relate classes
+      to source files. The JaCoCo DTD version has been updated to 1.1
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/702">#702</a>).</li>
+</ul>
+
+<h2>Release 0.8.1 (2018/03/21)</h2>
+
+<h3>New Features</h3>
+<ul>
+  <li>JaCoCo now supports Java 10
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/629">#629</a>).</li>
+  <li>Empty constructor without parameters in enum is filtered out during
+      generation of report
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/649">#649</a>).</li>
+</ul>
+
 <h2>Release 0.8.0 (2018/01/02)</h2>
 
 <h3>New Features</h3>
diff --git a/org.jacoco.doc/docroot/doc/environment.html b/org.jacoco.doc/docroot/doc/environment.html
index 33df73a..77c06a0 100644
--- a/org.jacoco.doc/docroot/doc/environment.html
+++ b/org.jacoco.doc/docroot/doc/environment.html
@@ -66,15 +66,16 @@
 <h3>JRE/JDK</h3>
 
 <p>
-  The minimum supported JRE version for JaCoCo is Java 1.5. To guarantee
-  compatibility JaCoCo builds should always be executed against Java 1.5 JDK. In
-  addition we run builds with 1.6, 1.7, 1.8 and 1.9 JDKs.
+  The minimum supported JRE version for JaCoCo is Java 5. To guarantee
+  compatibility JaCoCo release builds should always be executed using JDK 5.
+  In addition we run builds with 6, 7, 8, 9, 10, 11 and 12 JDKs.
 </p>
 
 <h3>Build</h3>
 
 <p>
-  The JaCoCo build is based on <a href="http://maven.apache.org/">Maven 3</a>.
+  The JaCoCo build is based on <a href="http://maven.apache.org/">Maven</a>
+  and requires at least Maven 3.3.9 and JDK 8.
   See the <a href="build.html">build description</a> for details.
 </p>
 
@@ -115,7 +116,7 @@
 
 <p>
   We track quality issues with our source code with
-  <a href="http://nemo.sonarqube.org/dashboard/index/org.jacoco:org.jacoco.build">SonarQube</a>.
+  <a href="https://sonarcloud.io/dashboard?id=org.jacoco:org.jacoco.build">SonarQube</a>.
 </p>
 
 <h3>Communication</h3>
diff --git a/org.jacoco.doc/docroot/doc/faq.html b/org.jacoco.doc/docroot/doc/faq.html
index 8eb14e4..2e48734 100644
--- a/org.jacoco.doc/docroot/doc/faq.html
+++ b/org.jacoco.doc/docroot/doc/faq.html
@@ -23,6 +23,20 @@
   before.
 </p>
 
+<h3>When will feature X be released?</h3>
+<p>
+  JaCoCo is maintained by volunteers in their free time. Since we cannot
+  guarantee free capacity, we do not commit to particular release dates.
+  Typically, you can expect a couple of releases every year.
+</p>
+<p>  
+  In the <a href="changes.html">change log</a>, you can see all features
+  that have been been implemented in master branch and will be available
+  with the next release. And in the meantime you can test latest build of
+  of master branch (<a href="repo.html">Maven SNAPSHOT</a>) and provide
+  <a href="support.html">feedback</a> to us.
+</p>
+
 <h3>Does JaCoCo have a plug-in for [Eclipse|Netbeans|Whatever...]?</h3>
 <p>
   See <a href="integrations.html">this list</a> for current integrations with
@@ -31,7 +45,7 @@
 
 <h3>What Java versions are supported by JaCoCo?</h3>
 <p>
-  JaCoCo supports Java class files from version 1.0 to 9. However the minimum
+  JaCoCo supports Java class files from version 1.0 to 12. However the minimum
   JRE version required by the JaCoCo runtime (e.g. the agent) and the JaCoCo
   tools is 1.5. Also note that class files under test from version 1.6 and above
   have to contain valid stackmap frames.
@@ -85,22 +99,22 @@
   ids</a> for a detailed discussion.
 </p>
 
-<h3>Why are Java interface types not shown in the coverage reports?</h3>
+<h3>Why are abstract methods not shown in coverage reports?</h3>
 <p>
-  Java interface methods do not contain code, therefore code coverage cannot
-  be evaluated. Indeed code coverage is recorded for the implementation classes.
-  The same applies to abstract methods in abstract classes.
+  Abstract methods do not contain code, therefore code coverage cannot be
+  evaluated. Indeed code coverage is recorded for subclasses implementing these
+  methods. The same applies to non-default methods in interfaces.
 </p>
 
 <h3>Can I collect coverage information without stopping the JVM?</h3>
 <p>
-  Yes, there are two possible ways: The JaCoCo <a href="agent.html">agent</a>
+  Yes, there are three possible ways: The JaCoCo <a href="agent.html">agent</a>
   can be configured for remote control via TCP/IP sockets. This allows to
   collect execution data at any point in time from a running JVM. The
-  <a href="ant.html#dump"><code>dump</code> Ant task</a> or the
-  <a href="dump-mojo.html"><code>dump</code> Maven goal</a> can be used to
-  request dumps. The remote control feature also allows you to reset execution
-  data.
+  <a href="ant.html#dump"><code>dump</code> Ant task</a>, the
+  <a href="dump-mojo.html"><code>dump</code> Maven goal</a> and the
+  <a href="cli.html">command line interface</a> can be used to request dumps.
+  The remote control feature also allows you to reset execution data.
 </p>
 <p>
   Alternatively the JaCoCo <a href="agent.html">agent</a> can be configured to
@@ -108,6 +122,10 @@
   <code><a href="./api/org/jacoco/agent/rt/IAgent.html">org.jacoco:type=Runtime</a></code>
   provides operations to dump and reset execution data at any point in time.
 </p>
+<p>
+  In addition JaCoCo provides a <a href="./api/org/jacoco/agent/rt/RT.html">Java API</a>
+  to directly access the runtime within the JVM executing the tests.
+</p>
 
 <h3>My code uses reflection. Why does it fail when I execute it with JaCoCo?</h3>
 <p>
diff --git a/org.jacoco.doc/docroot/doc/implementation.html b/org.jacoco.doc/docroot/doc/implementation.html
index b1eda7f..668b7dd 100644
--- a/org.jacoco.doc/docroot/doc/implementation.html
+++ b/org.jacoco.doc/docroot/doc/implementation.html
@@ -210,12 +210,18 @@
     public static field to an existing JRE class through instrumentation. Unlike
     the other methods above this is only possible for environments where a Java
     agent is active.</li> 
+  <li><b><code>InjectedClassRuntime</code></b>: This approach defines a new class
+    using <code>java.lang.invoke.MethodHandles.Lookup.defineClass</code>
+    introduced in Java 9.</li>
 </ul>
 
 <p>
-  The current JaCoCo Java agent implementation uses the 
-  <code>ModifiedSystemClassRuntime</code> adding a field to the class
-  <code>java.lang.UnknownError</code>. Versions 0.5.0 - 0.7.9 were adding field
+  Starting from version 0.8.3 JaCoCo Java agent implementation uses the
+  <code>InjectedClassRuntime</code> to define new class in bootstrap class
+  loader when running on JRE 9 and higher, otherwise uses
+  <code>ModifiedSystemClassRuntime</code> to add field to an existing JRE class.
+  Starting from version 0.8.0 field is added to the class
+  <code>java.lang.UnknownError</code>, versions 0.5.0 - 0.7.9 were adding field
   to the class <code>java.util.UUID</code>, having bigger chance of conflict
   with other agents.
 </p>
diff --git a/org.jacoco.doc/docroot/doc/integrations.html b/org.jacoco.doc/docroot/doc/integrations.html
index 2797013..6018891 100644
--- a/org.jacoco.doc/docroot/doc/integrations.html
+++ b/org.jacoco.doc/docroot/doc/integrations.html
@@ -102,6 +102,10 @@
     </tr>
     <tr>
       <td><a href="http://jenkins-ci.org/">Jenkins</a></td>
+      <td>GSoC project of Shenyu Zheng, see <a href="https://github.com/jenkinsci/code-coverage-api-plugin">project page</a></td>
+    </tr>
+    <tr>
+      <td><a href="http://jenkins-ci.org/">Jenkins</a></td>
       <td>GSoC project of Ognjen Bubalo, see <a href="https://wiki.jenkins-ci.org/display/JENKINS/JaCoCo+Plugin">documentation</a></td>
     </tr>
     <tr>
diff --git a/org.jacoco.doc/docroot/doc/maven.html b/org.jacoco.doc/docroot/doc/maven.html
index 0546c1b..5284978 100644
--- a/org.jacoco.doc/docroot/doc/maven.html
+++ b/org.jacoco.doc/docroot/doc/maven.html
@@ -73,7 +73,7 @@
 </p>
 
 <ul>
-  <li>Maven 2.1.0 or higher and</li>
+  <li>Maven 3.0 or higher and</li>
   <li>Java 1.5 or higher (for both, the Maven runtime and the test executor).</li>
 </ul>
 
diff --git a/org.jacoco.doc/docroot/doc/resources/doc.css b/org.jacoco.doc/docroot/doc/resources/doc.css
index 3e62c59..ec89c32 100644
--- a/org.jacoco.doc/docroot/doc/resources/doc.css
+++ b/org.jacoco.doc/docroot/doc/resources/doc.css
@@ -1,225 +1,225 @@
-.el_jar {

-  padding-left:18px;

-  background-image:url(jar.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_test {

-  padding-left:18px;

-  background-image:url(test.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_testsuite {

-  padding-left:18px;

-  background-image:url(testsuite.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-p.intro {

-  margin-left:20px;

-  padding-left:4px;

-  border-left:#cccca0 4px solid;

-  font-style:italic

-}

-

-p.hint {

-  margin-left:20px;

-  padding-left:4px;

-  border-left:#cccca0 4px solid;

-  font-style:italic

-}

-

-.high {

-  background-color:#ffff80;

-}

-

-div#content a[href^='http://'], a[href^='https://'] {

-  display:inline-block;

-  padding-left:15px;

-  background:transparent url(extern.gif) center left no-repeat;

-}

-

-/* === Definitions from report.css start here: === */ 

-

-body, td {

-  font-family:sans-serif;

-  font-size:10pt;

-}

-

-h1 {

-  font-weight:bold;

-  font-size:18pt;

-}

-

-.breadcrumb {

-  border:#d6d3ce 1px solid;

-  padding:2px 4px 2px 4px;

-}

-

-

-.el_report {

-  padding-left:18px;

-  background-image:url(report.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_group {

-  padding-left:18px;

-  background-image:url(group.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_bundle {

-  padding-left:18px;

-  background-image:url(bundle.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_package {

-  padding-left:18px;

-  background-image:url(package.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_class {

-  padding-left:18px;

-  background-image:url(class.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_source {

-  padding-left:18px;

-  background-image:url(source.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_method {

-  padding-left:18px;

-  background-image:url(method.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-.el_session {

-  padding-left:18px;

-  background-image:url(session.gif);

-  background-position:left center;

-  background-repeat:no-repeat;

-}

-

-pre.source {

-  border:#d6d3ce 1px solid;

-  font-family:monospace;

-}

-

-pre.source ol {

-  margin-bottom: 0px;

-  margin-top: 0px;

-}

-

-pre.source li {

-  border-left: 1px solid #D6D3CE;

-  color: #A0A0A0;

-  padding-left: 0px;

-}

-

-pre.source span.fc {

-  background-color:#ccffcc;

-}

-

-pre.source span.nc {

-  background-color:#ffcccc;

-}

-

-pre.source span.pc {

-  background-color:#ffffcc;

-}

-

-

-table.coverage {

-  empty-cells:show;

-  border-collapse:collapse; 

-}

-

-table.coverage thead {

-  background-color:#e0e0e0;

-}

-

-table.coverage thead td {

-  white-space:nowrap;

-  padding:2px 8px 0px 8px;

-  border-bottom:#b0b0b0 1px solid;

-}

-

-table.coverage thead td.ctr1 {

-  text-align:right;

-  padding-right:4px;

-  border-left:#cccccc 1px solid;

-}

-

-table.coverage thead td.ctr2 {

-  text-align:right;

-  padding-left:4px;

-}

-

-table.coverage tbody td {

-  vertical-align:top;

-  padding:2px 8px 2px 8px;

-  border-bottom:#d6d3ce 1px solid;

-}

-

-table.coverage tbody tr:hover { 

-  background: #f0f0d0 !important;

-}

-

-table.coverage tbody td.ctr1 {

-  text-align:right;

-  padding-right:4px;

-  border-left:#e8e8e8 1px solid;

-}

-

-table.coverage tbody td.ctr2 {

-  text-align:right;

-  padding-left:4px;

-}

-

-table.coverage tfoot td {

-  padding:2px 8px 2px 8px;

-}

-

-table.coverage tfoot td.ctr1 {

-  text-align:right;

-  padding-right:4px;

-  border-left:#e8e8e8 1px solid;

-}

-

-table.coverage tfoot td.ctr2 {

-  text-align:right;

-  padding-left:4px;

-}

-

-.footer {

-  margin-top:20px;

-  border-top:#d6d3ce 1px solid;

-  padding-top:2px;

-  font-size:8pt;

-  color:#a0a0a0;

-}

-

-.footer a {

-  color:#a0a0a0;

-}

-

-.right {

-  float:right;

-}

+.el_jar {
+  padding-left:18px;
+  background-image:url(jar.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_test {
+  padding-left:18px;
+  background-image:url(test.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_testsuite {
+  padding-left:18px;
+  background-image:url(testsuite.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+p.intro {
+  margin-left:20px;
+  padding-left:4px;
+  border-left:#cccca0 4px solid;
+  font-style:italic
+}
+
+p.hint {
+  margin-left:20px;
+  padding-left:4px;
+  border-left:#cccca0 4px solid;
+  font-style:italic
+}
+
+.high {
+  background-color:#ffff80;
+}
+
+div#content a[href^='http://'], a[href^='https://'] {
+  display:inline-block;
+  padding-left:15px;
+  background:transparent url(extern.gif) center left no-repeat;
+}
+
+/* === Definitions from report.css start here: === */ 
+
+body, td {
+  font-family:sans-serif;
+  font-size:10pt;
+}
+
+h1 {
+  font-weight:bold;
+  font-size:18pt;
+}
+
+.breadcrumb {
+  border:#d6d3ce 1px solid;
+  padding:2px 4px 2px 4px;
+}
+
+
+.el_report {
+  padding-left:18px;
+  background-image:url(report.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_group {
+  padding-left:18px;
+  background-image:url(group.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_bundle {
+  padding-left:18px;
+  background-image:url(bundle.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_package {
+  padding-left:18px;
+  background-image:url(package.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_class {
+  padding-left:18px;
+  background-image:url(class.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_source {
+  padding-left:18px;
+  background-image:url(source.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_method {
+  padding-left:18px;
+  background-image:url(method.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+.el_session {
+  padding-left:18px;
+  background-image:url(session.gif);
+  background-position:left center;
+  background-repeat:no-repeat;
+}
+
+pre.source {
+  border:#d6d3ce 1px solid;
+  font-family:monospace;
+}
+
+pre.source ol {
+  margin-bottom: 0px;
+  margin-top: 0px;
+}
+
+pre.source li {
+  border-left: 1px solid #D6D3CE;
+  color: #A0A0A0;
+  padding-left: 0px;
+}
+
+pre.source span.fc {
+  background-color:#ccffcc;
+}
+
+pre.source span.nc {
+  background-color:#ffcccc;
+}
+
+pre.source span.pc {
+  background-color:#ffffcc;
+}
+
+
+table.coverage {
+  empty-cells:show;
+  border-collapse:collapse; 
+}
+
+table.coverage thead {
+  background-color:#e0e0e0;
+}
+
+table.coverage thead td {
+  white-space:nowrap;
+  padding:2px 8px 0px 8px;
+  border-bottom:#b0b0b0 1px solid;
+}
+
+table.coverage thead td.ctr1 {
+  text-align:right;
+  padding-right:4px;
+  border-left:#cccccc 1px solid;
+}
+
+table.coverage thead td.ctr2 {
+  text-align:right;
+  padding-left:4px;
+}
+
+table.coverage tbody td {
+  vertical-align:top;
+  padding:2px 8px 2px 8px;
+  border-bottom:#d6d3ce 1px solid;
+}
+
+table.coverage tbody tr:hover { 
+  background: #f0f0d0 !important;
+}
+
+table.coverage tbody td.ctr1 {
+  text-align:right;
+  padding-right:4px;
+  border-left:#e8e8e8 1px solid;
+}
+
+table.coverage tbody td.ctr2 {
+  text-align:right;
+  padding-left:4px;
+}
+
+table.coverage tfoot td {
+  padding:2px 8px 2px 8px;
+}
+
+table.coverage tfoot td.ctr1 {
+  text-align:right;
+  padding-right:4px;
+  border-left:#e8e8e8 1px solid;
+}
+
+table.coverage tfoot td.ctr2 {
+  text-align:right;
+  padding-left:4px;
+}
+
+.footer {
+  margin-top:20px;
+  border-top:#d6d3ce 1px solid;
+  padding-top:2px;
+  font-size:8pt;
+  color:#a0a0a0;
+}
+
+.footer a {
+  color:#a0a0a0;
+}
+
+.right {
+  float:right;
+}
diff --git a/org.jacoco.doc/pom.xml b/org.jacoco.doc/pom.xml
index b866ad1..740b0ca 100644
--- a/org.jacoco.doc/pom.xml
+++ b/org.jacoco.doc/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
diff --git a/org.jacoco.examples.test/pom.xml b/org.jacoco.examples.test/pom.xml
index 7605ff3..7335864 100644
--- a/org.jacoco.examples.test/pom.xml
+++ b/org.jacoco.examples.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
diff --git a/org.jacoco.examples.test/src/org/jacoco/examples/ClassInfoTest.java b/org.jacoco.examples.test/src/org/jacoco/examples/ClassInfoTest.java
index 1147acd..baed329 100644
--- a/org.jacoco.examples.test/src/org/jacoco/examples/ClassInfoTest.java
+++ b/org.jacoco.examples.test/src/org/jacoco/examples/ClassInfoTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples.test/src/org/jacoco/examples/ConsoleOutput.java b/org.jacoco.examples.test/src/org/jacoco/examples/ConsoleOutput.java
index ba26178..7908116 100644
--- a/org.jacoco.examples.test/src/org/jacoco/examples/ConsoleOutput.java
+++ b/org.jacoco.examples.test/src/org/jacoco/examples/ConsoleOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples.test/src/org/jacoco/examples/CoreTutorialTest.java b/org.jacoco.examples.test/src/org/jacoco/examples/CoreTutorialTest.java
index 3b37d9f..462d17e 100644
--- a/org.jacoco.examples.test/src/org/jacoco/examples/CoreTutorialTest.java
+++ b/org.jacoco.examples.test/src/org/jacoco/examples/CoreTutorialTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples.test/src/org/jacoco/examples/ExecDumpTest.java b/org.jacoco.examples.test/src/org/jacoco/examples/ExecDumpTest.java
index 9de08ab..348b43f 100644
--- a/org.jacoco.examples.test/src/org/jacoco/examples/ExecDumpTest.java
+++ b/org.jacoco.examples.test/src/org/jacoco/examples/ExecDumpTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples.test/src/org/jacoco/examples/MBeanClientTest.java b/org.jacoco.examples.test/src/org/jacoco/examples/MBeanClientTest.java
index aba39eb..dcd905d 100644
--- a/org.jacoco.examples.test/src/org/jacoco/examples/MBeanClientTest.java
+++ b/org.jacoco.examples.test/src/org/jacoco/examples/MBeanClientTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples.test/src/test/resources/verify-it.groovy b/org.jacoco.examples.test/src/test/resources/verify-it.groovy
index 85ec205..a1b346a 100644
--- a/org.jacoco.examples.test/src/test/resources/verify-it.groovy
+++ b/org.jacoco.examples.test/src/test/resources/verify-it.groovy
@@ -1,4 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Mirko Friedenhagen - initial API and implementation
+ *
+ *******************************************************************************/
 File realBaseDir = new File(basedir, "../../../target/it-it/build");
 assert new File(realBaseDir, "target/site/jacoco/index.html").exists();
 assert new File(realBaseDir, "target/site/jacoco-it/index.html").exists();
-return true;
\ No newline at end of file
+return true;
diff --git a/org.jacoco.examples.test/src/test/resources/verify-offline.groovy b/org.jacoco.examples.test/src/test/resources/verify-offline.groovy
index 247fc4a..0f00234 100644
--- a/org.jacoco.examples.test/src/test/resources/verify-offline.groovy
+++ b/org.jacoco.examples.test/src/test/resources/verify-offline.groovy
@@ -1,5 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Mirko Friedenhagen - initial API and implementation
+ *
+ *******************************************************************************/
 File realBaseDir = new File(basedir, "../../../target/it-offline/build");
 assert new File(realBaseDir, "target/site/jacoco/index.html").exists();
 assert !new File(realBaseDir, "target/site/jacoco-it/index.html").exists();
 assert new File(realBaseDir, "build.log").getText().contains(":restore-instrumented-classes");
-return true;
\ No newline at end of file
+return true;
diff --git a/org.jacoco.examples.test/src/test/resources/verify.groovy b/org.jacoco.examples.test/src/test/resources/verify.groovy
index 4fa6fa0..a181e3c 100644
--- a/org.jacoco.examples.test/src/test/resources/verify.groovy
+++ b/org.jacoco.examples.test/src/test/resources/verify.groovy
@@ -1,4 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Mirko Friedenhagen - initial API and implementation
+ *
+ *******************************************************************************/
 File realBaseDir = new File(basedir, "../../../target/it/build");
 assert new File(realBaseDir, "target/site/jacoco/index.html").exists();
 assert !new File(realBaseDir, "target/site/jacoco-it/index.html").exists();
-return true;
\ No newline at end of file
+return true;
diff --git a/org.jacoco.examples/assembly.xml b/org.jacoco.examples/assembly.xml
index d372ca2..d712e10 100644
--- a/org.jacoco.examples/assembly.xml
+++ b/org.jacoco.examples/assembly.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/build-offline.xml b/org.jacoco.examples/build/build-offline.xml
index 4a4c851..9a99908 100644
--- a/org.jacoco.examples/build/build-offline.xml
+++ b/org.jacoco.examples/build/build-offline.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -95,4 +95,4 @@
 
 	<target name="rebuild" depends="clean,compile,instrument,test,report" />
 
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.examples/build/build.xml b/org.jacoco.examples/build/build.xml
index c7895dd..a148b4b 100644
--- a/org.jacoco.examples/build/build.xml
+++ b/org.jacoco.examples/build/build.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -81,4 +81,4 @@
 
 	<target name="rebuild" depends="clean,compile,test,report" />
 
-</project>
\ No newline at end of file
+</project>
diff --git a/org.jacoco.examples/build/pom-it.xml b/org.jacoco.examples/build/pom-it.xml
index 91886d8..e66ad4a 100644
--- a/org.jacoco.examples/build/pom-it.xml
+++ b/org.jacoco.examples/build/pom-it.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -74,12 +74,10 @@
             </goals>
             <configuration>
               <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <element>BUNDLE</element>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>COMPLEXITY</counter>
                       <value>COVEREDRATIO</value>
                       <minimum>0.60</minimum>
diff --git a/org.jacoco.examples/build/pom-offline.xml b/org.jacoco.examples/build/pom-offline.xml
index 0763f4a..b008b96 100644
--- a/org.jacoco.examples/build/pom-offline.xml
+++ b/org.jacoco.examples/build/pom-offline.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -75,12 +75,10 @@
             </goals>
             <configuration>
               <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <element>BUNDLE</element>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>COMPLEXITY</counter>
                       <value>COVEREDRATIO</value>
                       <minimum>0.60</minimum>
diff --git a/org.jacoco.examples/build/pom.xml b/org.jacoco.examples/build/pom.xml
index 26c6033..66ad9b3 100644
--- a/org.jacoco.examples/build/pom.xml
+++ b/org.jacoco.examples/build/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -62,12 +62,10 @@
             </goals>
             <configuration>
               <rules>
-                <!-- implementation is needed only for Maven 2 -->
-                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                <rule>
                   <element>BUNDLE</element>
                   <limits>
-                    <!-- implementation is needed only for Maven 2 -->
-                    <limit implementation="org.jacoco.report.check.Limit">
+                    <limit>
                       <counter>COMPLEXITY</counter>
                       <value>COVEREDRATIO</value>
                       <minimum>0.60</minimum>
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Add.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Add.java
index a1216a4..be17f50 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Add.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Add.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Const.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Const.java
index 286c653..7676760 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Const.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Const.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Div.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Div.java
index f087ffc..67c13ce 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Div.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Div.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/IExpression.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/IExpression.java
index dd17902..81be56a 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/IExpression.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/IExpression.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Mul.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Mul.java
index ac7e960..6342112 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Mul.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Mul.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Sub.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Sub.java
index 0abca96..5b23fcc 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Sub.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/expressions/Sub.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/ExpressionParser.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/ExpressionParser.java
index 893338e..496d860 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/ExpressionParser.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/ExpressionParser.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/Main.java b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/Main.java
index e82312a..c28767d 100644
--- a/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/Main.java
+++ b/org.jacoco.examples/build/src/main/java/org/jacoco/examples/parser/Main.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserIT.java b/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserIT.java
index 1e2af43..e446018 100644
--- a/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserIT.java
+++ b/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserIT.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserTest.java b/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserTest.java
index 501b44f..88b2c84 100755
--- a/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserTest.java
+++ b/org.jacoco.examples/build/src/test/java/org/jacoco/examples/parser/ExpressionParserTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/pom.xml b/org.jacoco.examples/pom.xml
index 64fd7aa..f942c77 100644
--- a/org.jacoco.examples/pom.xml
+++ b/org.jacoco.examples/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
diff --git a/org.jacoco.examples/src/org/jacoco/examples/ClassInfo.java b/org.jacoco.examples/src/org/jacoco/examples/ClassInfo.java
index a6acca4..690293f 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/ClassInfo.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/ClassInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/src/org/jacoco/examples/CoreTutorial.java b/org.jacoco.examples/src/org/jacoco/examples/CoreTutorial.java
index 26d307b..708955f 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/CoreTutorial.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/CoreTutorial.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/src/org/jacoco/examples/ExecDump.java b/org.jacoco.examples/src/org/jacoco/examples/ExecDump.java
index 946aad0..1a0342f 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/ExecDump.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/ExecDump.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataClient.java b/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataClient.java
index 47db6bd..0db3f59 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataClient.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataClient.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataServer.java b/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataServer.java
index ae4286b..9fb2dcd 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataServer.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/ExecutionDataServer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/src/org/jacoco/examples/MBeanClient.java b/org.jacoco.examples/src/org/jacoco/examples/MBeanClient.java
index 9394f5b..c45bece 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/MBeanClient.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/MBeanClient.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java b/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java
index 9316d63..13a9706 100644
--- a/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java
+++ b/org.jacoco.examples/src/org/jacoco/examples/ReportGenerator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/pom.xml b/org.jacoco.report.test/pom.xml
index 753267d..64c0cfa 100644
--- a/org.jacoco.report.test/pom.xml
+++ b/org.jacoco.report.test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.tests</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.tests</relativePath>
   </parent>
 
diff --git a/org.jacoco.report.test/src/org/jacoco/report/DirectorySourceFileLocatorTest.java b/org.jacoco.report.test/src/org/jacoco/report/DirectorySourceFileLocatorTest.java
index 9d53c79..a93e5c3 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/DirectorySourceFileLocatorTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/DirectorySourceFileLocatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/FileMultiReportOutputTest.java b/org.jacoco.report.test/src/org/jacoco/report/FileMultiReportOutputTest.java
index 2c465dc..c78df55 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/FileMultiReportOutputTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/FileMultiReportOutputTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/InputStreamSourceFileLocatorTest.java b/org.jacoco.report.test/src/org/jacoco/report/InputStreamSourceFileLocatorTest.java
index 6529e29..2225d6d 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/InputStreamSourceFileLocatorTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/InputStreamSourceFileLocatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/JavaNamesTest.java b/org.jacoco.report.test/src/org/jacoco/report/JavaNamesTest.java
index e1a93da..8c9e4a2 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/JavaNamesTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/JavaNamesTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java b/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java
index bbb9eea..e687db1 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/MemoryMultiReportOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MemoryOutput.java b/org.jacoco.report.test/src/org/jacoco/report/MemoryOutput.java
index e634523..d099bab 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/MemoryOutput.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/MemoryOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MultiReportVisitorTest.java b/org.jacoco.report.test/src/org/jacoco/report/MultiReportVisitorTest.java
index e9978aa..9f53228 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/MultiReportVisitorTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/MultiReportVisitorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/MultiSourceFileLocatorTest.java b/org.jacoco.report.test/src/org/jacoco/report/MultiSourceFileLocatorTest.java
index ca0011e..f91e1a4 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/MultiSourceFileLocatorTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/MultiSourceFileLocatorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java b/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java
index 1b9c80b..d2aace0 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,6 +13,8 @@
 
 import java.io.IOException;
 import java.io.Reader;
+import java.io.StringReader;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -45,7 +47,7 @@
 
 		public Reader getSourceFile(String packageName, String fileName)
 				throws IOException {
-			return null;
+			return  new StringReader("");
 		}
 
 		public int getTabWidth() {
@@ -69,7 +71,7 @@
 		m.increment(CounterImpl.getInstance(3, 5), CounterImpl.COUNTER_0_0, 1);
 		m.increment(CounterImpl.getInstance(3, 5),
 				CounterImpl.getInstance(1, 2), 2);
-		m.increment(CounterImpl.getInstance(4, 5), CounterImpl.COUNTER_0_0, 3);
+		m.increment(CounterImpl.getInstance(4, 5), CounterImpl.COUNTER_0_0, 4);
 		m.incrementMethodCounter();
 		methodCoverage = m;
 
@@ -84,11 +86,30 @@
 		sourceFileCoverageImpl.increment(classCoverage);
 		sourceFileCoverage = sourceFileCoverageImpl;
 
+		final ClassCoverageImpl emptyClassInNonEmptyPackage = new ClassCoverageImpl(
+				"org/jacoco/example/Empty", 0, false);
+		emptyClassInNonEmptyPackage.setSourceFileName("Empty.java");
+		final SourceFileCoverageImpl emptySourceInNonEmptyPackage = new SourceFileCoverageImpl(
+				"Empty.java", "org/jacoco/example");
+
+		final ClassCoverageImpl emptyClassInEmptyPackage = new ClassCoverageImpl(
+				"empty/Empty", 0, false);
+		emptyClassInEmptyPackage.setSourceFileName("Empty.java");
+		final SourceFileCoverageImpl emptySourceInEmptyPackage = new SourceFileCoverageImpl(
+				"Empty.java", "empty");
+		final PackageCoverageImpl emptyPackage = new PackageCoverageImpl(
+				"empty",
+				Collections.<IClassCoverage> singletonList(
+						emptyClassInEmptyPackage),
+				Collections.<ISourceFileCoverage> singletonList(
+						emptySourceInEmptyPackage));
+
 		packageCoverage = new PackageCoverageImpl("org/jacoco/example",
-				Collections.singleton(classCoverage),
-				Collections.singleton(sourceFileCoverage));
+				Arrays.asList(classCoverage, emptyClassInNonEmptyPackage),
+				Arrays.asList(sourceFileCoverage,
+						emptySourceInNonEmptyPackage));
 		bundleCoverage = new BundleCoverageImpl("bundle",
-				Collections.singleton(packageCoverage));
+				Arrays.asList(packageCoverage, emptyPackage));
 	}
 
 	public void sendNestedGroups(IReportVisitor reportVisitor)
@@ -119,7 +140,8 @@
 		reportVisitor.visitEnd();
 	}
 
-	public void sendBundle(IReportGroupVisitor groupVisitor) throws IOException {
+	public void sendBundle(IReportGroupVisitor groupVisitor)
+			throws IOException {
 		groupVisitor.visitBundle(bundleCoverage, sourceFileLocator);
 	}
 
diff --git a/org.jacoco.report.test/src/org/jacoco/report/ZipMultiReportOutputTest.java b/org.jacoco.report.test/src/org/jacoco/report/ZipMultiReportOutputTest.java
index 4ab6ac8..388ddce 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/ZipMultiReportOutputTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/ZipMultiReportOutputTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/check/BundleCheckerTest.java b/org.jacoco.report.test/src/org/jacoco/report/check/BundleCheckerTest.java
index 9c0bfa5..0761f74 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/check/BundleCheckerTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/check/BundleCheckerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/check/LimitTest.java b/org.jacoco.report.test/src/org/jacoco/report/check/LimitTest.java
index 6ce632c..07ecdc2 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/check/LimitTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/check/LimitTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/check/RuleTest.java b/org.jacoco.report.test/src/org/jacoco/report/check/RuleTest.java
index db3eaa7..076bfde 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/check/RuleTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/check/RuleTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/check/RulesCheckerTest.java b/org.jacoco.report.test/src/org/jacoco/report/check/RulesCheckerTest.java
index 7b243b3..de4cd8a 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/check/RulesCheckerTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/check/RulesCheckerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java
index ac0e61d..8b16200 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -64,6 +64,7 @@
 		assertEquals(
 				"group/bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
 				lines.get(1));
+		assertEquals(2, lines.size());
 	}
 
 	@Test
@@ -77,6 +78,7 @@
 		assertEquals(
 				"report/bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
 				lines.get(2));
+		assertEquals(3, lines.size());
 	}
 
 	@Test
@@ -84,9 +86,9 @@
 		driver.sendBundle(visitor);
 		final List<String> lines = getLines();
 		assertEquals(HEADER, lines.get(0));
-		assertEquals(
-				"bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
+		assertEquals("bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
 				lines.get(1));
+		assertEquals(2, lines.size());
 	}
 
 	@Test
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java
index 0317406..4e7a147 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -51,6 +51,7 @@
 		assertEquals(
 				"bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
 				reader.readLine());
+		assertEquals("no more lines expected", null, reader.readLine());
 	}
 
 	@Test
@@ -61,6 +62,7 @@
 		assertEquals(
 				"group/bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
 				reader.readLine());
+		assertEquals("no more lines expected", null, reader.readLine());
 	}
 
 	private BufferedReader getResultReader() {
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/ClassRowWriterTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/ClassRowWriterTest.java
index 4e2c63d..e231be4 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/csv/ClassRowWriterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/csv/ClassRowWriterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/csv/DelimitedWriterTest.java b/org.jacoco.report.test/src/org/jacoco/report/csv/DelimitedWriterTest.java
index 69b10e0..a45f506 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/csv/DelimitedWriterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/csv/DelimitedWriterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java b/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java
index b1c03ff..a26c909 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -65,16 +65,36 @@
 		driver.sendGroup(formatter.createVisitor(output));
 		output.assertFile("index.html");
 		output.assertFile("bundle/index.html");
+
 		output.assertFile("bundle/org.jacoco.example/index.html");
+		output.assertFile("bundle/org.jacoco.example/index.source.html");
 		output.assertFile("bundle/org.jacoco.example/FooClass.html");
+		output.assertFile("bundle/org.jacoco.example/FooClass.java.html");
+		output.assertNoFile("bundle/org.jacoco.example/Empty.html");
+		output.assertNoFile("bundle/org.jacoco.example/Empty.java.html");
+
+		output.assertNoFile("bundle/empty/index.html");
+		output.assertNoFile("bundle/empty/index.source.html");
+		output.assertNoFile("bundle/empty/Empty.html");
+		output.assertNoFile("bundle/empty/Empty.java.html");
 	}
 
 	@Test
 	public void testStructureWithBundleOnly() throws IOException {
 		driver.sendBundle(formatter.createVisitor(output));
 		output.assertFile("index.html");
+
 		output.assertFile("org.jacoco.example/index.html");
+		output.assertFile("org.jacoco.example/index.source.html");
 		output.assertFile("org.jacoco.example/FooClass.html");
+		output.assertFile("org.jacoco.example/FooClass.java.html");
+		output.assertNoFile("org.jacoco.example/Empty.html");
+		output.assertNoFile("org.jacoco.example/Empty.java.html");
+
+		output.assertNoFile("empty/index.html");
+		output.assertNoFile("empty/index.source.html");
+		output.assertNoFile("empty/Empty.html");
+		output.assertNoFile("empty/Empty.java.html");
 	}
 
 	@Test
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java
index 0dfb680..c0396d8 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/NormalizedFileNamesTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/ReportOutputFolderTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/ReportOutputFolderTest.java
index 7ff9641..905fe64 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/ReportOutputFolderTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/ReportOutputFolderTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLDocumentTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLDocumentTest.java
deleted file mode 100644
index 436fe9a..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLDocumentTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.report.internal.html;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link HTMLDocument}.
- */
-public class HTMLDocumentTest {
-
-	@Test
-	public void testWriter() throws IOException {
-		StringWriter buffer = new StringWriter();
-		new HTMLDocument(buffer, "UTF-8").close();
-		assertEquals(
-				"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-						+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
-						+ "<html xmlns=\"http://www.w3.org/1999/xhtml\"/>",
-				buffer.toString());
-	}
-
-	@Test
-	public void testStream() throws IOException {
-		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-		new HTMLDocument(buffer, "UTF-8").close();
-		assertEquals(
-				"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-						+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
-						+ "<html xmlns=\"http://www.w3.org/1999/xhtml\"/>",
-				buffer.toString("UTF-8"));
-	}
-
-	@Test
-	public void testHead() throws IOException {
-		StringWriter buffer = new StringWriter();
-		final HTMLDocument doc = new HTMLDocument(buffer, "UTF-8");
-		doc.head();
-		doc.close();
-		assertEquals(
-				"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-						+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
-						+ "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head/></html>",
-				buffer.toString());
-	}
-
-	@Test
-	public void testBody() throws IOException {
-		StringWriter buffer = new StringWriter();
-		final HTMLDocument doc = new HTMLDocument(buffer, "UTF-8");
-		doc.body();
-		doc.close();
-		assertEquals(
-				"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-						+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
-						+ "<html xmlns=\"http://www.w3.org/1999/xhtml\"><body/></html>",
-				buffer.toString());
-	}
-
-	@Test
-	public void testMinimalHTMLDocument() throws Exception {
-		StringWriter buffer = new StringWriter();
-		final HTMLDocument doc = new HTMLDocument(buffer, "UTF-8");
-		doc.head().title();
-		doc.body();
-		doc.close();
-		new HTMLSupport().parse(buffer.toString());
-	}
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLElementTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLElementTest.java
index 2eff51a..89a04ec 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLElementTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLElementTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,8 +13,8 @@
 
 import static org.junit.Assert.assertEquals;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.StringWriter;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -24,218 +24,215 @@
  */
 public class HTMLElementTest {
 
-	private StringWriter buffer;
+	private static final String PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\">";
+
+	private static final String SUFFIX = "</html>";
+
+	private ByteArrayOutputStream buffer;
 
 	private HTMLElement root;
 
 	@Before
-	public void setUp() throws IOException {
-		buffer = new StringWriter();
-		root = new HTMLElement(buffer, "root") {
-			{
-				beginOpenTag();
-			}
-		};
+	public void setup() throws IOException {
+		buffer = new ByteArrayOutputStream();
+		root = new HTMLElement(buffer, "UTF-8");
 	}
 
 	@Test
-	public void testMeta() throws IOException {
+	public void should_create_minimal_valid_html_document() throws Exception {
+		root.head().title();
+		root.body();
+		root.close();
+		new HTMLSupport().parse(buffer);
+	}
+
+	@Test
+	public void head_should_create_head_tag() throws IOException {
+		root.head();
+		assertContent("<head/>");
+	}
+
+	@Test
+	public void meta_should_create_meta_tag_with_attributes()
+			throws IOException {
 		root.meta("key", "value");
-		root.close();
-		assertEquals(
-				"<root><meta http-equiv=\"key\" content=\"value\"/></root>",
-				buffer.toString());
+		assertContent("<meta http-equiv=\"key\" content=\"value\"/>");
 	}
 
 	@Test
-	public void testLink() throws IOException {
+	public void body_should_create_body_tag() throws IOException {
+		root.body();
+		assertContent("<body/>");
+	}
+
+	@Test
+	public void link_should_create_link_tag_with_attributes()
+			throws IOException {
 		root.link("stylesheet", "style.css", "text/css");
-		root.close();
-		assertEquals(
-				"<root><link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\"/></root>",
-				buffer.toString());
+		assertContent(
+				"<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\"/>");
 	}
 
 	@Test
-	public void testTitle() throws IOException {
+	public void title_should_create_title_tag() throws IOException {
 		root.title();
-		root.close();
-		assertEquals("<root><title/></root>", buffer.toString());
+		assertContent("<title/>");
 	}
 
 	@Test
-	public void testH1() throws IOException {
+	public void h1_should_create_h1_tag() throws IOException {
 		root.h1();
-		root.close();
-		assertEquals("<root><h1/></root>", buffer.toString());
+		assertContent("<h1/>");
 	}
 
 	@Test
-	public void testP() throws IOException {
+	public void p_should_create_p_tag() throws IOException {
 		root.p();
-		root.close();
-		assertEquals("<root><p/></root>", buffer.toString());
+		assertContent("<p/>");
 	}
 
 	@Test
-	public void testSpan1() throws IOException {
+	public void span_should_create_span_tag() throws IOException {
 		root.span();
-		root.close();
-		assertEquals("<root><span/></root>", buffer.toString());
+		assertContent("<span/>");
 	}
 
 	@Test
-	public void testSpan2() throws IOException {
+	public void span_should_create_span_tag_with_class_attribute()
+			throws IOException {
 		root.span("abc");
-		root.close();
-		assertEquals("<root><span class=\"abc\"/></root>", buffer.toString());
+		assertContent("<span class=\"abc\"/>");
 	}
 
 	@Test
-	public void testSpan3() throws IOException {
+	public void span_should_create_span_tag_with_class_and_id_attribute()
+			throws IOException {
 		root.span("abc", "xy");
-		root.close();
-		assertEquals("<root><span class=\"abc\" id=\"xy\"/></root>",
-				buffer.toString());
+		assertContent("<span class=\"abc\" id=\"xy\"/>");
 	}
 
 	@Test
-	public void testPre() throws IOException {
+	public void pre_should_create_pre_tag_with_class_attribute()
+			throws IOException {
 		root.pre("mystyle");
-		root.close();
-		assertEquals("<root><pre class=\"mystyle\"/></root>", buffer.toString());
+		assertContent("<pre class=\"mystyle\"/>");
 	}
 
 	@Test
-	public void testDiv() throws IOException {
+	public void div_should_create_div_tag_with_class_attribute()
+			throws IOException {
 		root.div("mystyle");
-		root.close();
-		assertEquals("<root><div class=\"mystyle\"/></root>", buffer.toString());
+		assertContent("<div class=\"mystyle\"/>");
 	}
 
 	@Test
-	public void testCode() throws IOException {
+	public void code_should_create_code_tag() throws IOException {
 		root.code().text("0xCAFEBABE");
-		root.close();
-		assertEquals("<root><code>0xCAFEBABE</code></root>", buffer.toString());
+		assertContent("<code>0xCAFEBABE</code>");
 	}
 
 	@Test
-	public void testA1() throws IOException {
+	public void a_should_create_a_tag_with_href_attribute() throws IOException {
 		root.a("http://www.jacoco.org/");
-		root.close();
-		assertEquals("<root><a href=\"http://www.jacoco.org/\"/></root>",
-				buffer.toString());
+		assertContent("<a href=\"http://www.jacoco.org/\"/>");
 	}
 
 	@Test
-	public void testA2() throws IOException {
+	public void a_should_create_a_tag_with_href_and_class_attribute()
+			throws IOException {
 		root.a("http://www.jacoco.org/", "extern");
-		root.close();
-		assertEquals(
-				"<root><a href=\"http://www.jacoco.org/\" class=\"extern\"/></root>",
-				buffer.toString());
+		assertContent("<a href=\"http://www.jacoco.org/\" class=\"extern\"/>");
 	}
 
 	@Test
-	public void testALinkable1() throws IOException {
+	public void a_should_create_span_tag_when_no_link_is_given()
+			throws IOException {
 		root.a(new LinkableStub(null, "here", null), null);
-		root.close();
-		assertEquals("<root><span>here</span></root>", buffer.toString());
+		assertContent("<span>here</span>");
 	}
 
 	@Test
-	public void testALinkable2() throws IOException {
+	public void a_should_create_span_tag_with_class_attribute_when_no_link_is_given()
+			throws IOException {
 		root.a(new LinkableStub(null, "here", "blue"), null);
-		root.close();
-		assertEquals("<root><span class=\"blue\">here</span></root>",
-				buffer.toString());
+		assertContent("<span class=\"blue\">here</span>");
 	}
 
 	@Test
-	public void testALinkable3() throws IOException {
+	public void a_should_create_a_tag_when_link_is_given() throws IOException {
 		root.a(new LinkableStub("index.html", "here", null), null);
-		root.close();
-		assertEquals("<root><a href=\"index.html\">here</a></root>",
-				buffer.toString());
+		assertContent("<a href=\"index.html\">here</a>");
 	}
 
 	@Test
-	public void testALinkable4() throws IOException {
+	public void a_should_create_a_tag_with_class_attribute_when_link_is_given()
+			throws IOException {
 		root.a(new LinkableStub("index.html", "here", "red"), null);
-		root.close();
-		assertEquals(
-				"<root><a href=\"index.html\" class=\"red\">here</a></root>",
-				buffer.toString());
+		assertContent("<a href=\"index.html\" class=\"red\">here</a>");
 	}
 
 	@Test
-	public void testTable() throws IOException {
+	public void table_should_create_table_tag_with_attributes()
+			throws IOException {
 		root.table("tablestyle");
-		root.close();
-		assertEquals(
-				"<root><table class=\"tablestyle\" cellspacing=\"0\"/></root>",
-				buffer.toString());
+		assertContent("<table class=\"tablestyle\" cellspacing=\"0\"/>");
 	}
 
 	@Test
-	public void testThead() throws IOException {
+	public void thead_should_create_thead_tag() throws IOException {
 		root.thead();
-		root.close();
-		assertEquals("<root><thead/></root>", buffer.toString());
+		assertContent("<thead/>");
 	}
 
 	@Test
-	public void testTfoot() throws IOException {
+	public void tfoot_should_create_tfoot_tag() throws IOException {
 		root.tfoot();
-		root.close();
-		assertEquals("<root><tfoot/></root>", buffer.toString());
+		assertContent("<tfoot/>");
 	}
 
 	@Test
-	public void testTbody() throws IOException {
+	public void tbody_should_create_tbody_tag() throws IOException {
 		root.tbody();
-		root.close();
-		assertEquals("<root><tbody/></root>", buffer.toString());
+		assertContent("<tbody/>");
 	}
 
 	@Test
-	public void testTr() throws IOException {
+	public void tr_should_create_tr_tag() throws IOException {
 		root.tr();
-		root.close();
-		assertEquals("<root><tr/></root>", buffer.toString());
+		assertContent("<tr/>");
 	}
 
 	@Test
-	public void testTd1() throws IOException {
+	public void td_should_create_td_tag() throws IOException {
 		root.td();
-		root.close();
-		assertEquals("<root><td/></root>", buffer.toString());
+		assertContent("<td/>");
 	}
 
 	@Test
-	public void testTd2() throws IOException {
+	public void td_should_create_td_tag_with_class_attribute()
+			throws IOException {
 		root.td("mystyle");
-		root.close();
-		assertEquals("<root><td class=\"mystyle\"/></root>", buffer.toString());
+		assertContent("<td class=\"mystyle\"/>");
 	}
 
 	@Test
-	public void testImg() throws IOException {
+	public void img_should_create_img_tag_with_attributes() throws IOException {
 		root.img("sample.gif", 16, 32, "Hello");
-		root.close();
-		assertEquals(
-				"<root><img src=\"sample.gif\" width=\"16\" height=\"32\" title=\"Hello\" alt=\"Hello\"/></root>",
-				buffer.toString());
+		assertContent(
+				"<img src=\"sample.gif\" width=\"16\" height=\"32\" title=\"Hello\" alt=\"Hello\"/>");
 	}
 
 	@Test
-	public void testScript() throws IOException {
-		root.script("text/javascript", "file.js");
+	public void script_should_create_script_tag_with_attributes()
+			throws IOException {
+		root.script("file.js");
+		assertContent(
+				"<script type=\"text/javascript\" src=\"file.js\"></script>");
+	}
+
+	private void assertContent(String expected) throws IOException {
 		root.close();
-		assertEquals(
-				"<root><script type=\"text/javascript\" src=\"file.js\"></script></root>",
-				buffer.toString());
+		assertEquals(PREFIX + expected + SUFFIX, buffer.toString("UTF-8"));
 	}
 
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLSupport.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLSupport.java
index 1e83ebc..ae3a297 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLSupport.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/HTMLSupport.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java
index 799cd79..b80b5ac 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/LinkableStub.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/BundlePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/BundlePageTest.java
new file mode 100644
index 0000000..716249c
--- /dev/null
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/BundlePageTest.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.report.internal.html.page;
+
+import org.jacoco.core.analysis.IBundleCoverage;
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.analysis.IPackageCoverage;
+import org.jacoco.core.analysis.ISourceFileCoverage;
+import org.jacoco.core.internal.analysis.BundleCoverageImpl;
+import org.jacoco.core.internal.analysis.ClassCoverageImpl;
+import org.jacoco.core.internal.analysis.CounterImpl;
+import org.jacoco.core.internal.analysis.MethodCoverageImpl;
+import org.jacoco.core.internal.analysis.PackageCoverageImpl;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit tests for {@link BundlePage}.
+ */
+public class BundlePageTest extends PageTestBase {
+
+	@Before
+	@Override
+	public void setup() throws Exception {
+		super.setup();
+	}
+
+	@Test
+	public void should_render_non_empty_packages() throws Exception {
+		final ClassCoverageImpl classCoverage = new ClassCoverageImpl(
+				"example/Class", 0, false);
+		final MethodCoverageImpl methodCoverage = new MethodCoverageImpl("m",
+				"()V", null);
+		methodCoverage.increment(CounterImpl.COUNTER_1_0,
+				CounterImpl.COUNTER_0_0, 42);
+		classCoverage.addMethod(methodCoverage);
+		final IPackageCoverage nonEmptyPackage = new PackageCoverageImpl(
+				"example",
+				Collections.<IClassCoverage> singleton(classCoverage),
+				Collections.<ISourceFileCoverage> emptySet());
+
+		final IPackageCoverage emptyPackage = new PackageCoverageImpl("empty",
+				Collections.<IClassCoverage> emptySet(),
+				Collections.<ISourceFileCoverage> emptySet());
+
+		final IBundleCoverage node = new BundleCoverageImpl("bundle",
+				Arrays.asList(nonEmptyPackage, emptyPackage));
+
+		final BundlePage page = new BundlePage(node, null, null, rootFolder,
+				context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("index.html"));
+		assertEquals("el_package", support.findStr(doc,
+				"/html/body/table[1]/tbody/tr[1]/td[1]/a/@class"));
+		assertEquals("example", support.findStr(doc,
+				"/html/body/table[1]/tbody/tr[1]/td[1]/a"));
+		assertEquals("1",
+				support.findStr(doc, "count(/html/body/table[1]/tbody/tr)"));
+	}
+
+	@Test
+	public void should_render_message_when_no_class_files_specified()
+			throws Exception {
+		final IBundleCoverage node = new BundleCoverageImpl("bundle",
+				Collections.<IPackageCoverage> emptySet());
+
+		final BundlePage page = new BundlePage(node, null, null, rootFolder,
+				context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("index.html"));
+		assertEquals("No class files specified.",
+				support.findStr(doc, "/html/body/p"));
+	}
+
+	@Test
+	public void should_render_message_when_all_classes_empty()
+			throws Exception {
+		final ClassCoverageImpl emptyClass = new ClassCoverageImpl(
+				"example/Class", 0, false);
+		final IBundleCoverage node = new BundleCoverageImpl("bundle",
+				Collections.<IClassCoverage> singleton(emptyClass),
+				Collections.<ISourceFileCoverage> emptySet());
+
+		final BundlePage page = new BundlePage(node, null, null, rootFolder,
+				context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("index.html"));
+		assertEquals(
+				"None of the analyzed classes contain code relevant for code coverage.",
+				support.findStr(doc, "/html/body/p"));
+	}
+
+}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java
index 5a296f4..732d1c0 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ClassPageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -17,7 +17,10 @@
 
 import org.jacoco.core.analysis.IClassCoverage;
 import org.jacoco.core.internal.analysis.ClassCoverageImpl;
+import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.core.internal.analysis.MethodCoverageImpl;
+import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.ILinkable;
 import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
@@ -35,8 +38,10 @@
 	@Override
 	public void setup() throws Exception {
 		super.setup();
+		final MethodCoverageImpl m = new MethodCoverageImpl("a", "()V", null);
+		m.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42);
 		node = new ClassCoverageImpl("org/jacoco/example/Foo", 123, false);
-		node.addMethod(new MethodCoverageImpl("a", "()V", null));
+		node.addMethod(m);
 		node.addMethod(new MethodCoverageImpl("b", "()V", null));
 		node.addMethod(new MethodCoverageImpl("c", "()V", null));
 	}
@@ -47,6 +52,7 @@
 		page.render();
 
 		final Document doc = support.parse(output.getFile("Foo.html"));
+		assertEquals("", support.findStr(doc, "doc/body/p[1]"));
 		assertEquals("el_method", support.findStr(doc,
 				"/html/body/table[1]/tbody/tr[1]/td[1]/span/@class"));
 		assertEquals("a()", support.findStr(doc,
@@ -58,6 +64,106 @@
 	}
 
 	@Test
+	public void should_generate_message_when_SourceFileName_not_present()
+			throws Exception {
+		page = new ClassPage(node, null, null, rootFolder, context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("Foo.html"));
+		assertEquals(
+				"Class files must be compiled with debug information to link with source files.",
+				support.findStr(doc, "/html/body/p[1]"));
+	}
+
+	@Test
+	public void should_generate_message_when_SourceFileName_present_but_no_SourceFilePage()
+			throws Exception {
+		node.setSourceFileName("Foo.java");
+
+		page = new ClassPage(node, null, null, rootFolder, context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("Foo.html"));
+		assertEquals(
+				"Source file \"org/jacoco/example/Foo.java\" was not found during generation of report.",
+				support.findStr(doc, "/html/body/p[1]"));
+	}
+
+	@Test
+	public void should_generate_message_with_default_package_when_SourceFileName_present_but_no_SourceFilePage()
+			throws Exception {
+		final MethodCoverageImpl m = new MethodCoverageImpl("a", "()V", null);
+		m.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42);
+		node = new ClassCoverageImpl("Foo", 123, false);
+		node.addMethod(m);
+		node.setSourceFileName("Foo.java");
+
+		page = new ClassPage(node, null, null, rootFolder, context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("Foo.html"));
+		assertEquals(
+				"Source file \"Foo.java\" was not found during generation of report.",
+				support.findStr(doc, "/html/body/p[1]"));
+	}
+
+	@Test
+	public void should_not_generate_message_when_SourceFileName_and_SourceFilePage_present()
+			throws Exception {
+		node.setSourceFileName("Foo.java");
+
+		page = new ClassPage(node, null, new SourceLink(), rootFolder, context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("Foo.html"));
+		assertEquals("", support.findStr(doc, "/html/body/p[1]"));
+	}
+
+	@Test
+	public void should_generate_message_when_no_lines() throws Exception {
+		node = new ClassCoverageImpl("Foo", 123, false);
+		node.addMethod(new MethodCoverageImpl("m", "()V", null));
+
+		page = new ClassPage(node, null, new SourceLink(), rootFolder, context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("Foo.html"));
+		assertEquals(
+				"Class files must be compiled with debug information to show line coverage.",
+				support.findStr(doc, "/html/body/p[1]"));
+	}
+
+	@Test
+	public void should_generate_message_when_class_id_mismatch()
+			throws Exception {
+		node = new ClassCoverageImpl("Foo", 123, true);
+		node.addMethod(new MethodCoverageImpl("m", "()V", null));
+
+		page = new ClassPage(node, null, new SourceLink(), rootFolder, context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("Foo.html"));
+		assertEquals("A different version of class was executed at runtime.",
+				support.findStr(doc, "/html/body/p[1]"));
+	}
+
+	private class SourceLink implements ILinkable {
+
+		public String getLink(final ReportOutputFolder base) {
+			return "Source.java.html";
+		}
+
+		public String getLinkLabel() {
+			return "";
+		}
+
+		public String getLinkStyle() {
+			return null;
+		}
+
+	}
+
+	@Test
 	public void testGetFileName() throws IOException {
 		page = new ClassPage(node, null, null, rootFolder, context);
 		assertEquals("Foo.html", page.getFileName());
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/MethodItemTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/MethodItemTest.java
index ccd3a43..e9a030e 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/MethodItemTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/MethodItemTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/NodePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/NodePageTest.java
index 3adfaea..65affac 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/NodePageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/NodePageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackagePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackagePageTest.java
index 2a0fd27..828f5f5 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackagePageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackagePageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -22,6 +22,8 @@
 import org.jacoco.core.analysis.IPackageCoverage;
 import org.jacoco.core.analysis.ISourceFileCoverage;
 import org.jacoco.core.internal.analysis.ClassCoverageImpl;
+import org.jacoco.core.internal.analysis.CounterImpl;
+import org.jacoco.core.internal.analysis.MethodCoverageImpl;
 import org.jacoco.core.internal.analysis.PackageCoverageImpl;
 import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
 import org.jacoco.report.ISourceFileLocator;
@@ -30,7 +32,7 @@
 import org.w3c.dom.Document;
 
 /**
- * Unit tests for {@link PackageSourcePage}.
+ * Unit tests for {@link PackagePage}.
  */
 public class PackagePageTest extends PageTestBase {
 
@@ -57,15 +59,48 @@
 	}
 
 	@Test
+	public void should_render_non_empty_classes() throws Exception {
+		final ClassCoverageImpl nonEmptyClass = new ClassCoverageImpl(
+				"example/NonEmptyClass", 0, false);
+		final MethodCoverageImpl nonEmptyMethod = new MethodCoverageImpl("m",
+				"()V", null);
+		nonEmptyMethod.increment(CounterImpl.COUNTER_1_0,
+				CounterImpl.COUNTER_0_0, 42);
+		nonEmptyClass.addMethod(nonEmptyMethod);
+		final ClassCoverageImpl emptyClass = new ClassCoverageImpl(
+				"example/EmptyClass", 0, false);
+
+		node = new PackageCoverageImpl("example",
+				Arrays.<IClassCoverage> asList(emptyClass, nonEmptyClass),
+				Collections.<ISourceFileCoverage> emptySet());
+
+		page = new PackagePage(node, null, sourceLocator, rootFolder, context);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("index.html"));
+		assertEquals("NonEmptyClass", support.findStr(doc,
+				"/html/body/table[1]/tbody/tr[1]/td[1]/a"));
+		assertEquals("1",
+				support.findStr(doc, "count(/html/body/table[1]/tbody/tr)"));
+	}
+
+	@Test
 	public void testContentsWithSource() throws Exception {
-		IClassCoverage class1 = new ClassCoverageImpl(
+		ClassCoverageImpl class1 = new ClassCoverageImpl(
 				"org/jacoco/example/Foo1", 0x1000, false);
-		IClassCoverage class2 = new ClassCoverageImpl(
+		MethodCoverageImpl method1 = new MethodCoverageImpl("m", "()V", null);
+		method1.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42);
+		class1.addMethod(method1);
+		ClassCoverageImpl class2 = new ClassCoverageImpl(
 				"org/jacoco/example/Foo2", 0x2000, false);
+		MethodCoverageImpl method2 = new MethodCoverageImpl("m", "()V", null);
+		method2.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42);
+		class2.addMethod(method2);
 		ISourceFileCoverage src1 = new SourceFileCoverageImpl("Src1.java",
 				"org/jacoco/example");
-		node = new PackageCoverageImpl("org/jacoco/example", Arrays.asList(
-				class1, class2), Arrays.asList(src1));
+		node = new PackageCoverageImpl("org/jacoco/example",
+				Arrays.<IClassCoverage> asList(class1, class2),
+				Arrays.asList(src1));
 
 		page = new PackagePage(node, null, sourceLocator, rootFolder, context);
 		page.render();
@@ -93,12 +128,19 @@
 
 	@Test
 	public void testContentsNoSource() throws Exception {
-		IClassCoverage class1 = new ClassCoverageImpl(
+		ClassCoverageImpl class1 = new ClassCoverageImpl(
 				"org/jacoco/example/Foo1", 0x1000, false);
-		IClassCoverage class2 = new ClassCoverageImpl(
+		MethodCoverageImpl method1 = new MethodCoverageImpl("m", "()V", null);
+		method1.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42);
+		class1.addMethod(method1);
+		ClassCoverageImpl class2 = new ClassCoverageImpl(
 				"org/jacoco/example/Foo2", 0x2000, false);
-		node = new PackageCoverageImpl("org/jacoco/example", Arrays.asList(
-				class1, class2), Collections.<ISourceFileCoverage> emptyList());
+		MethodCoverageImpl method2 = new MethodCoverageImpl("m", "()V", null);
+		method2.increment(CounterImpl.COUNTER_1_0, CounterImpl.COUNTER_0_0, 42);
+		class2.addMethod(method2);
+		node = new PackageCoverageImpl("org/jacoco/example",
+				Arrays.<IClassCoverage> asList(class1, class2),
+				Collections.<ISourceFileCoverage> emptyList());
 
 		page = new PackagePage(node, null, sourceLocator, rootFolder, context);
 		page.render();
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackageSourcePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackageSourcePageTest.java
index c39a498..96db3a5 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackageSourcePageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PackageSourcePageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,7 @@
 
 import org.jacoco.core.analysis.IClassCoverage;
 import org.jacoco.core.analysis.ISourceFileCoverage;
+import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.core.internal.analysis.PackageCoverageImpl;
 import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
 import org.jacoco.report.ISourceFileLocator;
@@ -48,12 +49,16 @@
 	@Override
 	public void setup() throws Exception {
 		super.setup();
-		ISourceFileCoverage src1 = new SourceFileCoverageImpl("Src1.java",
+		SourceFileCoverageImpl src1 = new SourceFileCoverageImpl("Src1.java",
 				"org/jacoco/example");
-		ISourceFileCoverage src2 = new SourceFileCoverageImpl("Src2.java",
+		src1.increment(CounterImpl.COUNTER_1_0,
+				CounterImpl.COUNTER_0_0, 1);
+		SourceFileCoverageImpl src2 = new SourceFileCoverageImpl("Src2.java",
 				"org/jacoco/example");
+		src2.increment(CounterImpl.COUNTER_1_0,
+				CounterImpl.COUNTER_0_0, 1);
 		node = new PackageCoverageImpl("org/jacoco/example",
-				Collections.<IClassCoverage> emptyList(), Arrays.asList(src1,
+				Collections.<IClassCoverage> emptyList(), Arrays.<ISourceFileCoverage>asList(src1,
 						src2));
 		sourceLocator = new ISourceFileLocator() {
 
@@ -109,6 +114,29 @@
 	}
 
 	@Test
+	public void should_render_non_empty_sources() throws Exception {
+		final ISourceFileCoverage emptySource = new SourceFileCoverageImpl(
+				"Empty.java", "example");
+		final SourceFileCoverageImpl nonEmptySource = new SourceFileCoverageImpl(
+				"NonEmpty.java", "example");
+		nonEmptySource.increment(CounterImpl.COUNTER_1_0,
+				CounterImpl.COUNTER_0_0, 1);
+		node = new PackageCoverageImpl("example",
+				Collections.<IClassCoverage> emptyList(),
+				Arrays.asList(emptySource, nonEmptySource));
+
+		page = new PackageSourcePage(node, null, sourceLocator, rootFolder,
+				context, packagePageLink);
+		page.render();
+
+		final Document doc = support.parse(output.getFile("index.source.html"));
+		assertEquals("NonEmpty.java", support.findStr(doc,
+				"/html/body/table[1]/tbody/tr[1]/td[1]/span"));
+		assertEquals("1",
+				support.findStr(doc, "count(/html/body/table[1]/tbody/tr)"));
+	}
+
+	@Test
 	public void testGetSourceFilePages() throws Exception {
 		page = new PackageSourcePage(node, null, sourceLocator, rootFolder,
 				context, packagePageLink);
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PageTestBase.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PageTestBase.java
index 40cd983..8a5574d 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PageTestBase.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/PageTestBase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ReportPageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ReportPageTest.java
index 1d875f3..0f42bb4 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ReportPageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/ReportPageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SessionsPageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SessionsPageTest.java
index 7983d8d..2380d57 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SessionsPageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SessionsPageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceFilePageTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceFilePageTest.java
index c0bc72e..da43354 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceFilePageTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceFilePageTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceHighlighterTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceHighlighterTest.java
index ca9d4d7..3ef347d 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceHighlighterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/page/SourceHighlighterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,14 +13,13 @@
 
 import static org.junit.Assert.assertEquals;
 
+import java.io.ByteArrayOutputStream;
 import java.io.StringReader;
-import java.io.StringWriter;
 import java.util.Locale;
 
 import org.jacoco.core.analysis.ICoverageNode.ElementType;
 import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.core.internal.analysis.SourceNodeImpl;
-import org.jacoco.report.internal.html.HTMLDocument;
 import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.HTMLSupport;
 import org.jacoco.report.internal.html.resources.Styles;
@@ -35,9 +34,9 @@
 
 	private HTMLSupport htmlSupport;
 
-	private StringWriter buffer;
+	private ByteArrayOutputStream buffer;
 
-	private HTMLDocument html;
+	private HTMLElement html;
 
 	private HTMLElement parent;
 
@@ -49,8 +48,8 @@
 	public void setup() throws Exception {
 		htmlSupport = new HTMLSupport();
 		source = new SourceNodeImpl(ElementType.SOURCEFILE, "Foo.java");
-		buffer = new StringWriter();
-		html = new HTMLDocument(buffer, "UTF-8");
+		buffer = new ByteArrayOutputStream();
+		html = new HTMLElement(buffer, "UTF-8");
 		html.head().title();
 		parent = html.body();
 		sourceHighlighter = new SourceHighlighter(Locale.US);
@@ -60,8 +59,7 @@
 	public void testDefaultTabWidth() throws Exception {
 		final String src = "\tA";
 		sourceHighlighter.render(parent, source, new StringReader(src));
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 
 		// Assert that we no longer replace tabs with spaces
 		assertEquals("\tA\n", htmlSupport.findStr(doc, "//pre/text()"));
@@ -70,8 +68,7 @@
 	@Test
 	public void testDefaultLanguage() throws Exception {
 		sourceHighlighter.render(parent, source, new StringReader(""));
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 		assertEquals("source lang-java linenums",
 				htmlSupport.findStr(doc, "//pre/@class"));
 	}
@@ -80,8 +77,7 @@
 	public void testSetLanguage() throws Exception {
 		sourceHighlighter.setLanguage("scala");
 		sourceHighlighter.render(parent, source, new StringReader(""));
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 		assertEquals("source lang-scala linenums",
 				htmlSupport.findStr(doc, "//pre/@class"));
 	}
@@ -94,8 +90,7 @@
 		source.increment(CounterImpl.COUNTER_0_1, CounterImpl.COUNTER_0_0, 2);
 		source.increment(CounterImpl.COUNTER_0_1, CounterImpl.COUNTER_0_0, 3);
 		sourceHighlighter.render(parent, source, new StringReader(src));
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 		assertEquals(Styles.NOT_COVERED,
 				htmlSupport.findStr(doc, "//pre/span[text() = 'A']/@class"));
 		assertEquals(Styles.PARTLY_COVERED,
@@ -109,18 +104,16 @@
 	@Test
 	public void testHighlightNone() throws Exception {
 		sourceHighlighter.highlight(parent, source.getLine(1), 1);
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 		assertEquals("", htmlSupport.findStr(doc, "//pre"));
 	}
 
 	@Test
 	public void testHighlightBranchesFC() throws Exception {
-		source.increment(CounterImpl.COUNTER_0_1,
-				CounterImpl.getInstance(0, 5), 1);
+		source.increment(CounterImpl.COUNTER_0_1, CounterImpl.getInstance(0, 5),
+				1);
 		sourceHighlighter.highlight(parent.pre(null), source.getLine(1), 1);
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 		assertEquals("fc bfc", htmlSupport.findStr(doc, "//pre/span/@class"));
 		assertEquals("All 5 branches covered.",
 				htmlSupport.findStr(doc, "//pre/span/@title"));
@@ -128,11 +121,10 @@
 
 	@Test
 	public void testHighlightBranchesPC() throws Exception {
-		source.increment(CounterImpl.COUNTER_0_1,
-				CounterImpl.getInstance(2, 3), 1);
+		source.increment(CounterImpl.COUNTER_0_1, CounterImpl.getInstance(2, 3),
+				1);
 		sourceHighlighter.highlight(parent.pre(null), source.getLine(1), 1);
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 		assertEquals("pc bpc", htmlSupport.findStr(doc, "//pre/span/@class"));
 		assertEquals("2 of 5 branches missed.",
 				htmlSupport.findStr(doc, "//pre/span/@title"));
@@ -140,14 +132,18 @@
 
 	@Test
 	public void testHighlightBranchesNC() throws Exception {
-		source.increment(CounterImpl.COUNTER_0_1,
-				CounterImpl.getInstance(5, 0), 1);
+		source.increment(CounterImpl.COUNTER_0_1, CounterImpl.getInstance(5, 0),
+				1);
 		sourceHighlighter.highlight(parent.pre(null), source.getLine(1), 1);
-		html.close();
-		final Document doc = htmlSupport.parse(buffer.toString());
+		final Document doc = parseDoc();
 		assertEquals("pc bnc", htmlSupport.findStr(doc, "//pre/span/@class"));
 		assertEquals("All 5 branches missed.",
 				htmlSupport.findStr(doc, "//pre/span/@title"));
 	}
 
+	private Document parseDoc() throws Exception {
+		html.close();
+		return htmlSupport.parse(buffer);
+	}
+
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java
index 9dd7dea..1e61ceb 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/ResourcesTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/StylesTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/StylesTest.java
index e0eea6e..fdf5475 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/StylesTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/resources/StylesTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java
index 97e7658..8623eee 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/BarColumnTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,7 +26,6 @@
 import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.report.MemoryMultiReportOutput;
 import org.jacoco.report.internal.ReportOutputFolder;
-import org.jacoco.report.internal.html.HTMLDocument;
 import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.HTMLSupport;
 import org.jacoco.report.internal.html.resources.Resources;
@@ -46,7 +45,7 @@
 
 	private Resources resources;
 
-	private HTMLDocument doc;
+	private HTMLElement html;
 
 	private HTMLElement td;
 
@@ -59,9 +58,9 @@
 		output = new MemoryMultiReportOutput();
 		root = new ReportOutputFolder(output);
 		resources = new Resources(root);
-		doc = new HTMLDocument(root.createFile("Test.html"), "UTF-8");
-		doc.head().title();
-		td = doc.body().table("somestyle").tr().td();
+		html = new HTMLElement(root.createFile("Test.html"), "UTF-8");
+		html.head().title();
+		td = html.body().table("somestyle").tr().td();
 		support = new HTMLSupport();
 		column = new BarColumn(CounterEntity.LINE, Locale.ENGLISH);
 	}
@@ -76,14 +75,13 @@
 	public void testInit() throws Exception {
 		final ITableItem i = createItem(6, 24);
 		assertTrue(column.init(Arrays.asList(i), i.getNode()));
-		doc.close();
+		html.close();
 	}
 
 	@Test
 	public void testFooter() throws Exception {
 		column.footer(td, createNode(15, 5), resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("15 of 20",
 				support.findStr(doc, "/html/body/table/tr/td/text()"));
 	}
@@ -94,8 +92,7 @@
 		final ITableItem i2 = createItem(6, 24);
 		column.init(Arrays.asList(i1, i2), createNode(21, 29));
 		column.item(td, i1, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 
 		assertEquals("2",
 				support.findStr(doc, "count(/html/body/table/tr[1]/td/img)"));
@@ -105,16 +102,16 @@
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@src"));
 		assertEquals("15",
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@alt"));
-		assertEquals("60",
-				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@width"));
+		assertEquals("60", support.findStr(doc,
+				"/html/body/table/tr[1]/td/img[1]/@width"));
 
 		// green bar
 		assertEquals("jacoco-resources/greenbar.gif",
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[2]/@src"));
 		assertEquals("5",
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[2]/@alt"));
-		assertEquals("20",
-				support.findStr(doc, "/html/body/table/tr[1]/td/img[2]/@width"));
+		assertEquals("20", support.findStr(doc,
+				"/html/body/table/tr[1]/td/img[2]/@width"));
 	}
 
 	@Test
@@ -122,8 +119,7 @@
 		final ITableItem i1 = createItem(20, 0);
 		column.init(Arrays.asList(i1), createNode(20, 0));
 		column.item(td, i1, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 
 		assertEquals("1",
 				support.findStr(doc, "count(/html/body/table/tr[1]/td/img)"));
@@ -133,8 +129,8 @@
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@src"));
 		assertEquals("20",
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@alt"));
-		assertEquals("120",
-				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@width"));
+		assertEquals("120", support.findStr(doc,
+				"/html/body/table/tr[1]/td/img[1]/@width"));
 	}
 
 	@Test
@@ -142,8 +138,7 @@
 		final ITableItem i1 = createItem(00, 20);
 		column.init(Arrays.asList(i1), createNode(00, 20));
 		column.item(td, i1, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 
 		assertEquals("1",
 				support.findStr(doc, "count(/html/body/table/tr[1]/td/img)"));
@@ -153,8 +148,8 @@
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@src"));
 		assertEquals("20",
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@alt"));
-		assertEquals("120",
-				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@width"));
+		assertEquals("120", support.findStr(doc,
+				"/html/body/table/tr[1]/td/img[1]/@width"));
 	}
 
 	@Test
@@ -162,8 +157,7 @@
 		final ITableItem i1 = createItem(00, 00);
 		column.init(Arrays.asList(i1), createNode(00, 00));
 		column.item(td, i1, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 
 		assertEquals("0",
 				support.findStr(doc, "count(/html/body/table/tr[1]/td/img)"));
@@ -175,8 +169,7 @@
 		final ITableItem i1 = createItem(0, 123456);
 		col.init(Arrays.asList(i1), createNode(00, 20));
 		col.item(td, i1, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 
 		assertEquals("123\u00a0456",
 				support.findStr(doc, "/html/body/table/tr[1]/td/img[1]/@alt"));
@@ -190,7 +183,7 @@
 		assertTrue(c.compare(i1, i2) < 0);
 		assertTrue(c.compare(i2, i1) > 0);
 		assertEquals(0, c.compare(i1, i1));
-		doc.close();
+		html.close();
 	}
 
 	@Test
@@ -201,7 +194,7 @@
 		assertTrue(c.compare(i1, i2) < 0);
 		assertTrue(c.compare(i2, i1) > 0);
 		assertEquals(0, c.compare(i1, i1));
-		doc.close();
+		html.close();
 	}
 
 	private ITableItem createItem(final int missed, final int covered) {
@@ -233,4 +226,9 @@
 		};
 	}
 
+	private Document parseDoc() throws Exception {
+		html.close();
+		return support.parse(output.getFile("Test.html"));
+	}
+
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java
index 7c68e11..8311128 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/CounterColumnTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,7 +28,6 @@
 import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.report.MemoryMultiReportOutput;
 import org.jacoco.report.internal.ReportOutputFolder;
-import org.jacoco.report.internal.html.HTMLDocument;
 import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.HTMLSupport;
 import org.jacoco.report.internal.html.resources.Resources;
@@ -48,7 +47,7 @@
 
 	private Resources resources;
 
-	private HTMLDocument doc;
+	private HTMLElement html;
 
 	private HTMLElement td;
 
@@ -61,9 +60,9 @@
 		output = new MemoryMultiReportOutput();
 		root = new ReportOutputFolder(output);
 		resources = new Resources(root);
-		doc = new HTMLDocument(root.createFile("Test.html"), "UTF-8");
-		doc.head().title();
-		td = doc.body().table("somestyle").tr().td();
+		html = new HTMLElement(root.createFile("Test.html"), "UTF-8");
+		html.head().title();
+		td = html.body().table("somestyle").tr().td();
 		support = new HTMLSupport();
 		locale = Locale.ENGLISH;
 	}
@@ -80,7 +79,7 @@
 				locale);
 		final ITableItem item = createItem(0, 3);
 		assertTrue(column.init(Arrays.asList(item), item.getNode()));
-		doc.close();
+		html.close();
 	}
 
 	@Test
@@ -89,7 +88,7 @@
 				locale);
 		final ITableItem item = createItem(0, 0);
 		assertFalse(column.init(Arrays.asList(item), createNode(1, 0)));
-		doc.close();
+		html.close();
 	}
 
 	@Test
@@ -99,8 +98,7 @@
 		final ITableItem item = createItem(100, 50);
 		column.init(Collections.singletonList(item), item.getNode());
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("150",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -112,8 +110,7 @@
 		final ITableItem item = createItem(100, 50);
 		column.init(Collections.singletonList(item), item.getNode());
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("100",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -125,8 +122,7 @@
 		final ITableItem item = createItem(100, 50);
 		column.init(Collections.singletonList(item), item.getNode());
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("50",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -138,8 +134,7 @@
 		final ITableItem item = createItem(1000, 0);
 		column.init(Collections.singletonList(item), item.getNode());
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("1.000",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -151,8 +146,7 @@
 		final ITableItem item = createItem(20, 60);
 		column.init(Collections.singletonList(item), item.getNode());
 		column.footer(td, item.getNode(), resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("80",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -167,7 +161,7 @@
 		assertEquals(0, c.compare(i1, i1));
 		assertTrue(c.compare(i1, i2) > 0);
 		assertTrue(c.compare(i2, i1) < 0);
-		doc.close();
+		html.close();
 	}
 
 	@Test
@@ -180,7 +174,7 @@
 		assertEquals(0, c.compare(i1, i1));
 		assertTrue(c.compare(i1, i2) > 0);
 		assertTrue(c.compare(i2, i1) < 0);
-		doc.close();
+		html.close();
 	}
 
 	@Test
@@ -193,7 +187,7 @@
 		assertEquals(0, c.compare(i1, i1));
 		assertTrue(c.compare(i1, i2) > 0);
 		assertTrue(c.compare(i2, i1) < 0);
-		doc.close();
+		html.close();
 	}
 
 	private ITableItem createItem(final int missed, final int covered) {
@@ -224,4 +218,10 @@
 			}
 		};
 	}
+
+	private Document parseDoc() throws Exception {
+		html.close();
+		return support.parse(output.getFile("Test.html"));
+	}
+
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java
index adf4e24..f13ef47 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/LabelColumnTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -21,7 +21,6 @@
 import org.jacoco.core.analysis.ICoverageNode.ElementType;
 import org.jacoco.report.MemoryMultiReportOutput;
 import org.jacoco.report.internal.ReportOutputFolder;
-import org.jacoco.report.internal.html.HTMLDocument;
 import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.HTMLSupport;
 import org.jacoco.report.internal.html.resources.Resources;
@@ -41,7 +40,7 @@
 
 	private Resources resources;
 
-	private HTMLDocument doc;
+	private HTMLElement html;
 
 	private HTMLElement td;
 
@@ -54,9 +53,9 @@
 		output = new MemoryMultiReportOutput();
 		root = new ReportOutputFolder(output);
 		resources = new Resources(root);
-		doc = new HTMLDocument(root.createFile("Test.html"), "UTF-8");
-		doc.head().title();
-		td = doc.body().table("somestyle").tr().td();
+		html = new HTMLElement(root.createFile("Test.html"), "UTF-8");
+		html.head().title();
+		td = html.body().table("somestyle").tr().td();
 		support = new HTMLSupport();
 		column = new LabelColumn();
 	}
@@ -70,15 +69,14 @@
 	@Test
 	public void testInit() throws Exception {
 		assertTrue(column.init(null, null));
-		doc.close();
+		html.close();
 	}
 
 	@Test
 	public void testFooter() throws Exception {
 		column.footer(td, new CoverageNodeImpl(ElementType.GROUP, "Foo"),
 				resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("Total",
 				support.findStr(doc, "/html/body/table/tr/td/text()"));
 	}
@@ -86,8 +84,7 @@
 	@Test
 	public void testItemWithoutLink() throws Exception {
 		column.item(td, createItem("Abc", null), resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("Abc",
 				support.findStr(doc, "/html/body/table/tr/td/span/text()"));
 		assertEquals("el_group",
@@ -97,8 +94,7 @@
 	@Test
 	public void testItemWithLink() throws Exception {
 		column.item(td, createItem("Def", "def.html"), resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("Def",
 				support.findStr(doc, "/html/body/table/tr/td/a/text()"));
 		assertEquals("def.html",
@@ -112,7 +108,7 @@
 		final ITableItem i1 = createItem("abcdef", null);
 		final ITableItem i2 = createItem("aBcDeF", null);
 		assertEquals(0, column.getComparator().compare(i1, i2));
-		doc.close();
+		html.close();
 	}
 
 	@Test
@@ -121,11 +117,12 @@
 		final ITableItem i2 = createItem("world", null);
 		assertTrue(column.getComparator().compare(i1, i2) < 0);
 		assertTrue(column.getComparator().compare(i2, i1) > 0);
-		doc.close();
+		html.close();
 	}
 
 	private ITableItem createItem(final String name, final String link) {
-		final ICoverageNode node = new CoverageNodeImpl(ElementType.GROUP, name);
+		final ICoverageNode node = new CoverageNodeImpl(ElementType.GROUP,
+				name);
 		return new ITableItem() {
 			public String getLinkLabel() {
 				return name;
@@ -145,4 +142,8 @@
 		};
 	}
 
+	private Document parseDoc() throws Exception {
+		html.close();
+		return support.parse(output.getFile("Test.html"));
+	}
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java
index bff3d97..3028e00 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/PercentageColumnTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -25,7 +25,6 @@
 import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.report.MemoryMultiReportOutput;
 import org.jacoco.report.internal.ReportOutputFolder;
-import org.jacoco.report.internal.html.HTMLDocument;
 import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.HTMLSupport;
 import org.jacoco.report.internal.html.resources.Resources;
@@ -45,7 +44,7 @@
 
 	private Resources resources;
 
-	private HTMLDocument doc;
+	private HTMLElement html;
 
 	private HTMLElement td;
 
@@ -58,9 +57,9 @@
 		output = new MemoryMultiReportOutput();
 		root = new ReportOutputFolder(output);
 		resources = new Resources(root);
-		doc = new HTMLDocument(root.createFile("Test.html"), "UTF-8");
-		doc.head().title();
-		td = doc.body().table("somestyle").tr().td();
+		html = new HTMLElement(root.createFile("Test.html"), "UTF-8");
+		html.head().title();
+		td = html.body().table("somestyle").tr().td();
 		support = new HTMLSupport();
 		column = new PercentageColumn(CounterEntity.LINE, Locale.ENGLISH);
 	}
@@ -74,15 +73,14 @@
 	@Test
 	public void testInit() throws Exception {
 		assertTrue(column.init(null, null));
-		doc.close();
+		html.close();
 	}
 
 	@Test
 	public void testItem1() throws Exception {
 		final ITableItem item = createItem(100, 50);
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("33%",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -91,8 +89,7 @@
 	public void testItem2() throws Exception {
 		final ITableItem item = createItem(0, 0);
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("n/a",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -101,8 +98,7 @@
 	public void testRounding() throws Exception {
 		final ITableItem item = createItem(1, 199);
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("99%",
 				support.findStr(doc, "/html/body/table/tr/td[1]/text()"));
 	}
@@ -113,8 +109,7 @@
 				Locale.FRENCH);
 		final ITableItem item = createItem(0, 1000);
 		column.item(td, item, resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		// After integration of JEP 252 into JDK9, CLDR locale data is used by
 		// default, which results in usage of non-breaking space below, while
 		// the legacy locale data uses regular space:
@@ -126,8 +121,7 @@
 	public void testFooter1() throws Exception {
 		final ITableItem item = createItem(20, 60);
 		column.footer(td, item.getNode(), resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("75%", support.findStr(doc, "/html/body/table/tr"));
 	}
 
@@ -135,8 +129,7 @@
 	public void testFooter2() throws Exception {
 		final ITableItem item = createItem(0, 0);
 		column.footer(td, item.getNode(), resources, root);
-		doc.close();
-		final Document doc = support.parse(output.getFile("Test.html"));
+		final Document doc = parseDoc();
 		assertEquals("n/a", support.findStr(doc, "/html/body/table/tr"));
 	}
 
@@ -148,7 +141,7 @@
 		assertTrue(c.compare(i1, i2) < 0);
 		assertTrue(c.compare(i2, i1) > 0);
 		assertEquals(0, c.compare(i1, i1));
-		doc.close();
+		html.close();
 	}
 
 	private ITableItem createItem(final int missed, final int covered) {
@@ -179,4 +172,9 @@
 			}
 		};
 	}
+
+	private Document parseDoc() throws Exception {
+		html.close();
+		return support.parse(output.getFile("Test.html"));
+	}
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/SortIndexTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/SortIndexTest.java
index b3e1895..7ca4722 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/SortIndexTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/SortIndexTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java
index 4e6e2ed..eed6923 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/html/table/TableTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -27,7 +27,6 @@
 import org.jacoco.core.internal.analysis.CounterImpl;
 import org.jacoco.report.MemoryMultiReportOutput;
 import org.jacoco.report.internal.ReportOutputFolder;
-import org.jacoco.report.internal.html.HTMLDocument;
 import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.HTMLSupport;
 import org.jacoco.report.internal.html.resources.Resources;
@@ -47,7 +46,7 @@
 
 	private Resources resources;
 
-	private HTMLDocument doc;
+	private HTMLElement html;
 
 	private HTMLElement body;
 
@@ -58,9 +57,9 @@
 		output = new MemoryMultiReportOutput();
 		root = new ReportOutputFolder(output);
 		resources = new Resources(root);
-		doc = new HTMLDocument(root.createFile("Test.html"), "UTF-8");
-		doc.head().title();
-		body = doc.body();
+		html = new HTMLElement(root.createFile("Test.html"), "UTF-8");
+		html.head().title();
+		body = html.body();
 		table = new Table();
 	}
 
@@ -106,7 +105,7 @@
 				createItem("B", 2), createItem("C", 3));
 		table.add("Header", null, recorder, false);
 		table.render(body, items, createTotal("Sum", 6), resources, root);
-		doc.close();
+		html.close();
 		assertEquals("init-footer-itemA-itemB-itemC-", recorder.toString());
 	}
 
@@ -136,31 +135,35 @@
 		final List<ITableItem> items = Arrays.asList(createItem("A", 1));
 		table.add("Header", null, column, false);
 		table.render(body, items, createTotal("Sum", 1), resources, root);
-		doc.close();
+		html.close();
 	}
 
 	@Test(expected = IllegalStateException.class)
 	public void testTwoDefaultSorts() throws IOException {
-		doc.close();
-		table.add("Header1", null, new StubRenderer(
-				CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)), true);
-		table.add("Header2", null, new StubRenderer(
-				CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)), true);
+		html.close();
+		table.add("Header1", null,
+				new StubRenderer(
+						CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)),
+				true);
+		table.add("Header2", null,
+				new StubRenderer(
+						CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)),
+				true);
 	}
 
 	@Test
 	public void testSortIds() throws Exception {
 		final List<ITableItem> items = Arrays.asList(createItem("C", 3),
 				createItem("E", 4), createItem("A", 1), createItem("D", 2));
-		table.add("Forward", null, new StubRenderer(
-				CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)), false);
-		table.add(
-				"Reverse",
-				null,
-				new StubRenderer(CounterComparator.TOTALITEMS.reverse().on(
-						CounterEntity.CLASS)), false);
+		table.add("Forward", null,
+				new StubRenderer(
+						CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)),
+				false);
+		table.add("Reverse", null, new StubRenderer(
+				CounterComparator.TOTALITEMS.reverse().on(CounterEntity.CLASS)),
+				false);
 		table.render(body, items, createTotal("Sum", 6), resources, root);
-		doc.close();
+		html.close();
 
 		final HTMLSupport support = new HTMLSupport();
 		final Document doc = support.parse(output.getFile("Test.html"));
@@ -199,10 +202,12 @@
 		final List<ITableItem> items = Arrays.asList(createItem("C", 3),
 				createItem("E", 5), createItem("A", 1), createItem("D", 4),
 				createItem("B", 2));
-		table.add("Forward", null, new StubRenderer(
-				CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)), true);
+		table.add("Forward", null,
+				new StubRenderer(
+						CounterComparator.TOTALITEMS.on(CounterEntity.CLASS)),
+				true);
 		table.render(body, items, createTotal("Sum", 1), resources, root);
-		doc.close();
+		html.close();
 
 		final HTMLSupport support = new HTMLSupport();
 		final Document doc = support.parse(output.getFile("Test.html"));
@@ -222,7 +227,8 @@
 	}
 
 	private ITableItem createItem(final String name, final int count) {
-		final ICoverageNode node = new CoverageNodeImpl(ElementType.GROUP, name) {
+		final ICoverageNode node = new CoverageNodeImpl(ElementType.GROUP,
+				name) {
 			{
 				this.classCounter = CounterImpl.getInstance(count, 0);
 			}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/LocalEntityResolver.java b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/LocalEntityResolver.java
index c67fdb1..ae6fc91 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/LocalEntityResolver.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/LocalEntityResolver.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLDocumentTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLDocumentTest.java
deleted file mode 100644
index cd3d985..0000000
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLDocumentTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.report.internal.xml;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link XMLDocument}.
- */
-public class XMLDocumentTest {
-
-	@Test
-	public void testNoDoctype() throws IOException {
-		StringWriter writer = new StringWriter();
-		new XMLDocument("test", null, null, "UTF-8", false, writer).close();
-		assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test/>",
-				writer.toString());
-	}
-
-	@Test
-	public void testNoDoctypeStandalone() throws IOException {
-		StringWriter writer = new StringWriter();
-		new XMLDocument("test", null, null, "UTF-8", true, writer).close();
-		assertEquals(
-				"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
-						+ "<test/>", writer.toString());
-	}
-
-	@Test
-	public void testDoctype() throws IOException {
-		StringWriter writer = new StringWriter();
-		new XMLDocument("test", "sample", "sample.dtd", "UTF-8", false, writer)
-				.close();
-		assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-				+ "<!DOCTYPE test PUBLIC \"sample\" \"sample.dtd\"><test/>",
-				writer.toString());
-	}
-
-	@Test
-	public void testDoctypeStandalone() throws IOException {
-		StringWriter writer = new StringWriter();
-		new XMLDocument("test", "sample", "sample.dtd", "UTF-8", true, writer)
-				.close();
-		assertEquals(
-				"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
-						+ "<!DOCTYPE test PUBLIC \"sample\" \"sample.dtd\">"
-						+ "<test/>", writer.toString());
-	}
-
-	@Test
-	public void testStream() throws IOException {
-		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-		new XMLDocument("test", null, null, "UTF-8", false, buffer).text(
-				"\u00CD\u307e").close();
-		assertEquals(
-				"<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>\u00CD\u307e</test>",
-				buffer.toString("UTF-8"));
-	}
-
-	@Test
-	public void testClose() throws IOException {
-		class CloseVerifier extends StringWriter {
-
-			boolean closed = false;
-
-			@Override
-			public void close() throws IOException {
-				closed = true;
-				super.close();
-			}
-		}
-		CloseVerifier verifier = new CloseVerifier();
-		new XMLDocument("test", null, null, "UTF-8", false, verifier).close();
-		assertTrue(verifier.closed);
-	}
-
-}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLElementTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLElementTest.java
index 0ba4644..5ed161c 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLElementTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLElementTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,8 +13,8 @@
 
 import static org.junit.Assert.assertEquals;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.StringWriter;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -24,123 +24,156 @@
  */
 public class XMLElementTest {
 
-	private StringWriter buffer;
+	private static final String DECL = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+
+	private ByteArrayOutputStream buffer;
 
 	private XMLElement root;
 
 	@Before
-	public void setUp() throws IOException {
-		buffer = new StringWriter();
-		root = new XMLElement(buffer, "root");
-		root.beginOpenTag();
+	public void setup() throws IOException {
+		buffer = new ByteArrayOutputStream();
+		root = new XMLElement("root", null, null, false, "UTF-8", buffer);
 	}
 
 	@Test
-	public void testEmptyNode() throws IOException {
+	public void init_should_write_doctype_when_given() throws IOException {
+		root = new XMLElement("root", "-//JACOCO//TEST", "test.dtd", false,
+				"UTF-8", buffer);
+		assertEquals(DECL
+				+ "<!DOCTYPE root PUBLIC \"-//JACOCO//TEST\" \"test.dtd\"><root/>",
+				actual());
+	}
+
+	@Test
+	public void init_should_write_standalone_when_given() throws IOException {
+		root = new XMLElement("root", null, null, true, "UTF-8", buffer);
+		assertEquals(
+				"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><root/>",
+				actual());
+	}
+
+	@Test
+	public void close_should_emit_empty_element_when_no_children_exist()
+			throws IOException {
+		assertContent("<root/>");
+	}
+
+	@Test
+	public void close_should_be_allowed_multiple_times() throws IOException {
 		root.close();
-		// Second close has no effect:
 		root.close();
-		assertEquals("<root/>", buffer.toString());
+		assertContent("<root/>");
 	}
 
 	@Test(expected = IOException.class)
-	public void testAddAttributeToClosedNode() throws IOException {
+	public void attr_should_throw_exception_when_closed() throws IOException {
 		root.close();
 		root.attr("attr", "value");
 	}
 
 	@Test(expected = IOException.class)
-	public void testAddChildToClosedNode() throws IOException {
+	public void element_should_throw_exception_when_closed()
+			throws IOException {
 		root.close();
 		root.element("child");
 	}
 
 	@Test(expected = IOException.class)
-	public void testAddTextToClosedNode() throws IOException {
+	public void text_should_throw_exception_when_closed() throws IOException {
 		root.close();
 		root.text("text");
 	}
 
 	@Test
-	public void testNestedElement() throws IOException {
+	public void element_should_emit_nested_element() throws IOException {
 		root.element("world");
-		root.close();
-		assertEquals("<root><world/></root>", buffer.toString());
+		assertContent("<root><world/></root>");
 	}
 
 	@Test
-	public void test2NestedElements() throws IOException {
+	public void element_should_allow_multiple_nested_elements()
+			throws IOException {
 		root.element("world");
 		root.element("universe");
-		root.close();
-		assertEquals("<root><world/><universe/></root>", buffer.toString());
+		assertContent("<root><world/><universe/></root>");
 	}
 
 	@Test
-	public void testText() throws IOException {
+	public void text_should_emit_text() throws IOException {
 		root.text("world");
-		root.close();
-		assertEquals("<root>world</root>", buffer.toString());
+		assertContent("<root>world</root>");
 	}
 
 	@Test
-	public void testMixedContent() throws IOException {
+	public void text_should_allow_mixing_with_elements() throws IOException {
 		root.element("tag1");
 		root.text("world");
 		root.element("tag2");
-		root.close();
-		assertEquals("<root><tag1/>world<tag2/></root>", buffer.toString());
+		assertContent("<root><tag1/>world<tag2/></root>");
 	}
 
 	@Test
-	public void testQuotedText() throws IOException {
+	public void test_should_be_quoted() throws IOException {
 		root.text("<black&white\">");
-		root.close();
-		assertEquals("<root>&lt;black&amp;white&quot;&gt;</root>",
-				buffer.toString());
+		assertContent("<root>&lt;black&amp;white&quot;&gt;</root>");
 	}
 
 	@Test
-	public void testNullAttributes() throws IOException {
+	public void attr_should_ignore_call_when_value_is_null()
+			throws IOException {
 		root.attr("id", null);
-		root.close();
-		assertEquals("<root/>", buffer.toString());
+		assertContent("<root/>");
 	}
 
 	@Test
-	public void testStringAttributes() throws IOException {
-		root.attr("id", "12345").attr("quote", "<\">");
-		root.close();
-		assertEquals("<root id=\"12345\" quote=\"&lt;&quot;&gt;\"/>",
-				buffer.toString());
+	public void attr_should_emit_string_value() throws IOException {
+		root.attr("id", "12345");
+		assertContent("<root id=\"12345\"/>");
 	}
 
 	@Test
-	public void testIntAttributes() throws IOException {
-		root.attr("missed", 0).attr("total", 123);
-		root.close();
-		assertEquals("<root missed=\"0\" total=\"123\"/>", buffer.toString());
+	public void attr_should_quote_string_value() throws IOException {
+		root.attr("quote", "<\">");
+		assertContent("<root quote=\"&lt;&quot;&gt;\"/>");
 	}
 
 	@Test
-	public void testLongAttributes() throws IOException {
-		root.attr("min", Long.MIN_VALUE).attr("max", Long.MAX_VALUE);
-		root.close();
-		assertEquals(
-				"<root min=\"-9223372036854775808\" max=\"9223372036854775807\"/>",
-				buffer.toString());
+	public void attr_should_emit_int_value() throws IOException {
+		root.attr("missed", 0);
+		root.attr("total", 123);
+		assertContent("<root missed=\"0\" total=\"123\"/>");
+	}
+
+	@Test
+	public void attr_should_emit_long_value() throws IOException {
+		root.attr("min", Long.MIN_VALUE);
+		root.attr("max", Long.MAX_VALUE);
+		assertContent(
+				"<root min=\"-9223372036854775808\" max=\"9223372036854775807\"/>");
 	}
 
 	@Test(expected = IOException.class)
-	public void testInvalidAttributeOutput1() throws IOException {
+	public void attr_should_throw_exception_when_text_was_added()
+			throws IOException {
 		root.text("text");
 		root.attr("id", "12345");
 	}
 
 	@Test(expected = IOException.class)
-	public void testInvalidAttributeOutput2() throws IOException {
+	public void attr_should_throw_exception_when_child_was_added()
+			throws IOException {
 		root.element("child");
 		root.attr("id", "12345");
 	}
 
+	private void assertContent(String expected) throws IOException {
+		assertEquals(DECL + expected, actual());
+	}
+
+	private String actual() throws IOException {
+		root.close();
+		return buffer.toString("UTF-8");
+	}
+
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLGroupVisitorTest.java b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLGroupVisitorTest.java
index fb8771e..92f5c28 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLGroupVisitorTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLGroupVisitorTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,26 +13,22 @@
 
 import static org.junit.Assert.assertEquals;
 
-import java.io.IOException;
-import java.io.StringWriter;
-
-import javax.xml.parsers.ParserConfigurationException;
+import java.io.ByteArrayOutputStream;
 
 import org.jacoco.report.ReportStructureTestDriver;
 import org.jacoco.report.xml.XMLFormatter;
 import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
 
 /**
  * Unit tests for {@link XMLGroupVisitor}.
  */
 public class XMLGroupVisitorTest {
 
-	private XMLElement root;
+	private ReportElement root;
 
-	private StringWriter buffer;
+	private ByteArrayOutputStream buffer;
 
 	private XMLSupport support;
 
@@ -42,11 +38,9 @@
 
 	@Before
 	public void setup() throws Exception {
-		buffer = new StringWriter();
+		buffer = new ByteArrayOutputStream();
 		support = new XMLSupport(XMLFormatter.class);
-		root = new XMLDocument("report", "-//JACOCO//DTD Report 1.0//EN",
-				"report.dtd", "UTF-8", true, buffer);
-		root.attr("name", "Report");
+		root = new ReportElement("Report", buffer, "UTF-8");
 		handler = new XMLGroupVisitor(root, null);
 		driver = new ReportStructureTestDriver();
 	}
@@ -54,16 +48,14 @@
 	@Test
 	public void testVisitBundle() throws Exception {
 		driver.sendBundle(handler);
-		root.close();
-		final Document doc = getDocument();
+		final Document doc = parseDoc();
 		assertEquals("bundle", support.findStr(doc, "//report/group/@name"));
 	}
 
 	@Test
 	public void testVisitGroup() throws Exception {
 		driver.sendGroup(handler);
-		root.close();
-		final Document doc = getDocument();
+		final Document doc = parseDoc();
 		assertEquals("group", support.findStr(doc, "//report/group/@name"));
 	}
 
@@ -71,15 +63,14 @@
 	public void testVisitEnd() throws Exception {
 		driver.sendBundle(handler);
 		handler.visitEnd();
-		root.close();
-		final Document doc = getDocument();
+		final Document doc = parseDoc();
 		assertEquals("2", support.findStr(doc,
 				"//report/counter[@type='BRANCH']/@covered"));
 	}
 
-	private Document getDocument() throws SAXException, IOException,
-			ParserConfigurationException {
-		return support.parse(buffer.toString());
+	private Document parseDoc() throws Exception {
+		root.close();
+		return support.parse(buffer);
 	}
 
 }
diff --git a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLSupport.java b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLSupport.java
index c95e7b4..fbf4af4 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLSupport.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/internal/xml/XMLSupport.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,8 +14,8 @@
 import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.StringReader;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -71,13 +71,13 @@
 		return xpath;
 	}
 
-	public Document parse(String document) throws SAXException, IOException,
-			ParserConfigurationException {
-		return builder.parse(new InputSource(new StringReader(document)));
+	public Document parse(ByteArrayOutputStream buffer)
+			throws SAXException, IOException, ParserConfigurationException {
+		return parse(buffer.toByteArray());
 	}
 
-	public Document parse(byte[] document) throws SAXException, IOException,
-			ParserConfigurationException {
+	public Document parse(byte[] document)
+			throws SAXException, IOException, ParserConfigurationException {
 		return builder
 				.parse(new InputSource(new ByteArrayInputStream(document)));
 	}
diff --git a/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java b/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java
index c79078e..43157f6 100644
--- a/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java
+++ b/org.jacoco.report.test/src/org/jacoco/report/xml/XMLFormatterTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -98,6 +98,8 @@
 		assertPathMatches("org/jacoco/example", "/report/group/package/@name");
 		assertPathMatches("org/jacoco/example/FooClass",
 				"/report/group/package/class/@name");
+		assertPathMatches("FooClass.java",
+				"/report/group/package/class/@sourcefilename");
 		assertPathMatches("fooMethod",
 				"/report/group/package/class/method/@name");
 
@@ -132,9 +134,15 @@
 		visitor.visitInfo(infos, data);
 		driver.sendBundle(visitor);
 		assertPathMatches("bundle", "/report/@name");
+
+		assertPathMatches("2", "count(/report/package)");
 		assertPathMatches("org/jacoco/example", "/report/package/@name");
+
+		assertPathMatches("3", "count(/report/package/class)");
 		assertPathMatches("org/jacoco/example/FooClass",
 				"/report/package/class/@name");
+
+		assertPathMatches("1", "count(/report/package/class/method)");
 		assertPathMatches("fooMethod", "/report/package/class/method/@name");
 
 		assertPathMatches("1", "count(/report/counter[@type='INSTRUCTION'])");
@@ -160,6 +168,38 @@
 		assertPathMatches("1", "count(/report/counter[@type='CLASS'])");
 		assertPathMatches("0", "report/counter[@type='CLASS']/@missed");
 		assertPathMatches("1", "report/counter[@type='CLASS']/@covered");
+
+		assertPathMatches("2",
+				"count(report/package[@name='org/jacoco/example']/sourcefile)");
+		assertPathMatches("3", "count(report/package/sourcefile/line)");
+		assertPathMatches("1",
+				"report/package/sourcefile[@name='FooClass.java']/line[1]/@nr");
+		assertPathMatches("3",
+				"report/package/sourcefile[@name='FooClass.java']/line[1]/@mi");
+		assertPathMatches("2",
+				"report/package/sourcefile[@name='FooClass.java']/line[2]/@nr");
+		assertPathMatches("2",
+				"report/package/sourcefile[@name='FooClass.java']/line[2]/@cb");
+		// empty line is skipped
+		assertPathMatches("4",
+				"report/package/sourcefile[@name='FooClass.java']/line[3]/@nr");
+		assertPathMatches("4",
+				"report/package/sourcefile[@name='FooClass.java']/line[3]/@mi");
+
+		assertPathMatches("0", "count(/report/package[@name='empty']/counter)");
+
+		assertPathMatches("1", "count(/report/package[@name='empty']/class)");
+		assertPathMatches("empty/Empty",
+				"/report/package[@name='empty']/class/@name");
+		assertPathMatches("0",
+				"count(report/package[@name='empty']/class/*)");
+
+		assertPathMatches("1",
+				"count(/report/package[@name='empty']/sourcefile)");
+		assertPathMatches("Empty.java",
+				"report/package[@name='empty']/sourcefile/@name");
+		assertPathMatches("0",
+				"count(report/package[@name='empty']/sourcefile/*)");
 	}
 
 	@Test
@@ -167,8 +207,8 @@
 		final IReportVisitor visitor = formatter.createVisitor(output);
 		visitor.visitInfo(infos, data);
 		driver.sendBundle(visitor);
-		final BufferedReader reader = new BufferedReader(new InputStreamReader(
-				output.getContentsAsStream(), "UTF-8"));
+		final BufferedReader reader = new BufferedReader(
+				new InputStreamReader(output.getContentsAsStream(), "UTF-8"));
 		final String line = reader.readLine();
 		assertTrue(line,
 				line.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\""));
@@ -180,8 +220,8 @@
 		final IReportVisitor visitor = formatter.createVisitor(output);
 		visitor.visitInfo(infos, data);
 		driver.sendBundle(visitor);
-		final BufferedReader reader = new BufferedReader(new InputStreamReader(
-				output.getContentsAsStream(), "UTF-16"));
+		final BufferedReader reader = new BufferedReader(
+				new InputStreamReader(output.getContentsAsStream(), "UTF-16"));
 		final String line = reader.readLine();
 		assertTrue(line,
 				line.startsWith("<?xml version=\"1.0\" encoding=\"UTF-16\""));
@@ -190,7 +230,7 @@
 	private void assertPathMatches(String expected, String path)
 			throws Exception {
 		XMLSupport support = new XMLSupport(XMLFormatter.class);
-		Document document = support.parse(output.toByteArray());
+		Document document = support.parse(output);
 		assertEquals(expected, support.findStr(document, path));
 	}
 
diff --git a/org.jacoco.report/pom.xml b/org.jacoco.report/pom.xml
index 30f5ba5..9b83452 100644
--- a/org.jacoco.report/pom.xml
+++ b/org.jacoco.report/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
diff --git a/org.jacoco.report/src/org/jacoco/report/DirectorySourceFileLocator.java b/org.jacoco.report/src/org/jacoco/report/DirectorySourceFileLocator.java
index cb8cc2b..79881a7 100644
--- a/org.jacoco.report/src/org/jacoco/report/DirectorySourceFileLocator.java
+++ b/org.jacoco.report/src/org/jacoco/report/DirectorySourceFileLocator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java b/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java
index 74b504c..436db74 100644
--- a/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java
+++ b/org.jacoco.report/src/org/jacoco/report/FileMultiReportOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/ILanguageNames.java b/org.jacoco.report/src/org/jacoco/report/ILanguageNames.java
index 0e669bb..68a51b5 100644
--- a/org.jacoco.report/src/org/jacoco/report/ILanguageNames.java
+++ b/org.jacoco.report/src/org/jacoco/report/ILanguageNames.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -23,7 +23,7 @@
 	 *            vm name of a package
 	 * @return language specific notation for the package
 	 */
-	public String getPackageName(String vmname);
+	String getPackageName(String vmname);
 
 	/**
 	 * Calculates the language specific name of a class.
@@ -39,8 +39,8 @@
 	 *            vm names of interfaces of the class (may be <code>null</code>)
 	 * @return language specific notation of the class
 	 */
-	public String getClassName(String vmname, String vmsignature,
-			String vmsuperclass, String[] vminterfaces);
+	String getClassName(String vmname, String vmsignature, String vmsuperclass,
+			String[] vminterfaces);
 
 	/**
 	 * Calculates the language specific qualified name of a class.
@@ -49,7 +49,7 @@
 	 *            vm name of a class
 	 * @return language specific qualified notation of the class
 	 */
-	public String getQualifiedClassName(String vmname);
+	String getQualifiedClassName(String vmname);
 
 	/**
 	 * Calculates the language specific name of a method.
@@ -64,8 +64,8 @@
 	 *            vm signature of the method (may be <code>null</code>)
 	 * @return language specific notation for the method
 	 */
-	public String getMethodName(String vmclassname, String vmmethodname,
-			String vmdesc, String vmsignature);
+	String getMethodName(String vmclassname, String vmmethodname, String vmdesc,
+			String vmsignature);
 
 	/**
 	 * Calculates the language specific fully qualified name of a method.
@@ -80,7 +80,7 @@
 	 *            vm signature of the method (may be <code>null</code>)
 	 * @return language specific notation for the method
 	 */
-	public String getQualifiedMethodName(String vmclassname,
-			String vmmethodname, String vmdesc, String vmsignature);
+	String getQualifiedMethodName(String vmclassname, String vmmethodname,
+			String vmdesc, String vmsignature);
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java b/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java
index c249ea9..e40d36b 100644
--- a/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java
+++ b/org.jacoco.report/src/org/jacoco/report/IMultiReportOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -29,7 +29,7 @@
 	 * @throws IOException
 	 *             if the creation fails
 	 */
-	public OutputStream createFile(String path) throws IOException;
+	OutputStream createFile(String path) throws IOException;
 
 	/**
 	 * Closes the underlying resource container.
@@ -37,6 +37,6 @@
 	 * @throws IOException
 	 *             if closing fails
 	 */
-	public void close() throws IOException;
+	void close() throws IOException;
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/IReportGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/IReportGroupVisitor.java
index 9efb246..96867e0 100644
--- a/org.jacoco.report/src/org/jacoco/report/IReportGroupVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/IReportGroupVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java b/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
index 6b145cf..db36796 100644
--- a/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -38,7 +38,7 @@
 	 * @throws IOException
 	 *             in case of IO problems with the report writer
 	 */
-	public void visitInfo(List<SessionInfo> sessionInfos,
+	void visitInfo(List<SessionInfo> sessionInfos,
 			Collection<ExecutionData> executionData) throws IOException;
 
 	/**
@@ -47,6 +47,6 @@
 	 * @throws IOException
 	 *             in case of IO problems with the report writer
 	 */
-	public void visitEnd() throws IOException;
+	void visitEnd() throws IOException;
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/ISourceFileLocator.java b/org.jacoco.report/src/org/jacoco/report/ISourceFileLocator.java
index ed5809e..e32cbbf 100644
--- a/org.jacoco.report/src/org/jacoco/report/ISourceFileLocator.java
+++ b/org.jacoco.report/src/org/jacoco/report/ISourceFileLocator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -31,7 +31,7 @@
 	 * @throws IOException
 	 *             in case of problems while opening the file
 	 */
-	public Reader getSourceFile(String packageName, String fileName)
+	Reader getSourceFile(String packageName, String fileName)
 			throws IOException;
 
 	/**
@@ -39,6 +39,6 @@
 	 * 
 	 * @return tab width as number of blanks
 	 */
-	public int getTabWidth();
+	int getTabWidth();
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/InputStreamSourceFileLocator.java b/org.jacoco.report/src/org/jacoco/report/InputStreamSourceFileLocator.java
index af1d143..0d1b381 100644
--- a/org.jacoco.report/src/org/jacoco/report/InputStreamSourceFileLocator.java
+++ b/org.jacoco.report/src/org/jacoco/report/InputStreamSourceFileLocator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/JavaNames.java b/org.jacoco.report/src/org/jacoco/report/JavaNames.java
index daa301b..1ef1bae 100644
--- a/org.jacoco.report/src/org/jacoco/report/JavaNames.java
+++ b/org.jacoco.report/src/org/jacoco/report/JavaNames.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java b/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
index 0d81d14..3cd5e55 100644
--- a/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/MultiSourceFileLocator.java b/org.jacoco.report/src/org/jacoco/report/MultiSourceFileLocator.java
index 2ac55e8..90677d5 100644
--- a/org.jacoco.report/src/org/jacoco/report/MultiSourceFileLocator.java
+++ b/org.jacoco.report/src/org/jacoco/report/MultiSourceFileLocator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java b/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java
index 9c745cd..8138cee 100644
--- a/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java
+++ b/org.jacoco.report/src/org/jacoco/report/ZipMultiReportOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/check/BundleChecker.java b/org.jacoco.report/src/org/jacoco/report/check/BundleChecker.java
index 911fdd7..c6cd888 100644
--- a/org.jacoco.report/src/org/jacoco/report/check/BundleChecker.java
+++ b/org.jacoco.report/src/org/jacoco/report/check/BundleChecker.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/check/IViolationsOutput.java b/org.jacoco.report/src/org/jacoco/report/check/IViolationsOutput.java
index 0dfac3a..36c96bb 100644
--- a/org.jacoco.report/src/org/jacoco/report/check/IViolationsOutput.java
+++ b/org.jacoco.report/src/org/jacoco/report/check/IViolationsOutput.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/check/Limit.java b/org.jacoco.report/src/org/jacoco/report/check/Limit.java
index 8881ddb..5a24b45 100644
--- a/org.jacoco.report/src/org/jacoco/report/check/Limit.java
+++ b/org.jacoco.report/src/org/jacoco/report/check/Limit.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/check/Rule.java b/org.jacoco.report/src/org/jacoco/report/check/Rule.java
index 949d3b5..b247285 100644
--- a/org.jacoco.report/src/org/jacoco/report/check/Rule.java
+++ b/org.jacoco.report/src/org/jacoco/report/check/Rule.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java b/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java
index fe6715e..cc6acf0 100644
--- a/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java
+++ b/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/check/package-info.java b/org.jacoco.report/src/org/jacoco/report/check/package-info.java
index 35e547a..d3bee1e 100644
--- a/org.jacoco.report/src/org/jacoco/report/check/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/check/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Rules check implementation.
  */
-package org.jacoco.report.check;
\ No newline at end of file
+package org.jacoco.report.check;
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java b/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
index cb3f03c..793e215 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java b/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java
index 0f50ffe..594feb4 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/CSVGroupHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -43,7 +43,9 @@
 		for (final IPackageCoverage p : bundle.getPackages()) {
 			final String packageName = p.getName();
 			for (final IClassCoverage c : p.getClasses()) {
-				writer.writeRow(name, packageName, c);
+				if (c.containsCode()) {
+					writer.writeRow(name, packageName, c);
+				}
 			}
 		}
 	}
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java b/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java
index a9f7ee9..ef9a05c 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/ClassRowWriter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/DelimitedWriter.java b/org.jacoco.report/src/org/jacoco/report/csv/DelimitedWriter.java
index 0d37fc0..deadeec 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/DelimitedWriter.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/DelimitedWriter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/package-info.java b/org.jacoco.report/src/org/jacoco/report/csv/package-info.java
index 9e1fd91..e6194bc 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * CSV report implementation.
  */
-package org.jacoco.report.csv;
\ No newline at end of file
+package org.jacoco.report.csv;
diff --git a/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java b/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
index 5c4741b..9994ced 100644
--- a/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/html/package-info.java b/org.jacoco.report/src/org/jacoco/report/html/package-info.java
index 5a53705..9e0014e 100644
--- a/org.jacoco.report/src/org/jacoco/report/html/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/html/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * HTML report implementation.
  */
-package org.jacoco.report.html;
\ No newline at end of file
+package org.jacoco.report.html;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/AbstractGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/internal/AbstractGroupVisitor.java
index 7674427..63da569 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/AbstractGroupVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/AbstractGroupVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java b/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java
index 00eb0ed..65eba09 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/NormalizedFileNames.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java b/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java
index a429256..a0f0558 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/ReportOutputFolder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLDocument.java b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLDocument.java
deleted file mode 100644
index fb461e1..0000000
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLDocument.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.report.internal.html;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.Writer;
-
-import org.jacoco.report.internal.xml.XMLDocument;
-
-/**
- * {@link XMLDocument} that declares its content type to be XHTML 1.0 Strict and
- * produces {@link HTMLElement}s as children.
- */
-public class HTMLDocument extends XMLDocument {
-
-	private static final String ROOT = "html";
-
-	private static final String PUBID = "-//W3C//DTD XHTML 1.0 Strict//EN";
-
-	private static final String SYSTEM = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
-
-	private static final String XMLNS = "xmlns";
-
-	private static final String XHTML_NAMESPACE_URL = "http://www.w3.org/1999/xhtml";
-
-	/**
-	 * Creates a new HTML document based on the given writer.
-	 * 
-	 * @param writer
-	 *            writer for content output
-	 * @param encoding
-	 *            document encoding
-	 * @throws IOException
-	 *             in case of problems with the writer
-	 */
-	public HTMLDocument(final Writer writer, final String encoding)
-			throws IOException {
-		super(ROOT, PUBID, SYSTEM, encoding, false, writer);
-		attr(XMLNS, XHTML_NAMESPACE_URL);
-	}
-
-	/**
-	 * Creates a new HTML document based on the given stream.
-	 * 
-	 * @param output
-	 *            stream for content output
-	 * @param encoding
-	 *            document encoding
-	 * @throws IOException
-	 *             in case of problems with the stream
-	 */
-	public HTMLDocument(final OutputStream output, final String encoding)
-			throws IOException {
-		super(ROOT, PUBID, SYSTEM, encoding, false, output);
-		attr(XMLNS, XHTML_NAMESPACE_URL);
-	}
-
-	@Override
-	public HTMLElement element(final String name) throws IOException {
-		final HTMLElement element = new HTMLElement(writer, name);
-		addChildElement(element);
-		return element;
-	}
-
-	/**
-	 * Creates a 'head' element.
-	 * 
-	 * @return 'head' element
-	 * @throws IOException
-	 *             in case of problems with the writer
-	 */
-	public HTMLElement head() throws IOException {
-		return element("head");
-	}
-
-	/**
-	 * Creates a 'body' element.
-	 * 
-	 * @return 'body' element
-	 * @throws IOException
-	 *             in case of problems with the writer
-	 */
-	public HTMLElement body() throws IOException {
-		return element("body");
-	}
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java
index 18f5bdd..616b318 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLElement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,7 +12,7 @@
 package org.jacoco.report.internal.html;
 
 import java.io.IOException;
-import java.io.Writer;
+import java.io.OutputStream;
 
 import org.jacoco.report.internal.ReportOutputFolder;
 import org.jacoco.report.internal.xml.XMLElement;
@@ -23,23 +23,34 @@
  */
 public class HTMLElement extends XMLElement {
 
+	private static final String PUBID = "-//W3C//DTD XHTML 1.0 Strict//EN";
+
+	private static final String SYSTEM = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
+
 	/**
-	 * Creates a new element for a HTML document.
+	 * Creates a <code>html</code> root element of a XHTML document.
 	 * 
-	 * @param writer
-	 *            all output will be written directly to this
-	 * @param name
-	 *            element name
+	 * @param encoding
+	 *            character encoding used for output
+	 * @param output
+	 *            output stream will be closed if the root element is closed
+	 * @throws IOException
+	 *             in case of problems with the underlying output
 	 */
-	protected HTMLElement(final Writer writer, final String name) {
-		super(writer, name);
+	public HTMLElement(final OutputStream output, final String encoding)
+			throws IOException {
+		super("html", PUBID, SYSTEM, false, encoding, output);
+		attr("xmlns", "http://www.w3.org/1999/xhtml");
+	}
+
+	private HTMLElement(final String name, final HTMLElement parent)
+			throws IOException {
+		super(name, parent);
 	}
 
 	@Override
 	public HTMLElement element(final String name) throws IOException {
-		final HTMLElement element = new HTMLElement(writer, name);
-		addChildElement(element);
-		return element;
+		return new HTMLElement(name, this);
 	}
 
 	private void classattr(final String classattr) throws IOException {
@@ -47,6 +58,28 @@
 	}
 
 	/**
+	 * Creates a 'head' element.
+	 * 
+	 * @return 'head' element
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public HTMLElement head() throws IOException {
+		return element("head");
+	}
+
+	/**
+	 * Creates a 'body' element.
+	 * 
+	 * @return 'body' element
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public HTMLElement body() throws IOException {
+		return element("body");
+	}
+
+	/**
 	 * Creates a 'meta' element.
 	 * 
 	 * @param httpequivattr
@@ -55,10 +88,10 @@
 	 *            value for the content attribute
 	 * @return 'meta' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
-	public HTMLElement meta(final String httpequivattr, final String contentattr)
-			throws IOException {
+	public HTMLElement meta(final String httpequivattr,
+			final String contentattr) throws IOException {
 		final HTMLElement meta = element("meta");
 		meta.attr("http-equiv", httpequivattr);
 		meta.attr("content", contentattr);
@@ -76,7 +109,7 @@
 	 *            value for the type attribute
 	 * @return 'link' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement link(final String relattr, final String hrefattr,
 			final String typeattr) throws IOException {
@@ -92,7 +125,7 @@
 	 * 
 	 * @return 'title' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement title() throws IOException {
 		return element("title");
@@ -103,7 +136,7 @@
 	 * 
 	 * @return 'h1' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement h1() throws IOException {
 		return element("h1");
@@ -114,7 +147,7 @@
 	 * 
 	 * @return 'p' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement p() throws IOException {
 		return element("p");
@@ -125,7 +158,7 @@
 	 * 
 	 * @return 'span' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement span() throws IOException {
 		return element("span");
@@ -138,7 +171,7 @@
 	 *            value of the class attribute
 	 * @return 'span' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement span(final String classattr) throws IOException {
 		final HTMLElement span = span();
@@ -155,7 +188,7 @@
 	 *            value of the id attribute
 	 * @return 'span' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement span(final String classattr, final String idattr)
 			throws IOException {
@@ -171,7 +204,7 @@
 	 *            value of the class attribute
 	 * @return 'div' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement div(final String classattr) throws IOException {
 		final HTMLElement div = element("div");
@@ -184,7 +217,7 @@
 	 * 
 	 * @return 'code' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement code() throws IOException {
 		return element("code");
@@ -197,7 +230,7 @@
 	 *            value of the class attribute
 	 * @return 'pre' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement pre(final String classattr) throws IOException {
 		final HTMLElement pre = element("pre");
@@ -212,7 +245,7 @@
 	 *            value of the href attribute
 	 * @return 'a' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement a(final String hrefattr) throws IOException {
 		final HTMLElement a = element("a");
@@ -229,7 +262,7 @@
 	 *            value of the class attribute
 	 * @return 'a' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement a(final String hrefattr, final String classattr)
 			throws IOException {
@@ -247,10 +280,10 @@
 	 *            base folder where the link should be placed
 	 * @return 'a' element or 'span' element, if the link target does not exist
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
-	public HTMLElement a(final ILinkable linkable, final ReportOutputFolder base)
-			throws IOException {
+	public HTMLElement a(final ILinkable linkable,
+			final ReportOutputFolder base) throws IOException {
 		final HTMLElement a;
 		final String link = linkable.getLink(base);
 		if (link == null) {
@@ -269,7 +302,7 @@
 	 *            value of the class attribute
 	 * @return 'table' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement table(final String classattr) throws IOException {
 		final HTMLElement table = element("table");
@@ -283,7 +316,7 @@
 	 * 
 	 * @return 'thead' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement thead() throws IOException {
 		return element("thead");
@@ -294,7 +327,7 @@
 	 * 
 	 * @return 'tfoot' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement tfoot() throws IOException {
 		return element("tfoot");
@@ -305,7 +338,7 @@
 	 * 
 	 * @return 'tbody' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement tbody() throws IOException {
 		return element("tbody");
@@ -316,7 +349,7 @@
 	 * 
 	 * @return 'tr' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement tr() throws IOException {
 		return element("tr");
@@ -327,7 +360,7 @@
 	 * 
 	 * @return 'td' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement td() throws IOException {
 		return element("td");
@@ -340,7 +373,7 @@
 	 *            value of the class attribute
 	 * @return 'td' element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public HTMLElement td(final String classattr) throws IOException {
 		final HTMLElement td = td();
@@ -360,7 +393,7 @@
 	 * @param titleattr
 	 *            value of the title and alt attribute
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public void img(final String srcattr, final int widthattr,
 			final int heightattr, final String titleattr) throws IOException {
@@ -374,19 +407,16 @@
 	}
 
 	/**
-	 * Creates a 'script' element.
+	 * Creates a JavaScript 'script' element.
 	 * 
-	 * @param typeattr
-	 *            value of the type attribute
 	 * @param srcattr
 	 *            value of the src attribute
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
-	public void script(final String typeattr, final String srcattr)
-			throws IOException {
+	public void script(final String srcattr) throws IOException {
 		final HTMLElement script = element("script");
-		script.attr("type", typeattr);
+		script.attr("type", "text/javascript");
 		script.attr("src", srcattr);
 		// Enforce open and closing tag otherwise it won't work in browsers:
 		script.text("");
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLGroupVisitor.java
index c2991f0..e690efe 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLGroupVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/HTMLGroupVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java b/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java
index 49499de..5ce47b6 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/IHTMLReportContext.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,55 +28,55 @@
 	 * 
 	 * @return static resources
 	 */
-	public Resources getResources();
+	Resources getResources();
 
 	/**
 	 * Returns the language names call-back used in this report.
 	 * 
 	 * @return language names
 	 */
-	public ILanguageNames getLanguageNames();
+	ILanguageNames getLanguageNames();
 
 	/**
 	 * Returns a table for rendering coverage nodes.
 	 * 
 	 * @return table for rendering
 	 */
-	public Table getTable();
+	Table getTable();
 
 	/**
 	 * Returns a string of textual information to include in every page footer.
 	 * 
 	 * @return footer text or empty string
 	 */
-	public String getFooterText();
+	String getFooterText();
 
 	/**
 	 * Returns the link to the sessions page.
 	 * 
 	 * @return sessions page link
 	 */
-	public ILinkable getSessionsPage();
+	ILinkable getSessionsPage();
 
 	/**
 	 * Returns the encoding of the generated HTML documents.
 	 * 
 	 * @return encoding for generated HTML documents
 	 */
-	public String getOutputEncoding();
+	String getOutputEncoding();
 
 	/**
 	 * Returns the service for index updates.
 	 * 
 	 * @return sevice for indes updates
 	 */
-	public IIndexUpdate getIndexUpdate();
+	IIndexUpdate getIndexUpdate();
 
 	/**
 	 * Returns the locale used to format numbers and dates.
 	 * 
 	 * @return locale for numbers and dates
 	 */
-	public Locale getLocale();
+	Locale getLocale();
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java b/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java
index 900e495..bfec938 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/ILinkable.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -26,20 +26,20 @@
 	 *            folder where the link should be inserted
 	 * @return relative link or <code>null</code> if the target does not exist
 	 */
-	public String getLink(final ReportOutputFolder base);
+	String getLink(ReportOutputFolder base);
 
 	/**
 	 * Returns the display label used for the link.
 	 * 
 	 * @return display label
 	 */
-	public String getLinkLabel();
+	String getLinkLabel();
 
 	/**
 	 * Optional style class to be associated with the link.
 	 * 
 	 * @return link style class or <code>null</code>
 	 */
-	public String getLinkStyle();
+	String getLinkStyle();
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java b/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
index 3f2b821..08fba90 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/index/ElementIndex.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/index/IIndexUpdate.java b/org.jacoco.report/src/org/jacoco/report/internal/html/index/IIndexUpdate.java
index b6910fc..ce8d8ab 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/index/IIndexUpdate.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/index/IIndexUpdate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -27,6 +27,6 @@
 	 * @param classid
 	 *            identifier of the class
 	 */
-	public void addClass(ILinkable link, long classid);
+	void addClass(ILinkable link, long classid);
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/index/package-info.java b/org.jacoco.report/src/org/jacoco/report/internal/html/index/package-info.java
index 0d3edb5..e6760bb 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/index/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/index/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Internal: Index generation for HTML reports.
  */
-package org.jacoco.report.internal.html.index;
\ No newline at end of file
+package org.jacoco.report.internal.html.index;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/BundlePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/BundlePage.java
index 3189faa..4caeb67 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/BundlePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/BundlePage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -18,6 +18,7 @@
 import org.jacoco.core.analysis.IPackageCoverage;
 import org.jacoco.report.ISourceFileLocator;
 import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.IHTMLReportContext;
 
 /**
@@ -62,6 +63,9 @@
 
 	private void renderPackages() throws IOException {
 		for (final IPackageCoverage p : bundle.getPackages()) {
+			if (!p.containsCode()) {
+				continue;
+			}
 			final String packagename = p.getName();
 			final String foldername = packagename.length() == 0 ? "default"
 					: packagename.replace('/', '.');
@@ -82,4 +86,16 @@
 		return "index.html";
 	}
 
+	@Override
+	protected void content(HTMLElement body) throws IOException {
+		if (bundle.getPackages().isEmpty()) {
+			body.p().text("No class files specified.");
+		} else if (!bundle.containsCode()) {
+			body.p().text(
+					"None of the analyzed classes contain code relevant for code coverage.");
+		} else {
+			super.content(body);
+		}
+	}
+
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/ClassPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ClassPage.java
index 2fab2c2..8a759a3 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/ClassPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ClassPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
 import org.jacoco.core.analysis.IClassCoverage;
 import org.jacoco.core.analysis.IMethodCoverage;
 import org.jacoco.report.internal.ReportOutputFolder;
+import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.IHTMLReportContext;
 import org.jacoco.report.internal.html.ILinkable;
 
@@ -80,4 +81,35 @@
 				getNode().getInterfaceNames());
 	}
 
+	@Override
+	protected void content(HTMLElement body) throws IOException {
+		if (getNode().isNoMatch()) {
+			body.p().text(
+					"A different version of class was executed at runtime.");
+		}
+
+		if (getNode().getLineCounter().getTotalCount() == 0) {
+			body.p().text(
+					"Class files must be compiled with debug information to show line coverage.");
+		}
+
+		final String sourceFileName = getNode().getSourceFileName();
+		if (sourceFileName == null) {
+			body.p().text(
+					"Class files must be compiled with debug information to link with source files.");
+
+		} else if (sourcePage == null) {
+			final String sourcePath;
+			if (getNode().getPackageName().length() != 0) {
+				sourcePath = getNode().getPackageName() + "/" + sourceFileName;
+			} else {
+				sourcePath = sourceFileName;
+			}
+			body.p().text("Source file \"" + sourcePath
+					+ "\" was not found during generation of report.");
+		}
+
+		super.content(body);
+	}
+
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/GroupPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/GroupPage.java
index 8ecb5de..9e64605 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/GroupPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/GroupPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/MethodItem.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/MethodItem.java
index ecdf02a..601c711 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/MethodItem.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/MethodItem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/NodePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/NodePage.java
index 8f1dbdd..6dbb37f 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/NodePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/NodePage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackagePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackagePage.java
index f473850..3d5e24d 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackagePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackagePage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -65,6 +65,9 @@
 
 	private void renderClasses() throws IOException {
 		for (final IClassCoverage c : getNode().getClasses()) {
+			if (!c.containsCode()) {
+				continue;
+			}
 			final ILinkable sourceFilePage = packageSourcePage
 					.getSourceFilePage(c.getSourceFileName());
 			final ClassPage page = new ClassPage(c, this, sourceFilePage,
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java
index cfe7f79..988033d 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/PackageSourcePage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -79,6 +79,9 @@
 	private final void renderSourceFilePages() throws IOException {
 		final String packagename = getNode().getName();
 		for (final ISourceFileCoverage s : getNode().getSourceFiles()) {
+			if (!s.containsCode()) {
+				continue;
+			}
 			final String sourcename = s.getName();
 			final Reader reader = locator
 					.getSourceFile(packagename, sourcename);
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/ReportPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ReportPage.java
index 7dfec53..9660bdf 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/ReportPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/ReportPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -15,7 +15,6 @@
 
 import org.jacoco.core.JaCoCo;
 import org.jacoco.report.internal.ReportOutputFolder;
-import org.jacoco.report.internal.html.HTMLDocument;
 import org.jacoco.report.internal.html.HTMLElement;
 import org.jacoco.report.internal.html.IHTMLReportContext;
 import org.jacoco.report.internal.html.ILinkable;
@@ -71,12 +70,12 @@
 	 *             if the page can't be written
 	 */
 	public void render() throws IOException {
-		final HTMLDocument doc = new HTMLDocument(
+		final HTMLElement html = new HTMLElement(
 				folder.createFile(getFileName()), context.getOutputEncoding());
-		doc.attr("lang", context.getLocale().getLanguage());
-		head(doc.head());
-		body(doc.body());
-		doc.close();
+		html.attr("lang", context.getLocale().getLanguage());
+		head(html.head());
+		body(html.body());
+		html.close();
 	}
 
 	/**
@@ -130,8 +129,8 @@
 		span.a(context.getSessionsPage(), folder);
 	}
 
-	private void breadcrumb(final HTMLElement div, final ReportOutputFolder base)
-			throws IOException {
+	private void breadcrumb(final HTMLElement div,
+			final ReportOutputFolder base) throws IOException {
 		breadcrumbParent(parent, div, base);
 		div.span(getLinkStyle()).text(getLinkLabel());
 	}
@@ -151,7 +150,8 @@
 		final HTMLElement versioninfo = footer.span(Styles.RIGHT);
 		versioninfo.text("Created with ");
 		versioninfo.a(JaCoCo.HOMEURL).text("JaCoCo");
-		versioninfo.text(" ").text(JaCoCo.VERSION);
+		versioninfo.text(" ");
+		versioninfo.text(JaCoCo.VERSION);
 		footer.text(context.getFooterText());
 	}
 
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
index d01d589..67de494 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFileItem.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFileItem.java
index 27df8bb..70628ae 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFileItem.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFileItem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFilePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFilePage.java
index 8658d60..d4fe243 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFilePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceFilePage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -67,14 +67,10 @@
 	@Override
 	protected void head(final HTMLElement head) throws IOException {
 		super.head(head);
-		head.link(
-				"stylesheet",
-				context.getResources().getLink(folder,
-						Resources.PRETTIFY_STYLESHEET), "text/css");
-		head.script(
-				"text/javascript",
-				context.getResources().getLink(folder,
-						Resources.PRETTIFY_SCRIPT));
+		head.link("stylesheet", context.getResources().getLink(folder,
+				Resources.PRETTIFY_STYLESHEET), "text/css");
+		head.script(context.getResources().getLink(folder,
+				Resources.PRETTIFY_SCRIPT));
 	}
 
 	@Override
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceHighlighter.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceHighlighter.java
index fea5b61..5cb8eb0 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceHighlighter.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SourceHighlighter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/TablePage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/TablePage.java
index 30c4cdc..c8cd0c1 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/TablePage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/TablePage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -28,8 +28,8 @@
  * @param <NodeType>
  *            type of the node represented by this page
  */
-public abstract class TablePage<NodeType extends ICoverageNode> extends
-		NodePage<NodeType> {
+public abstract class TablePage<NodeType extends ICoverageNode>
+		extends NodePage<NodeType> {
 
 	private final List<ITableItem> items = new ArrayList<ITableItem>();
 
@@ -64,7 +64,7 @@
 	@Override
 	protected void head(final HTMLElement head) throws IOException {
 		super.head(head);
-		head.script("text/javascript",
+		head.script(
 				context.getResources().getLink(folder, Resources.SORT_SCRIPT));
 	}
 
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java
index bfb6a56..29fab0f 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Resources.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Styles.java b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Styles.java
index 0d76887..0d0d6cb 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Styles.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/Styles.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/package-info.java b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/package-info.java
index 6ccc5e5..ba6339a 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/resources/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/resources/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Internal: Resources for HTML reports.
  */
-package org.jacoco.report.internal.html.resources;
\ No newline at end of file
+package org.jacoco.report.internal.html.resources;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java
index de5cad2..ecbcd71 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/BarColumn.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -76,8 +76,9 @@
 			final Resources resources, final ReportOutputFolder base)
 			throws IOException {
 		final ICounter counter = total.getCounter(entity);
-		td.text(integerFormat.format(counter.getMissedCount())).text(" of ")
-				.text(integerFormat.format(counter.getTotalCount()));
+		td.text(integerFormat.format(counter.getMissedCount()));
+		td.text(" of ");
+		td.text(integerFormat.format(counter.getTotalCount()));
 	}
 
 	public void item(final HTMLElement td, final ITableItem item,
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java
index 957827d..823c5da 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/CounterColumn.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java
index 76724ea..dab38da 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/IColumnRenderer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -36,7 +36,7 @@
 	 *            the summary of all coverage data items in the table
 	 * @return <code>true</code> if the column should be visible
 	 */
-	public boolean init(List<? extends ITableItem> items, ICoverageNode total);
+	boolean init(List<? extends ITableItem> items, ICoverageNode total);
 
 	/**
 	 * Renders the footer for this column.
@@ -52,8 +52,8 @@
 	 * @throws IOException
 	 *             in case of IO problems with the element output
 	 */
-	public void footer(HTMLElement td, ICoverageNode total,
-			Resources resources, ReportOutputFolder base) throws IOException;
+	void footer(HTMLElement td, ICoverageNode total, Resources resources,
+			ReportOutputFolder base) throws IOException;
 
 	/**
 	 * Renders a single item in this column.
@@ -69,7 +69,7 @@
 	 * @throws IOException
 	 *             in case of IO problems with the element output
 	 */
-	public void item(HTMLElement td, ITableItem item, Resources resources,
+	void item(HTMLElement td, ITableItem item, Resources resources,
 			ReportOutputFolder base) throws IOException;
 
 	/**
@@ -77,6 +77,6 @@
 	 * 
 	 * @return comparator for this column
 	 */
-	public Comparator<ITableItem> getComparator();
+	Comparator<ITableItem> getComparator();
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/ITableItem.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/ITableItem.java
index dbed41f..0c0b2ca 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/ITableItem.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/ITableItem.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,6 @@
 	 * 
 	 * @return node data
 	 */
-	public ICoverageNode getNode();
+	ICoverageNode getNode();
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java
index 9ee258b..27347fe 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/LabelColumn.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java
index f7b003f..fa3f9c1 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/PercentageColumn.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/SortIndex.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/SortIndex.java
index 735628e..e2d0324 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/SortIndex.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/SortIndex.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java
index f68917f..f594dc0 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/Table.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/TableItemComparator.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/TableItemComparator.java
index 97e7af4..4912fb1 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/TableItemComparator.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/TableItemComparator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -30,4 +30,4 @@
 		return comparator.compare(i1.getNode(), i2.getNode());
 	}
 
-}
\ No newline at end of file
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/table/package-info.java b/org.jacoco.report/src/org/jacoco/report/internal/html/table/package-info.java
index c784f36..9208e47 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/table/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/table/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Internal: Sortable HTML table for coverage node elements.
  */
-package org.jacoco.report.internal.html.table;
\ No newline at end of file
+package org.jacoco.report.internal.html.table;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java
new file mode 100644
index 0000000..65782d9
--- /dev/null
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Marc R. Hoffmann - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.jacoco.report.internal.xml;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
+import org.jacoco.core.analysis.ILine;
+import org.jacoco.core.analysis.IMethodCoverage;
+import org.jacoco.core.data.SessionInfo;
+
+/**
+ * A {@link XMLElement} with utility methods to create JaCoCo XML reports.
+ */
+public class ReportElement extends XMLElement {
+
+	private static final String PUBID = "-//JACOCO//DTD Report 1.1//EN";
+
+	private static final String SYSTEM = "report.dtd";
+
+	/**
+	 * Creates a <code>report</code> root element for a XML report.
+	 * 
+	 * @param name
+	 *            value for the name attribute
+	 * @param encoding
+	 *            character encoding used for output
+	 * @param output
+	 *            output stream will be closed if the root element is closed
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public ReportElement(final String name, final OutputStream output,
+			final String encoding) throws IOException {
+		super("report", PUBID, SYSTEM, true, encoding, output);
+		attr("name", name);
+	}
+
+	private ReportElement(final String name, final ReportElement parent)
+			throws IOException {
+		super(name, parent);
+	}
+
+	@Override
+	public ReportElement element(final String name) throws IOException {
+		return new ReportElement(name, this);
+	}
+
+	private ReportElement namedElement(final String elementName,
+			final String name) throws IOException {
+		final ReportElement element = element(elementName);
+		element.attr("name", name);
+		return element;
+	}
+
+	/**
+	 * Creates a 'sessioninfo' element.
+	 * 
+	 * @param info
+	 *            info object to write out
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public void sessioninfo(final SessionInfo info) throws IOException {
+		final ReportElement sessioninfo = element("sessioninfo");
+		sessioninfo.attr("id", info.getId());
+		sessioninfo.attr("start", info.getStartTimeStamp());
+		sessioninfo.attr("dump", info.getDumpTimeStamp());
+	}
+
+	/**
+	 * Creates a 'group' element.
+	 * 
+	 * @param name
+	 *            value for the name attribute
+	 * @return 'group' element
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public ReportElement group(final String name) throws IOException {
+		return namedElement("group", name);
+	}
+
+	/**
+	 * Creates a 'package' element.
+	 * 
+	 * @param name
+	 *            value for the name attribute
+	 * @return 'package' element
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public ReportElement packageElement(final String name) throws IOException {
+		return namedElement("package", name);
+	}
+
+	/**
+	 * Creates a 'class' element.
+	 * 
+	 * @param coverage
+	 *            class coverage node to write out
+	 * @return 'class' element
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public ReportElement classElement(final IClassCoverage coverage)
+			throws IOException {
+		final ReportElement element = namedElement("class", coverage.getName());
+		element.attr("sourcefilename", coverage.getSourceFileName());
+		return element;
+	}
+
+	/**
+	 * Creates a 'method' element.
+	 * 
+	 * @param coverage
+	 *            method coverage node to write out
+	 * @return 'method' element
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public ReportElement method(final IMethodCoverage coverage)
+			throws IOException {
+		final ReportElement element = namedElement("method",
+				coverage.getName());
+		element.attr("desc", coverage.getDesc());
+		final int line = coverage.getFirstLine();
+		if (line != -1) {
+			element.attr("line", line);
+		}
+		return element;
+	}
+
+	/**
+	 * Creates a 'sourcefile' element.
+	 * 
+	 * @param name
+	 *            value for the name attribute
+	 * @return 'sourcefile' element
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public ReportElement sourcefile(final String name) throws IOException {
+		return namedElement("sourcefile", name);
+	}
+
+	/**
+	 * Creates a 'line' element.
+	 * 
+	 * @param nr
+	 *            line number
+	 * @param line
+	 *            line object to write out
+	 * 
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public void line(final int nr, final ILine line) throws IOException {
+		final ReportElement element = element("line");
+		element.attr("nr", nr);
+		counterAttributes(element, "mi", "ci", line.getInstructionCounter());
+		counterAttributes(element, "mb", "cb", line.getBranchCounter());
+	}
+
+	/**
+	 * Creates a 'counter' element.
+	 * 
+	 * @param counterEntity
+	 *            entity of this counter
+	 * 
+	 * @param counter
+	 *            counter object to write out
+	 * 
+	 * @throws IOException
+	 *             in case of problems with the underlying output
+	 */
+	public void counter(final CounterEntity counterEntity,
+			final ICounter counter) throws IOException {
+		final ReportElement counterNode = element("counter");
+		counterNode.attr("type", counterEntity.name());
+		counterAttributes(counterNode, "missed", "covered", counter);
+	}
+
+	private static void counterAttributes(final XMLElement element,
+			final String missedattr, final String coveredattr,
+			final ICounter counter) throws IOException {
+		element.attr(missedattr, counter.getMissedCount());
+		element.attr(coveredattr, counter.getCoveredCount());
+	}
+
+}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLCoverageWriter.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLCoverageWriter.java
index be326ec..7bf95af 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLCoverageWriter.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLCoverageWriter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -30,27 +30,6 @@
 public final class XMLCoverageWriter {
 
 	/**
-	 * Creates a child element with a name attribute.
-	 * 
-	 * @param parent
-	 *            parent element
-	 * @param tagname
-	 *            name of the child tag
-	 * @param name
-	 *            value of the name attribute
-	 * @return child element
-	 * @throws IOException
-	 *             if XML can't be written to the underlying output
-	 * 
-	 */
-	public static XMLElement createChild(final XMLElement parent,
-			final String tagname, final String name) throws IOException {
-		final XMLElement child = parent.element(tagname);
-		child.attr("name", name);
-		return child;
-	}
-
-	/**
 	 * Writes the structure of a given bundle.
 	 * 
 	 * @param bundle
@@ -61,7 +40,7 @@
 	 *             if XML can't be written to the underlying output
 	 */
 	public static void writeBundle(final IBundleCoverage bundle,
-			final XMLElement element) throws IOException {
+			final ReportElement element) throws IOException {
 		for (final IPackageCoverage p : bundle.getPackages()) {
 			writePackage(p, element);
 		}
@@ -69,8 +48,8 @@
 	}
 
 	private static void writePackage(final IPackageCoverage p,
-			final XMLElement parent) throws IOException {
-		final XMLElement element = createChild(parent, "package", p.getName());
+			final ReportElement parent) throws IOException {
+		final ReportElement element = parent.packageElement(p.getName());
 		for (final IClassCoverage c : p.getClasses()) {
 			writeClass(c, element);
 		}
@@ -81,8 +60,8 @@
 	}
 
 	private static void writeClass(final IClassCoverage c,
-			final XMLElement parent) throws IOException {
-		final XMLElement element = createChild(parent, "class", c.getName());
+			final ReportElement parent) throws IOException {
+		final ReportElement element = parent.classElement(c);
 		for (final IMethodCoverage m : c.getMethods()) {
 			writeMethod(m, element);
 		}
@@ -90,20 +69,14 @@
 	}
 
 	private static void writeMethod(final IMethodCoverage m,
-			final XMLElement parent) throws IOException {
-		final XMLElement element = createChild(parent, "method", m.getName());
-		element.attr("desc", m.getDesc());
-		final int line = m.getFirstLine();
-		if (line != -1) {
-			element.attr("line", line);
-		}
+			final ReportElement parent) throws IOException {
+		final ReportElement element = parent.method(m);
 		writeCounters(m, element);
 	}
 
 	private static void writeSourceFile(final ISourceFileCoverage s,
-			final XMLElement parent) throws IOException {
-		final XMLElement element = createChild(parent, "sourcefile",
-				s.getName());
+			final ReportElement parent) throws IOException {
+		final ReportElement element = parent.sourcefile(s.getName());
 		writeLines(s, element);
 		writeCounters(s, element);
 	}
@@ -119,39 +92,26 @@
 	 *             if XML can't be written to the underlying output
 	 */
 	public static void writeCounters(final ICoverageNode node,
-			final XMLElement parent) throws IOException {
+			final ReportElement parent) throws IOException {
 		for (final CounterEntity counterEntity : CounterEntity.values()) {
 			final ICounter counter = node.getCounter(counterEntity);
 			if (counter.getTotalCount() > 0) {
-				final XMLElement counterNode = parent.element("counter");
-				counterNode.attr("type", counterEntity.name());
-				writeCounter(counterNode, "missed", "covered", counter);
-				counterNode.close();
+				parent.counter(counterEntity, counter);
 			}
 		}
 	}
 
 	private static void writeLines(final ISourceNode source,
-			final XMLElement parent) throws IOException {
+			final ReportElement parent) throws IOException {
 		final int last = source.getLastLine();
 		for (int nr = source.getFirstLine(); nr <= last; nr++) {
 			final ILine line = source.getLine(nr);
 			if (line.getStatus() != ICounter.EMPTY) {
-				final XMLElement element = parent.element("line");
-				element.attr("nr", nr);
-				writeCounter(element, "mi", "ci", line.getInstructionCounter());
-				writeCounter(element, "mb", "cb", line.getBranchCounter());
+				parent.line(nr, line);
 			}
 		}
 	}
 
-	private static void writeCounter(final XMLElement element,
-			final String missedattr, final String coveredattr,
-			final ICounter counter) throws IOException {
-		element.attr(missedattr, counter.getMissedCount());
-		element.attr(coveredattr, counter.getCoveredCount());
-	}
-
 	private XMLCoverageWriter() {
 	}
 
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLDocument.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLDocument.java
deleted file mode 100644
index 99cae7e..0000000
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLDocument.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Marc R. Hoffmann - initial API and implementation
- *    
- *******************************************************************************/
-package org.jacoco.report.internal.xml;
-
-import static java.lang.String.format;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-
-/**
- * Root element of an XML document. Each instance represents a separate output
- * document.
- * 
- * @see XMLElement
- */
-public class XMLDocument extends XMLElement {
-
-	/** XML header template */
-	private static final String HEADER = "<?xml version=\"1.0\" encoding=\"%s\"?>";
-
-	/** XML header template for standalone documents */
-	private static final String HEADER_STANDALONE = "<?xml version=\"1.0\" encoding=\"%s\" standalone=\"yes\"?>";
-
-	/** DOCTYPE declaration template */
-	private static final String DOCTYPE = "<!DOCTYPE %s PUBLIC \"%s\" \"%s\">";
-
-	/**
-	 * Writes a new document to the given writer. The document might contain a
-	 * document type declaration.
-	 * 
-	 * @param rootnode
-	 *            name of the root node
-	 * @param pubId
-	 *            optional doctype identifier or <code>null</code>
-	 * @param system
-	 *            system reference, required if doctype is given
-	 * @param encoding
-	 *            encoding that will be specified in the header
-	 * @param standalone
-	 *            <code>true</code> if this is a standalone document
-	 * @param writer
-	 *            writer for content output
-	 * @throws IOException
-	 *             in case of problems with the writer
-	 */
-	public XMLDocument(final String rootnode, final String pubId,
-			final String system, final String encoding,
-			final boolean standalone, final Writer writer) throws IOException {
-		super(writer, rootnode);
-		writeHeader(rootnode, pubId, system, encoding, standalone, writer);
-		beginOpenTag();
-	}
-
-	/**
-	 * Writes a new document to the given binary stream. The document might
-	 * contain a document type declaration.
-	 * 
-	 * @param rootnode
-	 *            name of the root node
-	 * @param pubId
-	 *            optional doctype identifier or <code>null</code>
-	 * @param system
-	 *            system reference, required if doctype is given
-	 * @param encoding
-	 *            encoding of the XML document
-	 * @param standalone
-	 *            <code>true</code> if this is a standalone document
-	 * @param output
-	 *            output for content output
-	 * @throws IOException
-	 *             in case of problems with the writer
-	 */
-	public XMLDocument(final String rootnode, final String pubId,
-			final String system, final String encoding,
-			final boolean standalone, final OutputStream output)
-			throws IOException {
-		this(rootnode, pubId, system, encoding, standalone,
-				new OutputStreamWriter(output, encoding));
-	}
-
-	@Override
-	public void close() throws IOException {
-		super.close();
-		writer.close();
-	}
-
-	private static void writeHeader(final String rootnode, final String pubId,
-			final String system, final String encoding,
-			final boolean standalone, final Writer writer) throws IOException {
-		if (standalone) {
-			writer.write(format(HEADER_STANDALONE, encoding));
-		} else {
-			writer.write(format(HEADER, encoding));
-		}
-		if (pubId != null) {
-			writer.write(format(DOCTYPE, rootnode, pubId, system));
-		}
-	}
-
-}
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
index 3b60a04..c2da6bb 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLElement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,29 +14,26 @@
 import static java.lang.String.format;
 
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.Writer;
 
 /**
- * Simple API to create well formed XML streams. A {@link XMLElement} instance
- * represents a single element in a XML document.
- * 
- * @see XMLDocument
+ * Simple API to create well formed XML streams with minimal memory overhead. A
+ * {@link XMLElement} instance represents a single element in a XML document.
+ * {@link XMLElement} can be used directly or might be subclassed for schema
+ * specific convenience methods.
  */
 public class XMLElement {
 
-	private static final char SPACE = ' ';
+	/** XML header template */
+	private static final String HEADER = "<?xml version=\"1.0\" encoding=\"%s\"?>";
 
-	private static final char EQ = '=';
+	/** XML header template for standalone documents */
+	private static final String HEADER_STANDALONE = "<?xml version=\"1.0\" encoding=\"%s\" standalone=\"yes\"?>";
 
-	private static final char LT = '<';
-
-	private static final char GT = '>';
-
-	private static final char QUOT = '"';
-
-	private static final char AMP = '&';
-
-	private static final char SLASH = '/';
+	/** DOCTYPE declaration template */
+	private static final String DOCTYPE = "<!DOCTYPE %s PUBLIC \"%s\" \"%s\">";
 
 	/** Writer for content output */
 	protected final Writer writer;
@@ -49,51 +46,74 @@
 
 	private XMLElement lastchild;
 
-	/**
-	 * Creates a new element for a XML document.
-	 * 
-	 * @param writer
-	 *            all output will be written directly to this
-	 * @param name
-	 *            element name
-	 */
-	protected XMLElement(final Writer writer, final String name) {
+	private final boolean root;
+
+	private XMLElement(final Writer writer, final String name,
+			final boolean root) throws IOException {
 		this.writer = writer;
 		this.name = name;
 		this.openTagDone = false;
 		this.closed = false;
 		this.lastchild = null;
+		this.root = root;
 	}
 
 	/**
-	 * Emits the beginning of the open tag. This method has to be called before
-	 * other other methods are called on this element.
+	 * Creates a root element of a XML document.
 	 * 
+	 * @param name
+	 *            element name
+	 * @param pubId
+	 *            optional schema public identifier
+	 * @param system
+	 *            optional schema system identifier
+	 * @param standalone
+	 *            if <code>true</code> the document is declared as standalone
+	 * @param encoding
+	 *            character encoding used for output
+	 * @param output
+	 *            output stream will be closed if the root element is closed
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
-	protected void beginOpenTag() throws IOException {
-		writer.write(LT);
+	public XMLElement(final String name, final String pubId,
+			final String system, final boolean standalone,
+			final String encoding, final OutputStream output)
+			throws IOException {
+		this(new OutputStreamWriter(output, encoding), name, true);
+		if (standalone) {
+			writer.write(format(HEADER_STANDALONE, encoding));
+		} else {
+			writer.write(format(HEADER, encoding));
+		}
+		if (pubId != null) {
+			writer.write(format(DOCTYPE, name, pubId, system));
+		}
+		writer.write('<');
 		writer.write(name);
 	}
 
-	private void finishOpenTag() throws IOException {
-		if (!openTagDone) {
-			writer.append(GT);
-			openTagDone = true;
-		}
+	/**
+	 * Creates a new child element within a XML document. May only be called
+	 * before the parent element has been closed.
+	 * 
+	 * @param name
+	 *            element name
+	 * @param parent
+	 *            parent of this element
+	 * @throws IOException
+	 *             in case of problems with the underlying output or if the
+	 *             parent element is already closed
+	 */
+	protected XMLElement(final String name, final XMLElement parent)
+			throws IOException {
+		this(parent.writer, name, false);
+		parent.addChildElement(this);
+		writer.write('<');
+		writer.write(name);
 	}
 
-	/**
-	 * Adds the given child to this element. This will close all previous child
-	 * elements.
-	 * 
-	 * @param child
-	 *            child element to add
-	 * @throws IOException
-	 *             in case of invalid nesting or problems with the writer
-	 */
-	protected void addChildElement(final XMLElement child) throws IOException {
+	private void addChildElement(final XMLElement child) throws IOException {
 		if (closed) {
 			throw new IOException(format("Element %s already closed.", name));
 		}
@@ -101,25 +121,31 @@
 		if (lastchild != null) {
 			lastchild.close();
 		}
-		child.beginOpenTag();
 		lastchild = child;
 	}
 
+	private void finishOpenTag() throws IOException {
+		if (!openTagDone) {
+			writer.append('>');
+			openTagDone = true;
+		}
+	}
+
 	private void quote(final String text) throws IOException {
 		final int len = text.length();
 		for (int i = 0; i < len; i++) {
 			final char c = text.charAt(i);
 			switch (c) {
-			case LT:
+			case '<':
 				writer.write("&lt;");
 				break;
-			case GT:
+			case '>':
 				writer.write("&gt;");
 				break;
-			case QUOT:
+			case '"':
 				writer.write("&quot;");
 				break;
-			case AMP:
+			case '&':
 				writer.write("&amp;");
 				break;
 			default:
@@ -139,27 +165,25 @@
 	 *            attribute name
 	 * @param value
 	 *            attribute value or <code>null</code>
-	 * 
-	 * @return this element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output or if the
+	 *             element is already closed.
 	 */
-	public XMLElement attr(final String name, final String value)
+	public final void attr(final String name, final String value)
 			throws IOException {
 		if (value == null) {
-			return this;
+			return;
 		}
 		if (closed || openTagDone) {
-			throw new IOException(format("Element %s already closed.",
-					this.name));
+			throw new IOException(
+					format("Element %s already closed.", this.name));
 		}
-		writer.write(SPACE);
+		writer.write(' ');
 		writer.write(name);
-		writer.write(EQ);
-		writer.write(QUOT);
+		writer.write('=');
+		writer.write('"');
 		quote(value);
-		writer.write(QUOT);
-		return this;
+		writer.write('"');
 	}
 
 	/**
@@ -171,14 +195,13 @@
 	 *            attribute name
 	 * @param value
 	 *            attribute value
-	 * 
-	 * @return this element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output or if the
+	 *             element is already closed.
 	 */
-	public XMLElement attr(final String name, final int value)
+	public final void attr(final String name, final int value)
 			throws IOException {
-		return attr(name, String.valueOf(value));
+		attr(name, String.valueOf(value));
 	}
 
 	/**
@@ -190,26 +213,26 @@
 	 *            attribute name
 	 * @param value
 	 *            attribute value
-	 * 
-	 * @return this element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output or if the
+	 *             element is already closed.
 	 */
-	public XMLElement attr(final String name, final long value)
+	public final void attr(final String name, final long value)
 			throws IOException {
-		return attr(name, String.valueOf(value));
+		attr(name, String.valueOf(value));
 	}
 
 	/**
-	 * Adds the given text as a child to this node. The text will be quoted.
+	 * Adds the given text as a child to this node. The text will be quoted. May
+	 * only be called before this element has been closed.
 	 * 
 	 * @param text
 	 *            text to add
-	 * @return this element
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output or if the
+	 *             element is already closed.
 	 */
-	public XMLElement text(final String text) throws IOException {
+	public final void text(final String text) throws IOException {
 		if (closed) {
 			throw new IOException(format("Element %s already closed.", name));
 		}
@@ -218,45 +241,46 @@
 			lastchild.close();
 		}
 		quote(text);
-		return this;
 	}
 
 	/**
-	 * Creates a new child element for this element,
+	 * Creates a new child element for this element. Might be overridden in
+	 * subclasses to return a instance of the subclass.
 	 * 
 	 * @param name
 	 *            name of the child element
 	 * @return child element instance
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
 	public XMLElement element(final String name) throws IOException {
-		final XMLElement element = new XMLElement(writer, name);
-		addChildElement(element);
-		return element;
+		return new XMLElement(name, this);
 	}
 
 	/**
 	 * Closes this element if it has not been closed before.
 	 * 
 	 * @throws IOException
-	 *             in case of problems with the writer
+	 *             in case of problems with the underlying output
 	 */
-	public void close() throws IOException {
+	public final void close() throws IOException {
 		if (!closed) {
 			if (lastchild != null) {
 				lastchild.close();
 			}
 			if (openTagDone) {
-				writer.write(LT);
-				writer.write(SLASH);
+				writer.write('<');
+				writer.write('/');
 				writer.write(name);
 			} else {
-				writer.write(SLASH);
+				writer.write('/');
 			}
-			writer.write(GT);
+			writer.write('>');
 			closed = true;
 			openTagDone = true;
+			if (root) {
+				writer.close();
+			}
 		}
 	}
 
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLGroupVisitor.java b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLGroupVisitor.java
index e6795b7..7f2b7d3 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLGroupVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/xml/XMLGroupVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -25,7 +25,7 @@
 public class XMLGroupVisitor extends AbstractGroupVisitor {
 
 	/** XML element of this group */
-	protected final XMLElement element;
+	protected final ReportElement element;
 
 	/**
 	 * New handler for a group with the given name.
@@ -38,7 +38,7 @@
 	 * @throws IOException
 	 *             in case of problems with the underlying writer
 	 */
-	public XMLGroupVisitor(final XMLElement element, final String name)
+	public XMLGroupVisitor(final ReportElement element, final String name)
 			throws IOException {
 		super(name);
 		this.element = element;
@@ -47,14 +47,14 @@
 	@Override
 	protected void handleBundle(final IBundleCoverage bundle,
 			final ISourceFileLocator locator) throws IOException {
-		final XMLElement child = createChild(bundle.getName());
+		final ReportElement child = element.group(bundle.getName());
 		XMLCoverageWriter.writeBundle(bundle, child);
 	}
 
 	@Override
 	protected AbstractGroupVisitor handleGroup(final String name)
 			throws IOException {
-		final XMLElement child = createChild(name);
+		final ReportElement child = element.group(name);
 		return new XMLGroupVisitor(child, name);
 	}
 
@@ -63,8 +63,4 @@
 		XMLCoverageWriter.writeCounters(total, element);
 	}
 
-	private XMLElement createChild(final String name) throws IOException {
-		return XMLCoverageWriter.createChild(element, "group", name);
-	}
-
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/package-info.java b/org.jacoco.report/src/org/jacoco/report/package-info.java
index b80a41d..64ed4dd 100644
--- a/org.jacoco.report/src/org/jacoco/report/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * Common interfaces and utilities for report generation.
  */
-package org.jacoco.report;
\ No newline at end of file
+package org.jacoco.report;
diff --git a/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java b/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
index baeba88..a1fee86 100644
--- a/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -19,12 +19,11 @@
 import org.jacoco.core.analysis.IBundleCoverage;
 import org.jacoco.core.data.ExecutionData;
 import org.jacoco.core.data.SessionInfo;
+import org.jacoco.report.IReportGroupVisitor;
 import org.jacoco.report.IReportVisitor;
 import org.jacoco.report.ISourceFileLocator;
-import org.jacoco.report.internal.AbstractGroupVisitor;
+import org.jacoco.report.internal.xml.ReportElement;
 import org.jacoco.report.internal.xml.XMLCoverageWriter;
-import org.jacoco.report.internal.xml.XMLDocument;
-import org.jacoco.report.internal.xml.XMLElement;
 import org.jacoco.report.internal.xml.XMLGroupVisitor;
 
 /**
@@ -32,10 +31,6 @@
  */
 public class XMLFormatter {
 
-	private static final String PUBID = "-//JACOCO//DTD Report 1.0//EN";
-
-	private static final String SYSTEM = "report.dtd";
-
 	private String outputEncoding = "UTF-8";
 
 	/**
@@ -59,15 +54,11 @@
 	 */
 	public IReportVisitor createVisitor(final OutputStream output)
 			throws IOException {
-		final XMLElement root = new XMLDocument("report", PUBID, SYSTEM,
-				outputEncoding, true, output);
-		class RootVisitor extends XMLGroupVisitor implements IReportVisitor {
+		class RootVisitor implements IReportVisitor {
 
-			RootVisitor(final XMLElement element) throws IOException {
-				super(element, null);
-			}
-
+			private ReportElement report;
 			private List<SessionInfo> sessionInfos;
+			private XMLGroupVisitor groupVisitor;
 
 			public void visitInfo(final List<SessionInfo> sessionInfos,
 					final Collection<ExecutionData> executionData)
@@ -75,36 +66,35 @@
 				this.sessionInfos = sessionInfos;
 			}
 
-			@Override
-			protected void handleBundle(final IBundleCoverage bundle,
+			public void visitBundle(final IBundleCoverage bundle,
 					final ISourceFileLocator locator) throws IOException {
-				writeHeader(bundle.getName());
-				XMLCoverageWriter.writeBundle(bundle, element);
+				createRootElement(bundle.getName());
+				XMLCoverageWriter.writeBundle(bundle, report);
 			}
 
-			@Override
-			protected AbstractGroupVisitor handleGroup(final String name)
+			public IReportGroupVisitor visitGroup(final String name)
 					throws IOException {
-				writeHeader(name);
-				return new XMLGroupVisitor(element, name);
+				createRootElement(name);
+				groupVisitor = new XMLGroupVisitor(report, name);
+				return groupVisitor;
 			}
 
-			private void writeHeader(final String name) throws IOException {
-				element.attr("name", name);
+			private void createRootElement(final String name)
+					throws IOException {
+				report = new ReportElement(name, output, outputEncoding);
 				for (final SessionInfo i : sessionInfos) {
-					final XMLElement sessioninfo = root.element("sessioninfo");
-					sessioninfo.attr("id", i.getId());
-					sessioninfo.attr("start", i.getStartTimeStamp());
-					sessioninfo.attr("dump", i.getDumpTimeStamp());
+					report.sessioninfo(i);
 				}
 			}
 
-			@Override
-			protected void handleEnd() throws IOException {
-				element.close();
+			public void visitEnd() throws IOException {
+				if (groupVisitor != null) {
+					groupVisitor.visitEnd();
+				}
+				report.close();
 			}
 		}
-		return new RootVisitor(root);
+		return new RootVisitor();
 	}
 
 }
diff --git a/org.jacoco.report/src/org/jacoco/report/xml/package-info.java b/org.jacoco.report/src/org/jacoco/report/xml/package-info.java
index 92905ed..9d9236a 100644
--- a/org.jacoco.report/src/org/jacoco/report/xml/package-info.java
+++ b/org.jacoco.report/src/org/jacoco/report/xml/package-info.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,4 +13,4 @@
 /**
  * XML report implementation.
  */
-package org.jacoco.report.xml;
\ No newline at end of file
+package org.jacoco.report.xml;
diff --git a/org.jacoco.report/src/org/jacoco/report/xml/report.dtd b/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
index 6ceab8b..0e84bdf 100644
--- a/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
+++ b/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
@@ -1,5 +1,5 @@
 <!-- 
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -13,7 +13,7 @@
 <!-- This DTD describes the JaCoCo XML report format. It is identified by the
      following identifiers:
 
-        PUBID  = "-//JACOCO//DTD Report 1.0//EN"
+        PUBID  = "-//JACOCO//DTD Report 1.1//EN"
         SYSTEM = "report.dtd"
 -->
 
@@ -44,6 +44,8 @@
 <!ELEMENT class (method*, counter*)>
   <!-- fully qualified VM name -->
   <!ATTLIST class name CDATA #REQUIRED>
+  <!-- name of the corresponding source file -->
+  <!ATTLIST class sourcefilename CDATA #IMPLIED>
 
 <!-- representation of a method -->
 <!ELEMENT method (counter*)>
@@ -79,4 +81,4 @@
   <!-- number of missed items -->
   <!ATTLIST counter missed CDATA #REQUIRED>
   <!-- number of covered items -->
-  <!ATTLIST counter covered CDATA #REQUIRED>
\ No newline at end of file
+  <!ATTLIST counter covered CDATA #REQUIRED>
diff --git a/org.jacoco.tests/pom.xml b/org.jacoco.tests/pom.xml
index ae07b4b..3efa06c 100644
--- a/org.jacoco.tests/pom.xml
+++ b/org.jacoco.tests/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+   Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
    All rights reserved. This program and the accompanying materials
    are made available under the terms of the Eclipse Public License v1.0
    which accompanies this distribution, and is available at
@@ -16,7 +16,7 @@
   <parent>
     <groupId>org.jacoco</groupId>
     <artifactId>org.jacoco.build</artifactId>
-    <version>0.8.0</version>
+    <version>0.8.4</version>
     <relativePath>../org.jacoco.build</relativePath>
   </parent>
 
@@ -27,6 +27,7 @@
 
   <modules>
     <module>../org.jacoco.core.test</module>
+    <module>../org.jacoco.core.test.validation</module>
     <module>../org.jacoco.report.test</module>
     <module>../org.jacoco.agent.rt.test</module>
     <module>../org.jacoco.agent.test</module>
diff --git a/pom.xml b/pom.xml
index 129c95a..08fc669 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
 
   <groupId>org.jacoco</groupId>
   <artifactId>root</artifactId>
-  <version>0.8.0</version>
+  <version>0.8.4</version>
   <packaging>pom</packaging>
 
   <modules>