diff options
author | Evgeny Mandrikov <138671+Godin@users.noreply.github.com> | 2019-01-22 23:23:48 +0100 |
---|---|---|
committer | Marc R. Hoffmann <hoffmann@mountainminds.com> | 2019-01-22 23:23:48 +0100 |
commit | 2034d40ee2172339f33229f057d15b2b4e7aae29 (patch) | |
tree | 53df4f9b9b2b38ec208abfe7a59c3c3a1631357d | |
parent | b7441f2b51b3d147554845710c809e5a562dc36f (diff) | |
download | platform_external_jacoco-2034d40ee2172339f33229f057d15b2b4e7aae29.tar.gz platform_external_jacoco-2034d40ee2172339f33229f057d15b2b4e7aae29.tar.bz2 platform_external_jacoco-2034d40ee2172339f33229f057d15b2b4e7aae29.zip |
Add experimental support for Java 13 class files (#835)
17 files changed, 96 insertions, 16 deletions
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 e82b8d58..7f9eb8d7 100644 --- a/org.jacoco.ant.test/src/org/jacoco/ant/RemoveDebugInfos.java +++ b/org.jacoco.ant.test/src/org/jacoco/ant/RemoveDebugInfos.java @@ -16,6 +16,8 @@ import java.io.FileOutputStream; 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 class RemoveDebugInfos { 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.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java b/org.jacoco.cli.test/src/org/jacoco/cli/internal/commands/InstrumentTest.java index 556c09e8..ff49aa8d 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 @@ -26,6 +26,7 @@ import java.util.HashSet; 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; @@ -33,7 +34,6 @@ 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; /** * Unit tests for {@link Instrument}. @@ -135,7 +135,8 @@ public class InstrumentTest extends CommandTestBase { 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(InstrSupport.ASM_API_VERSION) { 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 index 54276cdc..91a81247 100644 --- 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 @@ -21,13 +21,13 @@ 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.ClassReader; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; @@ -195,7 +195,7 @@ public class FinallyTest extends ValidationTestBase { byte[] b = TargetLoader.getClassDataAsBytes(FinallyTarget.class); final ClassNode classNode = new ClassNode(); - new ClassReader(b).accept(classNode, 0); + InstrSupport.classReaderFor(b).accept(classNode, 0); for (final MethodNode m : classNode.methods) { if ("main".equals(m.name)) { // skip it diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FramesTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FramesTest.java index 92ac9074..88e39039 100644 --- a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FramesTest.java +++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/FramesTest.java @@ -86,7 +86,7 @@ public class FramesTest { } 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: diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/StructuredLockingTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/StructuredLockingTest.java index 1379616b..7e13e651 100644 --- a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/StructuredLockingTest.java +++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/java5/StructuredLockingTest.java @@ -20,12 +20,12 @@ import java.util.List; 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.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; @@ -65,7 +65,7 @@ public class StructuredLockingTest { 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); } 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 ffa48988..6f8fee9c 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 @@ -92,7 +92,7 @@ public class AnalyzerTest { @Test public void should_not_modify_class_bytes_to_support_next_version() throws Exception { - final byte[] originalBytes = createClass(Opcodes.V12); + 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); 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 index 769b9eab..f1f8d16c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/instr/ClassFileVersionsTest.java @@ -41,7 +41,6 @@ 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.Label; @@ -113,6 +112,11 @@ public class ClassFileVersionsTest { 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); @@ -124,7 +128,7 @@ public class ClassFileVersionsTest { } private void assertFrames(byte[] source, final boolean expected) { - new ClassReader(source) + InstrSupport.classReaderFor(source) .accept(new ClassVisitor(InstrSupport.ASM_API_VERSION) { @Override 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 406c5e80..d5104bcc 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 @@ -98,7 +98,7 @@ public class InstrumenterTest { @Test public void should_not_modify_class_bytes_to_support_next_version() throws Exception { - final byte[] originalBytes = createClass(Opcodes.V12); + 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); diff --git a/org.jacoco.core.test/src/org/jacoco/core/instr/ResizeInstructionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/instr/ResizeInstructionsTest.java index bb671b13..1a8137cb 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/instr/ResizeInstructionsTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/instr/ResizeInstructionsTest.java @@ -61,7 +61,7 @@ public class ResizeInstructionsTest { public void should_not_loose_InnerClasses_attribute() throws Exception { byte[] source = TargetLoader.getClassDataAsBytes(Inner.class); - final ClassReader cr = new ClassReader(source); + final ClassReader cr = InstrSupport.classReaderFor(source); final ClassWriter cw = new ClassWriter(0); cr.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION, cw) { @Override 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 6a1b08d3..a631b52e 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 @@ -152,6 +152,20 @@ public class ContentTypeDetectorTest { } @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/instr/InstrSupportTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java index eedea379..caec564b 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 @@ -11,6 +11,7 @@ *******************************************************************************/ 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; @@ -19,6 +20,9 @@ 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; @@ -42,6 +46,32 @@ public class InstrSupportTest { } @Test + 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(); + cw.toByteArray(); + return cw.toByteArray(); + } + + @Test public void getVersionMajor_should_return_major_version_number() { final byte[] bytes = new byte[] { (byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE, /* minor */ 0x00, 0x03, /* major */ 0x00, 0x2D }; @@ -66,6 +96,7 @@ public class InstrSupportTest { assertTrue(InstrSupport.needsFrames(Opcodes.V10)); assertTrue(InstrSupport.needsFrames(Opcodes.V11)); assertTrue(InstrSupport.needsFrames(Opcodes.V12)); + assertTrue(InstrSupport.needsFrames(Opcodes.V12 + 1)); } @Test 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 8b927459..97aa44f1 100644 --- a/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java +++ b/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java @@ -30,6 +30,7 @@ import org.jacoco.core.internal.analysis.ClassCoverageImpl; 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; @@ -112,7 +113,7 @@ public class Analyzer { private void analyzeClass(final byte[] source) { final long classId = CRC64.classId(source); - final ClassReader reader = new ClassReader(source); + final ClassReader reader = InstrSupport.classReaderFor(source); if ((reader.getAccess() & Opcodes.ACC_SYNTHETIC) != 0) { return; } 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 201d75ee..89f14019 100644 --- a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java +++ b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java @@ -83,7 +83,7 @@ public class Instrumenter { private byte[] instrument(final byte[] source) { final long classId = CRC64.classId(source); - final ClassReader reader = new ClassReader(source); + final ClassReader reader = InstrSupport.classReaderFor(source); final ClassWriter writer = new ClassWriter(reader, 0) { @Override protected String getCommonSuperClass(final String type1, 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 1d7617ee..74574ecc 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/ContentTypeDetector.java @@ -88,6 +88,8 @@ public class ContentTypeDetector { 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/instr/InstrSupport.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java index ce4bcbee..99e00270 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 @@ -13,6 +13,7 @@ package org.jacoco.core.internal.instr; import static java.lang.String.format; +import org.objectweb.asm.ClassReader; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -227,4 +228,25 @@ public final class InstrSupport { } } + /** + * 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 byte[] originalVersion = new byte[] { b[4], b[5], b[6], b[7] }; + if (getVersionMajor(b) == Opcodes.V12 + 1) { + b[4] = (byte) (Opcodes.V12 >>> 24); + b[5] = (byte) (Opcodes.V12 >>> 16); + b[6] = (byte) (Opcodes.V12 >>> 8); + b[7] = (byte) Opcodes.V12; + } + final ClassReader classReader = new ClassReader(b); + System.arraycopy(originalVersion, 0, b, 4, originalVersion.length); + return classReader; + } + } 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 a18f7299..5f2cc497 100644 --- a/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java +++ b/org.jacoco.core/src/org/jacoco/core/runtime/ModifiedSystemClassRuntime.java @@ -153,7 +153,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 = InstrSupport.classReaderFor(source); final ClassWriter writer = new ClassWriter(reader, 0); reader.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION, writer) { diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index e673eb5f..1cfeb212 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -26,6 +26,8 @@ (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> |