diff options
Diffstat (limited to 'org.jacoco.core/src/org')
5 files changed, 133 insertions, 6 deletions
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 ac86128f..7ab9003a 100644 --- a/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java +++ b/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java @@ -23,6 +23,7 @@ import java.util.zip.ZipInputStream; import org.jacoco.core.data.ExecutionData; import org.jacoco.core.data.ExecutionDataStore; import org.jacoco.core.internal.ContentTypeDetector; +import org.jacoco.core.internal.Java9Support; import org.jacoco.core.internal.Pack200Streams; import org.jacoco.core.internal.analysis.ClassAnalyzer; import org.jacoco.core.internal.analysis.ClassCoverageImpl; @@ -123,7 +124,8 @@ public class Analyzer { public void analyzeClass(final byte[] buffer, final String location) throws IOException { try { - analyzeClass(new ClassReader(buffer)); + analyzeClass( + new ClassReader(Java9Support.downgradeIfRequired(buffer))); } catch (final RuntimeException cause) { throw analyzerError(location, cause); } @@ -142,7 +144,7 @@ public class Analyzer { public void analyzeClass(final InputStream input, final String location) throws IOException { try { - analyzeClass(new ClassReader(input)); + analyzeClass(Java9Support.readFully(input), location); } catch (final RuntimeException e) { throw analyzerError(location, e); } 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 0d4eea6c..5a0ce7ab 100644 --- a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java +++ b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java @@ -22,6 +22,7 @@ import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import org.jacoco.core.internal.ContentTypeDetector; +import org.jacoco.core.internal.Java9Support; import org.jacoco.core.internal.Pack200Streams; import org.jacoco.core.internal.flow.ClassProbesAdapter; import org.jacoco.core.internal.instr.ClassInstrumenter; @@ -98,7 +99,14 @@ public class Instrumenter { public byte[] instrument(final byte[] buffer, final String name) throws IOException { try { - return instrument(new ClassReader(buffer)); + if (Java9Support.isPatchRequired(buffer)) { + final byte[] result = instrument( + new ClassReader(Java9Support.downgrade(buffer))); + Java9Support.upgrade(result); + return result; + } else { + return instrument(new ClassReader(buffer)); + } } catch (final RuntimeException e) { throw instrumentError(name, e); } @@ -119,7 +127,7 @@ public class Instrumenter { public byte[] instrument(final InputStream input, final String name) throws IOException { try { - return instrument(new ClassReader(input)); + return instrument(Java9Support.readFully(input), name); } catch (final RuntimeException e) { throw instrumentError(name, e); } @@ -141,7 +149,7 @@ public class Instrumenter { public void instrument(final InputStream input, final OutputStream output, final String name) throws IOException { try { - output.write(instrument(new ClassReader(input))); + output.write(instrument(Java9Support.readFully(input), name)); } catch (final RuntimeException e) { throw instrumentError(name, e); } 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 5bd22a47..7f734c10 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java @@ -82,6 +82,7 @@ public class ContentTypeDetector { case Opcodes.V1_6: case Opcodes.V1_7: case Opcodes.V1_8: + case Java9Support.V1_9: return CLASSFILE; } } diff --git a/org.jacoco.core/src/org/jacoco/core/internal/Java9Support.java b/org.jacoco.core/src/org/jacoco/core/internal/Java9Support.java new file mode 100644 index 00000000..fae1e0e4 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/Java9Support.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2009, 2016 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and 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; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.objectweb.asm.Opcodes; + +/** + * Patching for Java 9 classes, so that ASM can read them. + */ +public final class Java9Support { + + /** + * Version of the Java 9 class file format. + */ + public static final int V1_9 = Opcodes.V1_8 + 1; + + private Java9Support() { + } + + /** + * Reads all bytes from an input stream into a byte array. + * + * @param is + * the input stream to read from + * @return a byte array containing all the bytes from the stream + * @throws IOException + * if an I/O error occurs + */ + public static byte[] readFully(final InputStream is) + throws IOException { + if (is == null) { + throw new IllegalArgumentException(); + } + final byte[] buf = new byte[1024]; + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + while (true) { + int r = is.read(buf); + if (r == -1) { + break; + } + out.write(buf, 0, r); + } + return out.toByteArray(); + } + + private static void putShort(byte[] b, int index, int s) { + b[index] = (byte) (s >>> 8); + b[index + 1] = (byte) s; + } + + private static short readShort(byte[] b, int index) { + return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); + } + + /** + * Determines whether class definition contains {@link #V1_9} version. + * + * @param buffer + * definition of the class + * @return <code>true</code> if class definition contains Java 9 version + */ + public static boolean isPatchRequired(byte[] buffer) { + return readShort(buffer, 6) == V1_9; + } + + /** + * Returns new definition of class with version {@link Opcodes#V1_8}, + * if it has version {@link #V1_9}. + * + * @param buffer + * definition of the class + * @return new definition of the class + */ + public static byte[] downgradeIfRequired(byte[] buffer) { + return isPatchRequired(buffer) ? downgrade(buffer) : buffer; + } + + /** + * Replaces version in the definition of class on {@link Opcodes#V1_8}. + * + * @param b + * definition of the class + * @return new definition of the class + */ + public static byte[] downgrade(byte[] b) { + byte[] result = new byte[b.length]; + System.arraycopy(b, 0, result, 0, b.length); + putShort(result, 6, Opcodes.V1_8); + return result; + } + + /** + * Replaces version in the definition of class on {@link #V1_9}. + * + * @param b + * definition of the class + */ + public static void upgrade(byte[] b) { + putShort(b, 6, V1_9); + } + +} 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 19c6ef91..24e975ee 100644 --- a/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java +++ b/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java @@ -20,6 +20,7 @@ import java.lang.reflect.Field; import java.security.ProtectionDomain; import org.jacoco.core.JaCoCo; +import org.jacoco.core.internal.Java9Support; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; @@ -154,7 +155,7 @@ public class ModifiedSystemClassRuntime extends AbstractRuntime { */ public static byte[] instrument(final byte[] source, final String accessFieldName) { - final ClassReader reader = new ClassReader(source); + final ClassReader reader = new ClassReader(Java9Support.downgradeIfRequired(source)); final ClassWriter writer = new ClassWriter(reader, 0); reader.accept(new ClassVisitor(JaCoCo.ASM_API_VERSION, writer) { |