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

Java 可以为可以卸载的动态编译代码获得本机性能吗?,java,classloader,dynamic-compilation,Java,Classloader,Dynamic Compilation,事实上,你不能 动态编译代码 直接调用编译后的代码(即不使用“远程处理”、封送等)和 从内存中删除(仅)已编译代码 你必须在两个之间做出决定。(通过将代码生成到调用AppDomain本身)或3。(通过将代码生成一个废弃的AppDomain),但不能两者兼有 现在我很好奇这在Java中是否可行。我对类加载器了解不够,但在Java中我似乎可以 将代码动态编译到一次性类装入器中 直接调用编译后的代码(例如,通过对预定义接口的虚拟方法调用),而不进行任何封送处理 删除对已编译类的所有引用,并丢弃类加载器

事实上,你不能

  • 动态编译代码
  • 直接调用编译后的代码(即不使用“远程处理”、封送等)
  • 从内存中删除(仅)已编译代码
  • 你必须在两个之间做出决定。(通过将代码生成到调用AppDomain本身)或3。(通过将代码生成一个废弃的AppDomain),但不能两者兼有

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

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

  • 这个假设有效吗?

    是的,您可以编译/加载一个类a代码以外的类装入器,调用它没有问题

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

    然而,第3点是错误的。这很棘手

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

    谢谢。显然,如果你持有一个对象的引用,你不能期望它的类加载器消失。然而,好消息似乎是:在Java中,这是可以做到的。在.Net中,您必须决定:执行和泄漏,或者两者都不执行。