Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental support for Java 19 class files #1264

Merged
merged 4 commits into from Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .azure-pipelines/azure-pipelines.yml
Expand Up @@ -33,6 +33,8 @@ jobs:
JDK_VERSION: 17
JDK 18:
JDK_VERSION: 18
JDK 19:
JDK_VERSION: 19
pool:
vmImage: 'ubuntu-18.04'
steps:
Expand Down
14 changes: 14 additions & 0 deletions org.jacoco.build/pom.xml
Expand Up @@ -894,6 +894,20 @@
</properties>
</profile>

<profile>
<id>java19-bytecode</id>
<activation>
<property>
<name>bytecode.version</name>
<value>19</value>
</property>
</activation>
<properties>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</properties>
</profile>

<!-- This profile enables use of ECJ -->
<profile>
<id>ecj</id>
Expand Down
30 changes: 30 additions & 0 deletions org.jacoco.core.test.validation/pom.xml
Expand Up @@ -369,6 +369,36 @@
<module>../org.jacoco.core.test.validation.scala</module>
</modules>
</profile>

<profile>
<id>java19-bytecode</id>
<activation>
<property>
<name>bytecode.version</name>
<value>19</value>
</property>
</activation>
<properties>
<!-- Kotlin 1.5.0 doesn't support compilation into 19 -->
<kotlin.compiler.jvmTarget>16</kotlin.compiler.jvmTarget>
<!-- Groovy 3.0.8 does not support compilation into 19 -->
<groovy.targetBytecode>16</groovy.targetBytecode>
<!-- see respective profile in org.jacoco.build about this override -->
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
</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.java14</module>
<module>../org.jacoco.core.test.validation.java16</module>
<!-- Groovy 3.0.8 does not support Java 19
<module>../org.jacoco.core.test.validation.groovy</module>
-->
<module>../org.jacoco.core.test.validation.scala</module>
</modules>
</profile>
</profiles>

</project>
Expand Up @@ -108,7 +108,7 @@ public void should_ignore_synthetic_classes() throws Exception {
@Test
public void should_not_modify_class_bytes_to_support_next_version()
throws Exception {
final byte[] originalBytes = createClass(Opcodes.V17 + 1);
final byte[] originalBytes = createClass(Opcodes.V18 + 1);
final byte[] bytes = new byte[originalBytes.length];
System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length);
final long expectedClassId = CRC64.classId(bytes);
Expand All @@ -131,14 +131,14 @@ private static byte[] createClass(final int version) {
*/
@Test
public void analyzeClass_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V17 + 2);
final byte[] bytes = createClass(Opcodes.V18 + 2);
try {
analyzer.analyzeClass(bytes, "UnsupportedVersion");
fail("exception expected");
} catch (IOException e) {
assertEquals("Error while analyzing UnsupportedVersion.",
e.getMessage());
assertEquals("Unsupported class file major version 63",
assertEquals("Unsupported class file major version 64",
e.getCause().getMessage());
}
}
Expand Down Expand Up @@ -218,15 +218,15 @@ public void testAnalyzeClass_BrokenStream() throws IOException {
*/
@Test
public void analyzeAll_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V17 + 2);
final byte[] bytes = createClass(Opcodes.V18 + 2);
try {
analyzer.analyzeAll(new ByteArrayInputStream(bytes),
"UnsupportedVersion");
fail("exception expected");
} catch (IOException e) {
assertEquals("Error while analyzing UnsupportedVersion.",
e.getMessage());
assertEquals("Unsupported class file major version 63",
assertEquals("Unsupported class file major version 64",
e.getCause().getMessage());
}
}
Expand Down
Expand Up @@ -99,7 +99,7 @@ public void setup() throws Exception {
@Test
public void should_not_modify_class_bytes_to_support_next_version()
throws Exception {
final byte[] originalBytes = createClass(Opcodes.V17 + 1);
final byte[] originalBytes = createClass(Opcodes.V18 + 1);
final byte[] bytes = new byte[originalBytes.length];
System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length);
final long expectedClassId = CRC64.classId(bytes);
Expand All @@ -122,14 +122,14 @@ private static byte[] createClass(final int version) {
*/
@Test
public void instrument_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V17 + 2);
final byte[] bytes = createClass(Opcodes.V18 + 2);
try {
instrumenter.instrument(bytes, "UnsupportedVersion");
fail("exception expected");
} catch (final IOException e) {
assertEquals("Error while instrumenting UnsupportedVersion.",
e.getMessage());
assertEquals("Unsupported class file major version 63",
assertEquals("Unsupported class file major version 64",
e.getCause().getMessage());
}
}
Expand Down Expand Up @@ -224,15 +224,15 @@ public void testSerialization() throws Exception {
*/
@Test
public void instrumentAll_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V17 + 2);
final byte[] bytes = createClass(Opcodes.V18 + 2);
try {
instrumenter.instrumentAll(new ByteArrayInputStream(bytes),
new ByteArrayOutputStream(), "UnsupportedVersion");
fail("exception expected");
} catch (final IOException e) {
assertEquals("Error while instrumenting UnsupportedVersion.",
e.getMessage());
assertEquals("Unsupported class file major version 63",
assertEquals("Unsupported class file major version 64",
e.getCause().getMessage());
}
}
Expand Down
Expand Up @@ -43,8 +43,8 @@ public void setup() {
}

@Test
public void classReaderFor_should_read_java_18_class() {
final byte[] bytes = createJava18Class();
public void classReaderFor_should_read_java_19_class() {
final byte[] bytes = createJava19Class();

final ClassReader classReader = InstrSupport.classReaderFor(bytes);

Expand All @@ -53,16 +53,16 @@ public void classReaderFor_should_read_java_18_class() {
public void visit(final int version, final int access,
final String name, final String signature,
final String superName, final String[] interfaces) {
assertEquals(Opcodes.V17 + 1, version);
assertEquals(Opcodes.V18 + 1, version);
}
}, 0);

assertArrayEquals(createJava18Class(), bytes);
assertArrayEquals(createJava19Class(), bytes);
}

private static byte[] createJava18Class() {
private static byte[] createJava19Class() {
final ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V17 + 1, 0, "Foo", null, "java/lang/Object", null);
cw.visit(Opcodes.V18 + 1, 0, "Foo", null, "java/lang/Object", null);
cw.visitEnd();
return cw.toByteArray();
}
Expand Down Expand Up @@ -129,7 +129,8 @@ public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_
assertTrue(InstrSupport.needsFrames(Opcodes.V15));
assertTrue(InstrSupport.needsFrames(Opcodes.V16));
assertTrue(InstrSupport.needsFrames(Opcodes.V17));
assertTrue(InstrSupport.needsFrames(Opcodes.V17 + 1));
assertTrue(InstrSupport.needsFrames(Opcodes.V18));
assertTrue(InstrSupport.needsFrames(Opcodes.V18 + 1));

assertTrue(InstrSupport.needsFrames(0x0100));
}
Expand Down
Expand Up @@ -273,9 +273,9 @@ public static void push(final MethodVisitor mv, final int value) {
*/
public static ClassReader classReaderFor(final byte[] b) {
final int originalVersion = getMajorVersion(b);
if (originalVersion == Opcodes.V17 + 1) {
if (originalVersion == Opcodes.V18 + 1) {
// temporarily downgrade version to bypass check in ASM
setMajorVersion(Opcodes.V17, b);
setMajorVersion(Opcodes.V18, b);
}
final ClassReader classReader = new ClassReader(b);
setMajorVersion(originalVersion, b);
Expand Down
2 changes: 2 additions & 0 deletions org.jacoco.doc/docroot/doc/changes.html
Expand Up @@ -24,6 +24,8 @@ <h3>New Features</h3>
<ul>
<li>Experimental support for Java 18 class files
(GitHub <a href="https://github.com/jacoco/jacoco/issues/1198">#1198</a>).</li>
<li>Experimental support for Java 19 class files
(GitHub <a href="https://github.com/jacoco/jacoco/issues/1264">#1264</a>).</li>
<li>Part of bytecode generated by the Java compilers for <code>assert</code>
statement is filtered out during generation of report
(GitHub <a href="https://github.com/jacoco/jacoco/issues/1196">#1196</a>).</li>
Expand Down