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



在.Net中,似乎无法

  1. 动态编译代码
  2. 直接调用编译后的代码(即w/o"远程处理"、封送处理等)
  3. 从内存中删除(仅)已编译的代码

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

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

  1. 将代码动态编译到一次性类加载器中
  2. 直接调用编译后的代码(例如,通过对预定义接口的虚拟方法调用),不进行任何封送处理
  3. 删除对已编译类的所有引用并丢弃类加载器,以便GC负责删除

这个假设成立吗?

是的,您可以编译/加载一个类作为代码外类加载器,调用它不会有问题。

是的,动态代码将达到"完全性能"。没有区别。但是,新加载的代码将以解释模式启动,并且需要在编译之前进行预热。

然而,第3点。非常棘手。

  • "泄漏"一次性类加载器非常容易/很可能。类加载器保留对其加载的类的引用。每个类都有一个对其类加载器的引用。每个对象都是对其类的引用。因此,只要您有一个对象或类的引用,该对象或类是用一次性类加载器加载的,它和它加载的类就会保持活动。因为引用对象非常容易,所以"类加载器"泄漏非常常见
  • 这取决于GC配置和JVM版本,它实际上对加载的类进行GC传递。您可能需要额外的标志来启用它。例如CMS GC的"-XX:+CMSClassUnloadingEnabled"
  • 有一个代码缓存(在OpenJDK/Hotespot中),用于保存编译后的代码。如果你在应用程序的整个生命周期中一直加载代码,你可能会溢出这个缓存。在旧的JVM中,它只是被填满了,一旦填满,它就停止编译代码,从而降低性能,除非您启用了刷新缓存(-XX:+UseCodeCacheFlushing)。Afaik在较新版本中默认情况下会刷新。仔细检查一下。你可能需要留意代码缓存。(例如通过JMX)

最新更新