为什么基于 invokedynamic 的字符串连接不适用于 java.base 中的 javac

Why invokedynamic-based String concatenation is not available for javac in java.base

有一次我鲁莽tried去优化Class.resolveName()靠的结果 基准(在引用的 PR 中可用)复制上述方法的逻辑。优化的想法非常简单,就是用简单的连接替换 new StringBuilder().append() 。事实证明,虽然基准测试显示出显着的改进,但修补后的方法本身却出现了倒退。正如 it was pointed out 在 PR

的评论中

The JMH test may show better results as it is compiled to bytecode that uses special invokedynamic-based string concatenation with optimal MH based underlying strategy. The code in java.lang.Class can't be compiled to use this kind of concatenation because of bootstrapping issues and is therefore compiled to bytecode that uses StringBuilder directly (much like the existing code of the patched method).

确实,java.base 中的字符串连接被编译成基于 StringBuilder 的字节码,这与客户端代码的做法不同(它们利用 invokedynamicStringConcatFactory ).

我调查了那些 'bootstrapping issues',但我唯一发现的是 class 加载的顺序。如果运行 java -Xlog:class+init -version,很明显 StringConcatFactoryj.l.Class 之后很远的地方加载。同时还有许多其他 class 引用自 j.l.Class 之后加载。

所以我的问题是为什么 javac 可以使用 e。 G。 StringBuilderClass.resolveName() 内,但不在 StringConcatFactory 内? class有什么特别之处?

或者我的猜测是错误的,引导问题不是关于 StringConcatFactoryinvokedynamic

这里的“Bootstrapping issues”是先有鸡还是先有蛋的问题

StringConcatFactory 依赖于 JSR 292 机制,后者又使用 java.base 类,后者使用字符串连接。为了解决这个循环依赖,concatenation is java.base 类 编译成 old-fashioned 的方式,不依赖 StringConcatFactory.