Fix instrumentation of interfaces with default methods (#428)

Without this change instrumented classes can't pass consistency
checks for a constant pool and cause IncompatibleClassChangeError
starting with OpenJDK 9 EA b122
(see https://bugs.openjdk.java.net/browse/JDK-8145148).
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 e244b82..c8da6d6 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
@@ -12,7 +12,9 @@
 package org.jacoco.core.internal.instr;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import org.jacoco.core.runtime.IExecutionDataAccessorGenerator;
 import org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator;
@@ -92,9 +94,13 @@
 
 	@Test
 	public void testClass8() {
-		test(Opcodes.V1_8, 0, false, true);
+		final IProbeArrayStrategy strategy = test(Opcodes.V1_8, 0, false, true);
 		assertDataField(InstrSupport.DATAFIELD_ACC);
 		assertInitMethod(true);
+
+		final ClassVisitorMock cv = new ClassVisitorMock();
+		strategy.storeInstance(cv.visitMethod(0, null, null, null, null), 0);
+		assertFalse(cv.interfaceMethod);
 	}
 
 	@Test
@@ -120,9 +126,14 @@
 
 	@Test
 	public void testInterface8() {
-		test(Opcodes.V1_8, Opcodes.ACC_INTERFACE, false, true);
+		final IProbeArrayStrategy strategy = test(Opcodes.V1_8,
+				Opcodes.ACC_INTERFACE, false, true);
 		assertDataField(InstrSupport.DATAFIELD_INTF_ACC);
 		assertInitMethod(true);
+
+		final ClassVisitorMock cv = new ClassVisitorMock();
+		strategy.storeInstance(cv.visitMethod(0, null, null, null, null), 0);
+		assertTrue(cv.interfaceMethod);
 	}
 
 	@Test
@@ -177,6 +188,7 @@
 		private String methodName;
 
 		private boolean frames;
+		private boolean interfaceMethod;
 
 		ClassVisitorMock() {
 			super(Opcodes.ASM5);
@@ -203,6 +215,12 @@
 						int nStack, Object[] stack) {
 					frames = true;
 				}
+
+				@Override
+				public void visitMethodInsn(int opcode, String owner,
+						String name, String desc, boolean itf) {
+					interfaceMethod = itf;
+				}
 			};
 		}
 	}
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/FieldProbeArrayStrategy.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/FieldProbeArrayStrategy.java
index 9eb5340..26902c2 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/FieldProbeArrayStrategy.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/FieldProbeArrayStrategy.java
@@ -37,15 +37,18 @@
 	private final String className;
 	private final long classId;
 	private final boolean withFrames;
+	private final boolean isInterface;
 	private final int fieldAccess;
 	private final IExecutionDataAccessorGenerator accessorGenerator;
 
 	FieldProbeArrayStrategy(final String className, final long classId,
-			final boolean withFrames, final int fieldAccess,
+			final boolean withFrames, final boolean isInterface,
+			final int fieldAccess,
 			final IExecutionDataAccessorGenerator accessorGenerator) {
 		this.className = className;
 		this.classId = classId;
 		this.withFrames = withFrames;
+		this.isInterface = isInterface;
 		this.fieldAccess = fieldAccess;
 		this.accessorGenerator = accessorGenerator;
 	}
@@ -53,7 +56,7 @@
 	public int storeInstance(final MethodVisitor mv, final int variable) {
 		mv.visitMethodInsn(Opcodes.INVOKESTATIC, className,
 				InstrSupport.INITMETHOD_NAME, InstrSupport.INITMETHOD_DESC,
-				false);
+				isInterface);
 		mv.visitVarInsn(Opcodes.ASTORE, variable);
 		return 1;
 	}
@@ -134,4 +137,4 @@
 		return Math.max(size, 2); // Maximum local stack size is 2
 	}
 
-}
\ 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 9e8d6ca..8ce2f23 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
@@ -51,7 +51,7 @@
 			}
 			if (version >= Opcodes.V1_8 && counter.hasMethods()) {
 				return new FieldProbeArrayStrategy(className, classId,
-						withFrames, InstrSupport.DATAFIELD_INTF_ACC,
+						withFrames, true, InstrSupport.DATAFIELD_INTF_ACC,
 						accessorGenerator);
 			} else {
 				return new LocalProbeArrayStrategy(className, classId,
@@ -59,7 +59,7 @@
 			}
 		} else {
 			return new FieldProbeArrayStrategy(className, classId, withFrames,
-					InstrSupport.DATAFIELD_ACC, accessorGenerator);
+					false, InstrSupport.DATAFIELD_ACC, accessorGenerator);
 		}
 	}
 
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index fdc0d8c..b2e9d4b 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -29,6 +29,10 @@
 
 <h3>Fixed Bugs</h3>
 <ul>
+  <li>Fix instrumentation of interfaces with default methods to not create incorrect
+      constant pool entries, which lead to <code>IncompatibleClassChangeError</code>
+      starting from OpenJDK 9 EA b122
+      (GitHub <a href="https://github.com/jacoco/jacoco/issues/428">#428</a>).</li>
   <li>Add Maven goal <code>report-aggregate</code> to lifecycle-mapping-metadata.xml
       (GitHub <a href="https://github.com/jacoco/jacoco/issues/427">#427</a>).</li>
 </ul>