'How do I map ASM's API version in Opcodes to Java version?

ASM's ClassVisitor constructor requires passing one of Opcodes's ASM4, ASM5, ASM6, ASM7, ASM8 or ASM9.

How do I know which ASM# to use for each version of Java? What ASM# would I use for Java 8? What ASM# would I use for Java 11?



Solution 1:[1]

The ASM… constants describe the minimum ASM library version required by your software. This is crucial for compatibility, e.g. in the Visitor API, as when you’re overriding a method that does not exist in an older version, you wouldn’t notice when linking against an older version. The method would just never get called.

So, using the ASM… constant allows to spot such issue earlier. That’s why some implementation classes offer a constructors not requiring the version number, not allowed for subclasses, whereas their constructor for subclasses does require it. As only subclasses can override methods, thus, are affected by this issue.

If you are not planning to use your software with an older version of the ASM library, just use the number corresponding to your current ASM library version, i.e. the highest without the EXPERIMENTAL suffix. Otherwise, I suggest using the older version during development and testing, which again allows to just use the highest ASM… number existing in that version.

You can use the newest ASM library to generate classes targeting all versions. It depends on the version you’re passing to the visit method. Which is V1_8 for Java 8 and V11 for Java 11. The actual values of these constants are identical to the versions of the JVM specification.

Solution 2:[2]

As far as I know, no easy way, but the changelog of ASM helps a lot. Note that these versions refer to the ASM version, NOT the class file format version.

Solution 3:[3]

It appears that you need to specify a version of the ASM API that supports whatever class files you have, so if you are in a context that uses an unknown latest ASM, you can specify it by a reflective field search.

private static int ASM_VERSION = Opcodes.ASM5;      // Default to first Java 8 version

static {
    try {
        for (int i = 6; true; i++) {                // Loop for as many versions are available
            Field asmField = org.objectweb.asm.Opcodes.class.getField("ASM" + i);
            ASM_VERSION = asmField.getInt(null);
        }
    } catch (Throwable exception) {
    }
}

and then use it as:

ClassVisitor cv = new ClassVisitor(ASM_VERSION)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Holger
Solution 2 rzwitserloot
Solution 3 Ed Willink