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 23 class files #1553

Merged
merged 3 commits into from
Dec 12, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ jobs:
JDK_VERSION: 21
JDK 22:
JDK_VERSION: 22
JDK 23:
JDK_VERSION: 23
pool:
vmImage: 'ubuntu-20.04'
steps:
Expand Down
14 changes: 14 additions & 0 deletions org.jacoco.build/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,20 @@
</properties>
</profile>

<profile>
<id>java23-bytecode</id>
<activation>
<property>
<name>bytecode.version</name>
<value>23</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
33 changes: 33 additions & 0 deletions org.jacoco.core.test.validation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,39 @@
</modules>
</profile>

<profile>
<id>java23-bytecode</id>
<activation>
<property>
<name>bytecode.version</name>
<value>23</value>
</property>
</activation>
<properties>
<!-- Kotlin 1.5.0 doesn't support compilation into 23 -->
<kotlin.compiler.jvmTarget>16</kotlin.compiler.jvmTarget>
<!-- Groovy 3.0.19 does not support compilation into 23 -->
<groovy.targetBytecode>16</groovy.targetBytecode>
<!-- see respective profile in org.jacoco.build about this override -->
<maven.compiler.source>23</maven.compiler.source>
<maven.compiler.target>23</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>
<module>../org.jacoco.core.test.validation.java21</module>
<!-- Groovy 3.0.19 does not support Java 23
<module>../org.jacoco.core.test.validation.groovy</module>
-->
<!-- Scala 2.13.4 does not support Java 23 - see https://github.com/jacoco/jacoco/issues/1431
<module>../org.jacoco.core.test.validation.scala</module>
-->
</modules>
</profile>

</profiles>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,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.V21 + 1);
final byte[] originalBytes = createClass(Opcodes.V22 + 1);
final byte[] bytes = new byte[originalBytes.length];
System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length);
final long expectedClassId = CRC64.classId(bytes);
Expand All @@ -132,13 +132,13 @@ private static byte[] createClass(final int version) {
*/
@Test
public void analyzeClass_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V21 + 2);
final byte[] bytes = createClass(Opcodes.V22 + 2);
try {
analyzer.analyzeClass(bytes, "UnsupportedVersion");
fail("exception expected");
} catch (IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
assertEquals("Unsupported class file major version 67",
assertEquals("Unsupported class file major version 68",
e.getCause().getMessage());
}
}
Expand Down Expand Up @@ -218,14 +218,14 @@ public void testAnalyzeClass_BrokenStream() throws IOException {
*/
@Test
public void analyzeAll_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V21 + 2);
final byte[] bytes = createClass(Opcodes.V22 + 2);
try {
analyzer.analyzeAll(new ByteArrayInputStream(bytes),
"UnsupportedVersion");
fail("exception expected");
} catch (IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
assertEquals("Unsupported class file major version 67",
assertEquals("Unsupported class file major version 68",
e.getCause().getMessage());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,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.V21 + 1);
final byte[] originalBytes = createClass(Opcodes.V22 + 1);
final byte[] bytes = new byte[originalBytes.length];
System.arraycopy(originalBytes, 0, bytes, 0, originalBytes.length);
final long expectedClassId = CRC64.classId(bytes);
Expand All @@ -123,13 +123,13 @@ private static byte[] createClass(final int version) {
*/
@Test
public void instrument_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V21 + 2);
final byte[] bytes = createClass(Opcodes.V22 + 2);
try {
instrumenter.instrument(bytes, "UnsupportedVersion");
fail("exception expected");
} catch (final IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
assertEquals("Unsupported class file major version 67",
assertEquals("Unsupported class file major version 68",
e.getCause().getMessage());
}
}
Expand Down Expand Up @@ -221,14 +221,14 @@ public void testSerialization() throws Exception {
*/
@Test
public void instrumentAll_should_throw_exception_for_unsupported_class_file_version() {
final byte[] bytes = createClass(Opcodes.V21 + 2);
final byte[] bytes = createClass(Opcodes.V22 + 2);
try {
instrumenter.instrumentAll(new ByteArrayInputStream(bytes),
new ByteArrayOutputStream(), "UnsupportedVersion");
fail("exception expected");
} catch (final IOException e) {
assertExceptionMessage("UnsupportedVersion", e);
assertEquals("Unsupported class file major version 67",
assertEquals("Unsupported class file major version 68",
e.getCause().getMessage());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public void setup() {
}

@Test
public void classReaderFor_should_read_java_22_class() {
final byte[] bytes = createJava22Class();
public void classReaderFor_should_read_java_23_class() {
final byte[] bytes = createJava23Class();

final ClassReader classReader = InstrSupport.classReaderFor(bytes);

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

assertArrayEquals(createJava22Class(), bytes);
assertArrayEquals(createJava23Class(), bytes);
}

private static byte[] createJava22Class() {
private static byte[] createJava23Class() {
final ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V21 + 1, 0, "Foo", null, "java/lang/Object", null);
cw.visit(Opcodes.V22 + 1, 0, "Foo", null, "java/lang/Object", null);
cw.visitEnd();
return cw.toByteArray();
}
Expand Down Expand Up @@ -133,7 +133,8 @@ public void needFrames_should_return_true_for_versions_greater_than_or_equal_to_
assertTrue(InstrSupport.needsFrames(Opcodes.V19));
assertTrue(InstrSupport.needsFrames(Opcodes.V20));
assertTrue(InstrSupport.needsFrames(Opcodes.V21));
assertTrue(InstrSupport.needsFrames(Opcodes.V21 + 1));
assertTrue(InstrSupport.needsFrames(Opcodes.V22));
assertTrue(InstrSupport.needsFrames(Opcodes.V22 + 1));

assertTrue(InstrSupport.needsFrames(0x0100));
}
Expand Down
Original file line number Diff line number Diff line change
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.V21 + 1) {
if (originalVersion == Opcodes.V22 + 1) {
// temporarily downgrade version to bypass check in ASM
setMajorVersion(Opcodes.V21, b);
setMajorVersion(Opcodes.V22, b);
}
final ClassReader classReader = new ClassReader(b);
setMajorVersion(originalVersion, b);
Expand Down
6 changes: 6 additions & 0 deletions org.jacoco.doc/docroot/doc/changes.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ <h1>Change History</h1>

<h2>Snapshot Build @qualified.bundle.version@ (@build.date@)</h2>

<h3>New Features</h3>
<ul>
<li>Experimental support for Java 23 class files
(GitHub <a href="https://github.com/jacoco/jacoco/issues/1553">#1553</a>).</li>
</ul>

<h2>Release 0.8.11 (2023/10/14)</h2>

<h3>New Features</h3>
Expand Down