可以为可以卸载的动态编译代码获得本机性能吗?

Possible to get native performance for dynamically compiled code that can be unloaded?

.Net, it seems你不能

  1. 动态编译代码
  2. 直接调用编译后的代码(即w/o"remoting"、编组等)
  3. 从内存中删除(仅)编译后的代码

您必须在 2.(通过将代码生成到调用 AppDomain 本身)或 3.(通过将代码生成到一次性 AppDomain 中)之间做出决定,但您不能两者兼得。

现在我很好奇这在 Java 中是否可行。我对 ClassLoader 了解不够,但似乎 Java 我可以

  1. 将代码动态编译成一次性 class 加载器
  2. 直接调用编译后的代码(比如,通过对预定义接口的虚方法调用),w/o任何封送处理
  3. 删除所有对已编译 class 和丢弃 class 加载程序的引用,以便 GC 负责删除

这个假设是否成立?

是的,您可以编译/加载一个 class 代码 class 加载程序,调用它没有问题。

是的,动态代码将达到 'full performance'。没有区别。但是,新加载的代码将以解释模式启动,需要在编译前预热。

然而,第 3 点非常棘手。

  • 'Leaking' 扔掉 class 装载机很容易/可能。 class 加载程序保留对其加载的 classes 的引用。每个 class 都包含对其 class 加载程序的引用。每个对象都是对它的引用 class。因此,只要你有一个对象或 class 的引用,它是用丢弃的 class 加载程序加载的,它和它加载的 class 就会保持活动状态。 因为很容易引用对象,所以 'classloader' 泄漏很常见。
  • 这取决于 GC 配置和 JVM 版本,它实际上会在加载的 classes 上传递 GC。您可能需要额外的标志来启用它。类似于 CMS GC '-XX:+CMSClassUnloadingEnabled'。
  • 有一个代码缓存(在OpenJDK/Hotspot),它保存编译后的代码。如果您在应用程序的整个生命周期中一直加载代码,您可能会超出此缓存。在较旧的 JVM 中,它刚刚填满,一旦填满,它就停止编译代码,性能下降,除非您启用刷新缓存 (-XX:+UseCodeCacheFlushing)。 Afaik 在较新的版本中默认刷新。仔细检查一下。您可能需要关注代码缓存。 (例如通过 JMX)