Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java和.Net在JIT方面有什么不同_Java_.net_Clr_Jit_Jvm Hotspot - Fatal编程技术网

Java和.Net在JIT方面有什么不同

Java和.Net在JIT方面有什么不同,java,.net,clr,jit,jvm-hotspot,Java,.net,Clr,Jit,Jvm Hotspot,我知道Microsoft.NET使用CLR作为JIT编译器,而Java则是热点。它们之间有什么区别?它们是非常不同的动物。正如人们指出的,CLR在执行一段MSIL之前编译成机器代码。除了典型的死代码消除和内联私有优化之外,它还可以利用目标机器的特定CPU体系结构(尽管我不确定它是否做到了)。这也会对每个类产生影响(尽管编译器速度相当快,而且许多平台库只是Win32 API上的一个薄层) HotSpot VM采取了不同的方法。它规定大部分代码很少执行,因此不值得花时间编译。所有字节码都以解释模式启

我知道Microsoft.NET使用CLR作为JIT编译器,而Java则是热点。它们之间有什么区别?

它们是非常不同的动物。正如人们指出的,CLR在执行一段MSIL之前编译成机器代码。除了典型的死代码消除和内联私有优化之外,它还可以利用目标机器的特定CPU体系结构(尽管我不确定它是否做到了)。这也会对每个类产生影响(尽管编译器速度相当快,而且许多平台库只是Win32 API上的一个薄层)

HotSpot VM采取了不同的方法。它规定大部分代码很少执行,因此不值得花时间编译。所有字节码都以解释模式启动。VM在调用站点保留统计信息,并尝试识别调用次数超过预定义次数的方法。然后它使用快速JIT编译器(C1)只编译这些方法,并在运行时交换该方法(这是HS的特殊特性)。在C1编译的方法被多次调用之后,同样的方法将使用缓慢但复杂的编译器编译,代码将在运行中再次交换

由于HotSpot可以在方法运行时交换方法,因此VM编译器可以执行一些在静态编译代码中不安全的推测性优化。一个典型的例子是单态调用的静态分派/内联(只有一个实现的多态方法)。如果VM发现此方法始终解析为同一目标,则会执行此操作。过去的复杂调用被简化为几个CPU指令,这些指令由现代CPU预测和流水线处理。当保护条件不再为真时,VM可以采用不同的代码路径,甚至返回到解释模式。根据统计数据和程序工作量,在不同的时间生成的机器代码可能不同。许多优化依赖于程序执行期间收集的信息,如果在加载类时编译一次,则不可能实现

这就是为什么在对算法进行基准测试时,需要预热JVM并模拟真实的工作负载(扭曲的数据可能会导致对优化进行不切实际的评估)。其他优化包括锁省略、自适应自旋锁定、转义分析和堆栈分配等


也就是说,HotSpot只是虚拟机中的一个。JRockit、Azul、IBM的J9和可重置RVM都有不同的性能配置文件。

NGen用于将MSIL预编译为本机代码,并对整个程序集进行预编译,但是,如果不进行NGen编码,则.Net CLR中的JIT编译器将为您即时进行预编译。在CLR中使用JIT编译器而不是NGen vs Hotspot可以更好地对两者进行比较。对于Java,“所有字节码都以解释模式启动”是真的吗?我认为在启动时也会进行调用计数,如果超过阈值,则会在启动时进行编译。这可能与编译器有关:@kovac-是的,对于OpenJDK热点来说是这样。所有代码都从C1开始,C2只编译热循环/方法。不过,Java语言规范并没有告诉每个JVM都应该这样做。