如何将操作码中 ASM 的 API 版本映射到 Java 版本?

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.

我如何知道 ASM# 用于 Java 的每个版本?我将 ASM# 用于 Java 8 什么? ASM# 我会为 Java 11 使用什么?

据我所知,没有简单的方法,但是 changelog of ASM 帮助很大。请注意,这些版本指的是 ASM 版本,不是 class 文件格式版本。

ASM… 常量描述了您的软件所需的最低 ASM 库版本。这对于兼容性至关重要,例如在 Visitor API 中,当您覆盖旧版本中不存在的方法时,您在链接到旧版本时不会注意到。该方法永远不会被调用。

因此,使用 ASM… 常量可以更早地发现此类问题。这就是为什么某些实现 类 提供 a constructors not requiring the version number, not allowed for subclasses, whereas their constructor for subclasses 确实需要它。由于只有 sub类 可以覆盖方法,因此受此问题影响。

如果您不打算将您的软件与旧版本的 ASM 库一起使用,只需使用与您当前的 ASM 库版本对应的编号,即没有 EXPERIMENTAL 后缀的最高版本。否则,我建议在开发和测试期间使用旧版本,这再次允许只使用该版本中现有的最高 ASM… 数字。

您可以使用最新的 ASM 库生成针对所有版本的 类。这取决于您传递给 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.

的版本

您似乎需要指定支持任何 class 文件的 ASM API 版本,因此如果您处于使用未知最新 ASM 的环境中,您可以通过反射字段搜索指定它。

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) {
    }
}

然后将其用作:

ClassVisitor cv = new ClassVisitor(ASM_VERSION)