Java 如何使用Scala(50.0/51.0)发布较新的类文件版本?

Java 如何使用Scala(50.0/51.0)发布较新的类文件版本?,java,class,scala,versioning,bytecode,Java,Class,Scala,Versioning,Bytecode,我想用scalac创建的类测试新的类型检查字节码验证器 scalac当前输出49.0版的类文件,但新的类型检查验证器仅在51.0版之后才是必需的 我试图用ProGuard“预先验证”这些类(实际上它将它们转换为50.0版),但我不确定新的验证器是否会自动退回到旧类型推断验证器 如何将类文件转换为51.0版(或者如何找出加载50.0版类文件时使用的验证器)?我不确定,但我认为字节码格式从未发生过深刻的变化,而且它可能总是向后兼容的。(如果您对字节码有所了解,请记住常量池和操作数堆栈上的long和d

我想用
scalac
创建的类测试新的类型检查字节码验证器

scalac
当前输出49.0版的类文件,但新的类型检查验证器仅在51.0版之后才是必需的

我试图用ProGuard“预先验证”这些类(实际上它将它们转换为50.0版),但我不确定新的验证器是否会自动退回到旧类型推断验证器


如何将类文件转换为51.0版(或者如何找出加载50.0版类文件时使用的验证器)?

我不确定,但我认为字节码格式从未发生过深刻的变化,而且它可能总是向后兼容的。(如果您对字节码有所了解,请记住常量池和操作数堆栈上的long和double,它们的设计有点疯狂。它没有被修改,是吗?)因此,更改主/次数字可能会起作用

怎么做?有两种方法:

  • 使用hexa编辑器并手动修改它。如果您知道字节的位置,它应该非常简单。这里有[字节码规范][1],它说,你应该跳过前四个字节,你会看到两个字节的次要版本和两个字节的主要版本(按此顺序)
  • 使用图书馆。我对BCEL有一些经验。它似乎不是我见过的设计最好的库,但它应该足够适合您的情况。我在类中见过方法setMinor和setMajor(看看ClassGen和“几乎不可变”的JavaClass)

[1] 我会用它来解析字节码。我知道scala(和clojure)在内部使用ASM,所以学习ASM的努力不会白费。您可以将a和a组合在一起,以相当快的速度覆盖提供标题信息的访问方法。

我知道这可能很明显,但在阅读您的问题后,我不确定,因此我会问:

你在使用测试版吗?比如在一个夜间构建中?还是要修改当前版本

编辑:好吧,有些东西我不明白。我刚刚尝试了夜间版本,是的,它们是49.0版。但据我所知,这是由编译器设置的

您正在尝试更改版本以访问一些新的高级功能。但这对我来说没有意义。如果编译器发布了49.0版,那么将其更改为任何更新的版本(重要的是50.0、51.0或70.0)都不会产生任何影响。据我所知,该版本是为了确保兼容性,这意味着您不会使用不支持您的语言的旧VM运行新类

因此,在您的情况下,添加新版本可能意味着当前VM不想运行您的代码。即使它包含,它也可能不包含您提到的功能,如果该功能仅在51.0版本中,而您当前的编译器/VM不支持该版本


我的意思是,也许你正在尝试做的事情是完全正常的,只是我不知道这一点,我在这方面显示了我的无知:),但我认为这其中缺少了一些东西。

我想最简单的事情之一就是使用java反编译器(请参阅Eclipse插件)然后将源代码重新编译到您需要的任何版本。

看起来FJBG(NSC用来生成字节码的库)已经在支持方面做了一些努力,但我不知道这有多远


如果你问scala内部的问题,Stephane Michelou可能会出现。他就是那个被杀的人。

不,这行不通。51.0引入了一个强制的StackMap属性,该属性与类型检查验证器一起使用。更改版本不会添加它。嗯,这是相互测试。我认为这不是强制性的。(我不是在说J2ME中的类似概念。)但是,我不理解您所做的“预先验证”操作。如果是J2ME预先验证,它不会将类文件转换为这样的新版本。如果它是较新的概念,它必须将其转换为51.0而不是50.0。顺便说一下,您还可以检查ASM库/工具。我在调试时使用它进行了一些字节码验证,它能够推断操作数堆栈类型,因此可以在此IMHO上生成StackMap。scala在内部不使用ASM。在我说之前,我甚至想过在线检查它。显然只有斯卡拉。我对这个错误深表歉意。我正在使用当前的2.9主干。我认为它不会在Scala source->bytecode->Java source->bytecode之间的往返过程中幸存下来。不是Scala中的所有东西都可以翻译成Java。谢谢!你的回答很有趣,也很有帮助。