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 16 class files #1059

Merged
merged 1 commit into from Jun 16, 2020
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
7 changes: 7 additions & 0 deletions .travis.sh
Expand Up @@ -75,6 +75,9 @@ case "$JDK" in
15-ea)
install_jdk $JDK15_EA_URL
;;
16-ea)
install_jdk $JDK16_EA_URL
;;
esac

# Do not use "~/.mavenrc" set by Travis (https://github.com/travis-ci/travis-ci/issues/3893),
Expand Down Expand Up @@ -110,6 +113,10 @@ case "$JDK" in
mvn -V -B -e verify -Dbytecode.version=15 \
--settings=./.travis/settings.xml
;;
16-ea)
mvn -V -B -e verify -Dbytecode.version=16 \
--settings=./.travis/settings.xml
;;
*)
echo "Incorrect JDK [$JDK]"
exit 1;
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -31,5 +31,6 @@ env:
- JDK=13
- JDK=14
- JDK=15-ea
- JDK=16-ea

script: ./.travis.sh
14 changes: 14 additions & 0 deletions org.jacoco.build/pom.xml
Expand Up @@ -841,6 +841,20 @@
</properties>
</profile>

<profile>
<id>java16-bytecode</id>
<activation>
<property>
<name>bytecode.version</name>
<value>16</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
25 changes: 25 additions & 0 deletions org.jacoco.core.test.validation/pom.xml
Expand Up @@ -246,6 +246,31 @@
<module>../org.jacoco.core.test.validation.scala</module>
</modules>
</profile>

<profile>
<id>java16-bytecode</id>
<activation>
<property>
<name>bytecode.version</name>
<value>16</value>
</property>
</activation>
<properties>
<!-- see respective profile in org.jacoco.build about this override -->
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</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>
<!-- Groovy 2.5.8 doesn't support bytecode version 16
<module>../org.jacoco.core.test.validation.groovy</module>
-->
<module>../org.jacoco.core.test.validation.scala</module>
</modules>
</profile>
</profiles>

</project>
Expand Up @@ -107,7 +107,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.V14 + 1);
final byte[] originalBytes = createClass(Opcodes.V15 + 1);
final byte[] bytes = new byte[originalBytes.length];
System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length);
final long expectedClassId = CRC64.classId(bytes);
Expand All @@ -130,14 +130,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.V14 + 2);
final byte[] bytes = createClass(Opcodes.V15 + 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 60",
assertEquals("Unsupported class file major version 61",
e.getCause().getMessage());
}
}
Expand Down Expand Up @@ -217,15 +217,15 @@ public void testAnalyzeClass_BrokenStream() throws IOException {
*/
@Test
public void analyzeAll_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V14 + 2);
final byte[] bytes = createClass(Opcodes.V15 + 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 60",
assertEquals("Unsupported class file major version 61",
e.getCause().getMessage());
}
}
Expand Down
Expand Up @@ -29,6 +29,7 @@
import static org.objectweb.asm.Opcodes.V12;
import static org.objectweb.asm.Opcodes.V13;
import static org.objectweb.asm.Opcodes.V14;
import static org.objectweb.asm.Opcodes.V15;
import static org.objectweb.asm.Opcodes.V1_1;
import static org.objectweb.asm.Opcodes.V1_2;
import static org.objectweb.asm.Opcodes.V1_3;
Expand Down Expand Up @@ -129,7 +130,12 @@ public void test_14() throws IOException {

@Test
public void test_15() throws IOException {
testVersion(V14 + 1, true);
testVersion(V15, true);
}

@Test
public void test_16() throws IOException {
testVersion(V15 + 1, true);
}

private void testVersion(int version, boolean frames) throws IOException {
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.V14 + 1);
final byte[] originalBytes = createClass(Opcodes.V15 + 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.V14 + 2);
final byte[] bytes = createClass(Opcodes.V15 + 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 60",
assertEquals("Unsupported class file major version 61",
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.V14 + 2);
final byte[] bytes = createClass(Opcodes.V15 + 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 60",
assertEquals("Unsupported class file major version 61",
e.getCause().getMessage());
}
}
Expand Down
Expand Up @@ -43,8 +43,8 @@ public void setup() {
}

@Test
public void classReaderFor_should_read_java_15_class() {
final byte[] bytes = createJava15Class();
public void classReaderFor_should_read_java_16_class() {
final byte[] bytes = createJava16Class();

final ClassReader classReader = InstrSupport.classReaderFor(bytes);

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

assertArrayEquals(createJava15Class(), bytes);
assertArrayEquals(createJava16Class(), bytes);
}

private static byte[] createJava15Class() {
private static byte[] createJava16Class() {
final ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V14 + 1, 0, "Foo", null, "java/lang/Object", null);
cw.visit(Opcodes.V15 + 1, 0, "Foo", null, "java/lang/Object", null);
cw.visitEnd();
return cw.toByteArray();
}
Expand Down Expand Up @@ -126,7 +126,8 @@ public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_
assertTrue(InstrSupport.needsFrames(Opcodes.V12));
assertTrue(InstrSupport.needsFrames(Opcodes.V13));
assertTrue(InstrSupport.needsFrames(Opcodes.V14));
assertTrue(InstrSupport.needsFrames(Opcodes.V14 + 1));
assertTrue(InstrSupport.needsFrames(Opcodes.V15));
assertTrue(InstrSupport.needsFrames(Opcodes.V15 + 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.V14 + 1) {
if (originalVersion == Opcodes.V15 + 1) {
// temporarily downgrade version to bypass check in ASM
setMajorVersion(Opcodes.V14, b);
setMajorVersion(Opcodes.V15, 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 @@ -25,6 +25,8 @@ <h3>New Features</h3>
<li>JaCoCo now officially supports Java 14.</li>
<li>Experimental support for Java 15 class files
(GitHub <a href="https://github.com/jacoco/jacoco/issues/992">#992</a>).</li>
<li>Experimental support for Java 16 class files
(GitHub <a href="https://github.com/jacoco/jacoco/issues/1059">#1059</a>).</li>
<li>Methods <code>toString</code>, <code>hashCode</code> and <code>equals</code>
generated by compiler for records are filtered out during generation of report
(GitHub <a href="https://github.com/jacoco/jacoco/issues/990">#990</a>).</li>
Expand Down