I'm trying to parse bytecode from Java 16 (bytecode version 60) using the ObjectWeb ASM. I've written the following code:
@Test
void parseBytecode() {
try (InputStream stream = this.getClass()
.getClassLoader()
.getResourceAsStream("MethodByte.class")) {
//MethodByte.class has 60 version (Java 16)
new ClassReader(stream).accept(new ClassPrinter(), 0);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private class ClassPrinter extends ClassVisitor {
protected ClassPrinter() {
super(Opcodes.ASM9);
}
}
When I run the code, I'm getting an IllegalArgumentException
:
Caused by: java.lang.IllegalArgumentException
at org.objectweb.asm.ClassReader.<init>(ClassReader.java:262)
at org.objectweb.asm.ClassReader.<init>(ClassReader.java:180)
at org.objectweb.asm.ClassReader.<init>(ClassReader.java:166)
at org.objectweb.asm.ClassReader.<init>(ClassReader.java:287)
Version of ASM library is 9.5
(from pom.xml
):
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.5</version>
<scope>compile</scope>
</dependency>
Also, it's worth mentioning that I checked the MethodByte.class
lies in the correct place. I printed its content to ensure that it is reachable in the test.
From my understanding, ASM 9 should support java 16. I suspect the error might be due to the ASM version I'm using, and its incompatibility with Java 16 bytecode, so I tried Opcodes.V16
instead of Opcodes.ASM9
and it didn't help.
Also I tried to parse the bytecode with 52 version (Java 8) and it didn't help either.
Has anyone encountered this before?
Update: How I get MethodByte.class
.
I'm using maven
to build project and run the tests. So, I have the next pipeline:
package org.eolang.jeo;
public class MethodByte {
public static void main(String[] args) {
System.out.println(method());
System.out.println("passed");
}
static byte method() {
return 52;
}
}
mvn clean compile
in order to build that class. I use the next maven configuration properties for that:<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
cp target/classes/org/eolang/jeo/MethodByte.class src/test/resources/.
As Johannes Kuhn mentioned, the binary representation of the original class didn't match the byte array passed into the org.objectweb.asm.ClassReader
class. The root of the problem lies in the Maven Resource Filtering mechanism. To put it simply, Maven triggers the resources:3.3.1:testResources
goal during the generate-test-sources
phase, which replaces placeholders in resource files with actual values. When Maven attempts to apply this filtering to binary files, it can encounter encoding issues, leading to the exception I mentioned in my question.
While the src/test/resources
folder contained the correct bytecode, it was corrupted when I ran the tests (using mvn clean test
command), subsequently causing the IllegalArgumentException
.
To address this, I excluded .class
files from filtering:
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.class</include>
</includes>
</testResource>
</testResources>
</build>
With this configuration, everything now works as expected without exceptions.