java代码的动态编译问题

    上回听了一堂关于Java动态编译和静态编译的课,觉得自己对这方面了解不多,于是整理下知识点,也上网查了些资料,对Java的动态编译有了一些基础的了解。
    Java动态编译器,通常称作即时(Just-in-time,JIT)编译器。程序运行时,JIT 编译器选择将最频繁执行的方法编译成本地代码。运行时再进行本地代码编译而不是在程序运行前进行编译,保证了可移植性的需求。但动态编译可能严重干扰程序操作,因为编译器必须与应用程序共享 CPU。对于Java代码,静态编译可以极大地提高 Java 性能,但同时也带来了很多复杂性。
    Java 程序最初是通过 Java SDK 的 javac程序编译成本地的与平台无关的class文件,可将此格式看作 Java 平台,因为它定义了执行 Java 程序所需的所有信息。Java 程序执行引擎,也称作 Java 运行时环境(JRE),包含了为特定的本地平台实现 Java 平台的虚拟机。
    尽管通过 JIT 编译保持了平台无关性,但是付出了一定代价。因为在程序执行时进行编译,所以编译代码的时间将计入程序的执行时间。为了克服这个缺点,现代的 JIT 编译器使用了下面两种方法的任意一种(某些情况下同时使用了这两种方法)。第一种方法是:编译所有的代码,但是不执行任何耗时多的分析和转换,因此可以快速生成代码。第二种方法是:将编译资源只分配给少量的频繁执行的方法(通常称作热方法),这种方法有效地实现了编译性能成本的最小化。

动态编译优点:
    动态编译能够比静态编译语言更好地生成代码,现代的 JIT 编译器常常向生成的代码中插入挂钩以收集有关程序行为的信息,以便如果要选择方法进行重编译,就可以更好地优化动态行为。比如说收集一个特定 arraycopy操作的长度。如果发现每次执行操作时该长度基本不变,则可以为最频繁使用的 arraycopy长度生成专门的代码,或者可以调用调整为该长度的代码序列。由于内存系统和指令集设计的特性,用于复制内存的最佳通用例程的执行速度通常比用于复制特定长度的代码慢。因为动态编译器通常只是集中编译少量的热方法,所以可以执行更主动的分析来生成更好的代码,使编译的回报更高。事实上,大部分现代的 JIT 编译器也支持重编译被认为是热方法的方法。
动态编译缺点:
    大量的初始编译可能直接影响应用程序的启动时间。不仅这些编译延迟了应用程序达到稳定状态的时间,而且在准备阶段中频繁执行的方法可能对应用程序的稳定状态的性能所起的作用也不大。如果 JIT 编译会延迟启动又不能显著改善应用程序的长期性能,则执行这种编译就非常浪费。
    其次,有些应用程序完全不能忍受动态编译带来的延迟。如 GUI 接口之类交互式应用程序就是这样的例子。在这种情况下,编译活动可能对用户使用造成不利影响,同时又不能显著地改善应用程序的性能。
    最后,用于实时环境并具有严格的任务时限的应用程序可能无法忍受编译的不确定性性能影响或动态编译器本身的内存开销。
    因此,虽然 JIT 编译技术已经能够提供与静态语言性能相当的性能水平,但是动态编译并不适合于某些应用程序。

你可能感兴趣的:(java,虚拟机,活动)