18

问题:我有一个方法可以编译成超过 8000 字节的 Java 字节码。HotSpot 有一个神奇的限制,使 JIT 不会为超过 8000 字节的方法启动。(是的,拥有一个巨大的方法是合理的。这是一个标记器循环。)该方法在一个库中,我不想要求该库的用户必须配置 HotSpot 才能停用魔法限制。

观察:反编译字节码表明 Eclipse Java 编译器生成了很多无意义的 goto。(javac 甚至更糟。)也就是说,有些 goto 只能通过跳转到达。显然,跳转到 goto 的跳转应该直接跳转到 goto 跳转的地方,并且 goto 应该被消除。

问题:是否有针对 Java 5 类文件的字节码优化器,它可以扁平化无意义的跳转链,然后删除不必要的 goto?

编辑:我的意思是这样的模式:

8698:   goto    8548
8701:   goto    0

显然,第二个 goto 只能通过跳转到 8701 来达到,这也可能是直接跳转到 0。

在第二次调查中,这种可疑的模式更为常见:

4257:   if_icmpne   4263
4260:   goto    8704
4263:   aload_0

显然,人们希望编译器将“不等于”比较反转为“相等”比较,跳转到 8704 并消除 goto。

4

7 回答 7

1

我感觉到你的痛苦。我不得不编写一个解析器,它有大约 5kloc 的 if(str.equals(...)) 代码。我按照 parse1、parse2 等的方式分解了几种方法。如果 parse1 没有产生解析的答案,则调用 parse2 等。这不一定是最佳实践,但它确实可以满足您的需要.

于 2009-06-03T12:55:11.607 回答
0

一种编译超过 8000 字节的方法?有人看懂那个代码吗?是否可测试?尝试将其拆分为具有有意义名称的多个(私有?)方法,而不是使用优化器!

好的,也许有一些合法的大方法。但是很抱歉,问题中没有任何提示。

于 2009-06-03T12:49:50.527 回答
0

如果您不使用调试符号(即 javac 中的 -g 标志)进行编译,是否会有所不同?这可能会使该方法低于魔法极限。

于 2009-06-03T12:57:13.243 回答
0

将方法重构为子方法是不可能的吗?无论如何,现代 JIT 都会内联这些调用。

于 2009-06-03T13:06:47.480 回答
0

如果它是一个标记器循环,最好使用数据驱动的一组映射和一些适当的反射来做到这一点?

因此,您可以将标记匹配存储在一个结构中,该结构将它们映射到有关该标记的语法和实现相关函数的方法的数据。查找可以在结构上进行优化,避免大循环。

这引入了保持数据和实现同步的问题,但是您可以使用 doclet 或可能的注释从代码库生成数据。

在不确切知道您的大方法的作用的情况下,我们仅限于尝试以您认为最好的方式对其进行优化(这显然是不可能的)。

于 2009-06-03T14:34:12.733 回答
0

如果您在课堂上运行字节码收缩器/混淆器,您的性能会提高吗?例如,yguard,proguard,...

也许您可以使用 asm 编写类文件后处理器,因为您的用例非常具体。

即使您删除所有无意义的 goto,这是否会使您处于魔法限制之下?

于 2009-06-30T12:29:46.290 回答
0

字节码库列表提到了BCELASM,我以前听说过,还有许多其他人在做各种各样的事情。

于 2009-06-30T12:48:19.217 回答