动态编译技术百度百科
A. 了解什么叫做jit compiling,与传统的编译技术有何不同
java 应用程序的性能经常成为开发社区中的讨论热点。因为该语言的设计初衷是使用解释的方式支持应用程序的可移植性目标,早期
Java 运行时所提供的性能级别远低于 C 和
C++
之类的编译语言。尽管这些语言可以提供更高的性能,但是生成的代码只能在有限的几种系统上执行。在过去的十年中,Java
运行时供应商开发了一些复杂的动态编译器,通常称作即时(Just-in-time,JIT)编译器。程序运行时,JIT
编译器选择将最频繁执行的方法编译成本地代码。运行时才进行本地代码编译而不是在程序运行前进行编译(用 C 或
C++ 编写的程序正好属于后一情形),保证了可移植性的需求。有些 JIT 编译器甚至不使用解释程序就能编译所有的代码,但是这些编译器仍然通过在程序执行时进行一些操作来保持 Java 应用程序的可移植性。
由于动态编译技术的多项改进,在很多应用程序中,现代的 JIT 编译器可以产生与 C 或 C++
静态编译相当的应用程序性能。但是,仍然有很多软件开发人员认为 —— 基于经验或者传闻 ——
动态编译可能严重干扰程序操作,因为编译器必须与应用程序共享 CPU。一些开发人员强烈呼吁对 Java
代码进行静态编译,并且坚信那样可以解决性能问题。对于某些应用程序和执行环境而言,这种观点是正确的,静态编译可以极大地提高 Java
性能,或者说它是惟一的实用选择。但是,静态地编译 Java 应用程序在获得高性能的同时也带来了很多复杂性。一般的
Java 开发人员可能并没有充分地感受到 JIT 动态编译器的优点。
本文考察了 Java 语言静态编译和动态编译所涉及的一些问题,重点介绍了实时 (RT) 系统。简要描述了 Java
语言解释程序的操作原理并说明了现代 JIT 编译器执行本地代码编译的优缺点。介绍了 IBM 在 WebSphere Real Time 中发布的
AOT 编译技术和它的一些优缺点。然后比较了这两种编译策略并指出了几种比较适合使用 AOT
编译的应用程序领域和执行环境。要点在于这两种编译技术并不互斥:即使在使用这两种技术最为有效的各种应用程序中,它们也分别存在一些影响应用程序的优缺
点。
执行 Java 程序
Java 程序最初是通过 Java SDK 的 javac程序编译成本地的与平台无关的格式(类文件)。可将此格式看作 Java
平台,因为它定义了执行 Java 程序所需的所有信息。Java 程序执行引擎,也称作 Java 运行时环境(JRE),包含了为特定的本地平台实现
Java 平台的虚拟机。例如,基于 Linux 的 Intel x86 平台、Sun Solaris 平台和 AIX 操作系统上运行的 IBM
System p 平台,每个平台都拥有一个 JRE。这些 JRE 实现实现了所有的本地支持,从而可以正确执行为
Java 平台编写的程序。
事实上,操作数堆栈的大小有实际限制,但是编程人员极少编写超出该限制的方法。JVM 提供了安全性检查,对那些创建出此类方法的编程人员进行通知。
Java 平台程序表示的一个重要部分是字节码序列,它描述了 Java
类中每个方法所执行的操作。字节码使用一个理论上无限大的操作数堆栈来描述计算。这个基于堆栈的程序表示提供了平台无关性,因为它不依赖任何特定本地平台
的 CPU 中可用寄存器的数目。可在操作数堆栈上执行的操作的定义都独立于所有本地处理器的指令集。Java
虚拟机(JVM)规范定义了这些字节码的执行(参见 参考资料)。执行 Java 程序时,用于任何特定本地平台的任何 JRE 都必须遵守 JVM
规范中列出的规则。
因为基于堆栈的本地平台很少(Intel X87 浮点数协处理器是一个明显的例外),所以大多数本地平台不能直接执行 Java 字节码。为了解决这个问题,早期的 JRE 通过解释字节码来执行 Java 程序。即 JVM 在一个循环中重复操作:
◆获取待执行的下一个字节码;
◆解码;
◆从操作数堆栈获取所需的操作数;
◆按照 JVM 规范执行操作;
◆将结果写回堆栈。
这种方法的优点是其简单性:JRE 开发人员只需编写代码来处理每种字节码即可。并且因为用于描述操作的字节码少于 255 个,所以实现的成本比较低。当然,缺点是性能:这是一个早期造成很多人对 Java 平台不满的问题,尽管拥有很多其他优点。
解决与 C 或 C++ 之类的语言之间的性能差距意味着,使用不会牺牲可移植性的方式开发用于 Java 平台的本地代码编译。
编译 Java 代码
尽管传闻中 Java 编程的 “一次编写,随处运行”
的口号可能并非在所有情况下都严格成立,但是对于大量的应用程序来说情况确实如此。另一方面,本地编译本质上是特定于平台的。那么 Java
平台如何在不牺牲平台无关性的情况下实现本地编译的性能?答案就是使用 JIT 编译器进行动态编译,这种方法已经使用了十年(参见图 1):
图 1. JIT 编译器
使用 JIT 编译器时,Java
程序按每次编译一个方法的形式进行编译,因为它们在本地处理器指令中执行以获得更高的性能。此过程将生成方法的一个内部表示,该表示与字节码不同但是其级
别要高于目标处理器的本地指令。(IBM JIT
编译器使用一个表达式树序列表示方法的操作。)编译器执行一系列优化以提高质量和效率,最后执行一个代码生成步骤将优化后的内部表示转换成目标处理器的本
地指令。生成的代码依赖运行时环境来执行一些活动,比如确保类型转换的合法性或者对不能在代码中直接执行的某些类型的对象进行分配。JIT
编译器操作的编译线程与应用程序线程是分开的,因此应用程序不需要等待编译的执行。
图 1 中还描述了用于观察执行程序行为的分析框架,通过周期性地对线程取样找出频繁执行的方法。该框架还为专门进行分析的方法提供了工具,用来存储程序的此次执行中可能不会改变的动态值。
因为这个 JIT 编译过程在程序执行时发生,所以能够保持平台无关性:发布的仍然是中立的 Java 平台代码。C 和 C++ 之类的语言缺乏这种优点,因为它们在程序执行前进行本地编译;发布给(本地平台)执行环境的是本地代码。
挑战
尽管通过 JIT 编译保持了平台无关性,但是付出了一定代价。因为在程序执行时进行编译,所以编译代码的时间将计入程序的执行时间。任何编写过大型 C 或 C++ 程序的人都知道,编译过程往往较慢。
为了克服这个缺点,现代的 JIT
编译器使用了下面两种方法的任意一种(某些情况下同时使用了这两种方法)。第一种方法是:编译所有的代码,但是不执行任何耗时多的分析和转换,因此可以快
速生成代码。由于生成代码的速度很快,因此尽管可以明显观察到编译带来的开销,但是这很容易就被反复执行本地代码所带来的性能改善所掩盖。第二种方法是:
将编译资源只分配给少量的频繁执行的方法(通常称作热方法)。低编译开销更容易被反复执行热代码带来的性能优势掩盖。很多应用程序只执行少量的热方法,因
此这种方法有效地实现了编译性能成本的最小化。
动态编译器的一个主要的复杂性在于权衡了解编译代码的预期获益使方法的执行对整个程序的性能起多大作用。一个极端的例子是,程序执行后,您非常清楚哪些方
法对于这个特定的执行的性能贡献最大,但是编译这些方法毫无用处,因为程序已经完成。而在另一个极端,程序执行前无法得知哪些方法重要,但是每种方法的潜
在受益都最大化了。大多数动态编译器的操作介于这两个极端之间,方法是权衡了解方法预期获益的重要程度。
Java 语言需要动态加载类这一事实对 Java
编译器的设计有着重要的影响。如果待编译代码引用的其他类还没有加载怎么办?比如一个方法需要读取某个尚未加载的类的静态字段值。Java
语言要求第一次执行类引用时加载这个类并将其解析到当前的 JVM
中。直到第一次执行时才解析引用,这意味着没有地址可供从中加载该静态字段。编译器如何处理这种可能性?编译器生成一些代码,用于在没有加载类时加载并解
析类。类一旦被解析,就会以一种线程安全的方式修改原始代码位置以便直接访问静态字段的地址,因为此时已获知该地址。
IBM JIT
编译器中进行了大量的努力以便使用安全而有效率的代码补丁技术,因此在解析类之后,执行的本地代码只加载字段的值,就像编译时已经解析了字段一样。另外一
种方法是生成一些代码,用于在查明字段的位置以前一直检查是否已经解析字段,然后加载该值。对于那些由未解析变成已解析并被频繁访问的字段来说,这种简单
的过程可能带来严重的性能问题。
动态编译的优点
动态地编译 Java 程序有一些重要的优点,甚至能够比静态编译语言更好地生成代码,现代的 JIT 编译器常常向生成的代码中插入挂钩以收集有关程序行为的信息,以便如果要选择方法进行重编译,就可以更好地优化动态行为。
关于此方法的一个很好的例子是收集一个特定 array操作的长度。如果发现每次执行操作时该长度基本不变,则可以为最频繁使用的
array长度生成专门的代码,或者可以调用调整为该长度的代码序列。由于内存系统和指令集设计的特性,用于复制内存的最佳通用例程的执行速度通
常比用于复制特定长度的代码慢。例如,复制 8
个字节的对齐的数据可能需要一到两条指令直接复制,相比之下,使用可以处理任意字节数和任意对齐方式的一般复制循环可能需要 10 条指令来复制同样的 8
个字节。但是,即使此类专门的代码是为某个特定的长度生成的,生成的代码也必须正确地执行其他长度的复制。生成代码只是为了使常见长度的操作执行得更快,
因此平均下来,性能得到了改进。此类优化对大多数静态编译语言通常不实用,因为所有可能的执行中长度恒定的操作比一个特定程序执行中长度恒定的操作要少得
多。
此类优化的另一个重要的例子是基于类层次结构的优化。例如,一个虚方法调用需要查看接收方对象的类调用,以便找出哪个实际目标实现了接收方对象的虚方法。
研究表明:大多数虚调用只有一个目标对应于所有的接收方对象,而 JIT
编译器可以为直接调用生成比虚调用更有效率的代码。通过分析代码编译后类层次结构的状态,JIT
编译器可以为虚调用找到一个目标方法,并且生成直接调用目标方法的代码而不是执行较慢的虚调用。当然,如果类层次结构发生变化,并且出现另外的目标方法,
则 JIT
编译器可以更正最初生成的代码以便执行虚调用。在实践中,很少需要作出这些更正。另外,由于可能需要作出此类更正,因此静态地执行这种优化非常麻烦。
因为动态编译器通常只是集中编译少量的热方法,所以可以执行更主动的分析来生成更好的代码,使编译的回报更高。事实上,大部分现代的
JIT
编译器也支持重编译被认为是热方法的方法。可以使用静态编译器(不太强调编译时间)中常见的非常主动的优化来分析和转换这些频繁执行的方法,以便生成更好
的代码并获得更高的性能。
这些改进及其他一些类似的改进所产生的综合效果是:对于大量的 Java 应用程序来说,动态编译已经弥补了与 C 和 C++ 之类语言的静态本地编译性能之间的差距,在某些情况下,甚至超过了后者的性能。
缺点
但是,动态编译确实具有一些缺点,这些缺点使它在某些情况下算不上一个理想的解决方案。例如,因为识别频繁执行的方法以及编译这些方法需要时间,所以应用
程序通常要经历一个准备过程,在这个过程中性能无法达到其最高值。在这个准备过程中出现性能问题有几个原因。首先,大量的初始编译可能直接影响应用程序的
启动时间。不仅这些编译延迟了应用程序达到稳定状态的时间(想象 Web
服务器经
历一个初始阶段后才能够执行实际有用的工作),而且在准备阶段中频繁执行的方法可能对应用程序的稳定状态的性能所起的作用也不大。如果 JIT
编译会延迟启动又不能显着改善应用程序的长期性能,则执行这种编译就非常浪费。虽然所有的现代 JVM
都执行调优来减轻启动延迟,但是并非在所有情况下都能够完全解决这个问题。
其次,有些应用程序完全不能忍受动态编译带来的延迟。如 GUI 接口之类交互式应用程序就是这样的例子。在这种情况下,编译活动可能对用户使用造成不利影响,同时又不能显着地改善应用程序的性能。
最后,用于实时环境并具有严格的任务时限的应用程序可能无法忍受编译的不确定性性能影响或动态编译器本身的内存开销。
因此,虽然 JIT 编译技术已经能够提供与静态语言性能相当(甚至更好)的性能水平,但是动态编译并不适合于某些应用程序。在这些情况下,Java 代码的提前(Ahead-of-time,AOT)编译可能是合适的解决方案。
AOT Java 编译
大致说来,Java 语言本地编译应该是为传统语言(如 C++ 或
Fortran)而开发的编译技术的一个简单应用。不幸的是,Java 语言本身的动态特性带来了额外的复杂性,影响了 Java
程序静态编译代码的质量。但是基本思想仍然是相同的:在程序执行前生成 Java 方法的本地代码,以便在程序运行时直接使用本地代码。目的在于避免
JIT 编译器的运行时性能消耗或内存消耗,或者避免解释程序的早期性能开销。
挑战
动态类加载是动态 JIT 编译器面临的一个挑战,也是 AOT
编译的一个更重要的问题。只有在执行代码引用类的时候才加载该类。因为是在程序执行前进行 AOT
编译的,所以编译器无法预测加载了哪些类。就是说编译器无法获知任何静态字段的地址、任何对象的任何实例字段的偏移量或任何调用的实际目标,甚至对直接调
用(非虚调用)也是如此。在执行代码时,如果证明对任何这类信息的预测是错误的,这意味着代码是错误的并且还牺牲了 Java 的一致性。
因为代码可以在任何环境中执行,所以类文件可能与代码编译时不同。例如,一个 JVM
实例可能从磁盘的某个特定位置加载类,而后面一个实例可能从不同的位置甚至网络加载该类。设想一个正在进行 bug
修复的开发环境:类文件的内容可能随不同的应用程序的执行而变化。此外,Java 代码可能在程序执行前根本不存在:比如 Java
反射服务通常在运行时生成新类来支持程序的行为。
缺少关于静态、字段、类和方法的信息意味着严重限制了 Java 编译器中优化框架的大部分功能。内联可能是静态或动态编译器应用的最重要的优化,但是由于编译器无法获知调用的目标方法,因此无法再使用这种优化。
内联
内联是一种用于在运行时生成代码避免程序开始和结束时开销的技术,方法是将函数的调用代码插入到调用方的函数中。但是内联最大的益处可能是优化方可见的代码的范围扩大了,从而能够生成更高质量的代码。下面是一个内联前的代码示例:
int foo() { int x=2, y=3; return bar(x,y); }final int bar(int a, int b) { return a+b; }
如果编译器可以证明这个 bar就是 foo()中调用的那个方法,则 bar中的代码可以取代 foo()中对
bar()的调用。这时,bar()方法是 final类型,因此肯定是 foo()中调用的那个方法。甚至在一些虚调用例子中,动态 JIT
编译器通常能够推测性地内联目标方法的代码,并且在绝大多数情况下能够正确使用。编译器将生成以下代码:
int foo() { int x=2, y=3; return x+y; }
在这个例子中,简化前名为值传播的优化可以生成直接返回
5的代码。如果不使用内联,则不能执行这种优化,产生的性能就会低很多。如果没有解析
bar()方法(例如静态编译),则不能执行这种优化,而代码必须执行虚调用。运行时,实际调用的可能是另外一个执行两个数字相乘而不是相加的
bar方法。所以不能在 Java 程序的静态编译期间直接使用内联。
AOT
代码因此必须在没有解析每个静态、字段、类和方法引用的情况下生成。执行时,每个这些引用必须利用当前运行时环境的正确值进行更新。这个过程可能直接影响
第一次执行的性能,因为在第一次执行时将解析所有引用。当然,后续执行将从修补代码中获益,从而可以更直接地引用实例、静态字段或方法目标。
另外,为 Java 方法生成的本地代码通常需要使用仅在单个 JVM 实例中使用的值。例如,代码必须调用 JVM
运行时中的某些运行时例程来执行特定操作,如查找未解析的方法或分配内存。这些运行时例程的地址可能在每次将 JVM 加载到内存时变化。因此 AOT
编译代码需要绑定到 JVM 的当前执行环境中,然后才能执行。其他的例子有字符串的地址和常量池入口的内部位置。
在 WebSphere Real Time 中,AOT 本地代码编译通过 jxeinajar工具(参见图 2)来执行。该工具对 JAR 文件中所有类的所有方法应用本地代码编译,也可以选择性地对需要的方法应用本地代码编译。结果被存储到名为 Java eXEcutable (JXE) 的内部格式中,但是也可轻松地存储到任意的持久性容器中。
您可能认为对所有的代码进行静态编译是最好的方法,因为可以在运行时执行最大数量的本地代码。但是此处可以作出一些权衡。编译的方法越多,代码占用的内存
就越多。编译后的本地代码大概比字节码大 10 倍:本地代码本身的密度比字节码小,而且必须包含代码的附加元数据,以便将代码绑定到 JVM
中,并且在出现异常或请求堆栈跟踪时正确执行代码。构成普通 Java 应用程序的 JAR
文件通常包含许多很少执行的方法。编译这些方法会消耗内存却没有什么预期收益。相关的内存消耗包括以下过程:将代码存储到磁盘上、从磁盘取出代码并装入
JVM,以及将代码绑定到 JVM。除非多次执行代码,否则这些代价不能由本地代码相对解释的性能优势来弥补。
图 2. jxeinajar
跟大小问题相违背的一个事实是:在编译过的方法和解释过的方法之间进行的调用(即编译过的方法调用解释过的方法,或者相反)可能比这两类方法各自内部之间
进行的调用所需的开销大。动态编译器通过最终编译所有由 JIT
编译代码频繁调用的那些解释过的方法来减少这项开销,但是如果不使用动态编译器,则这项开销就不可避免。因此如果是选择性地编译方法,则必须谨慎操作以使
从已编译方法到未编译方法的转换最小化。为了在所有可能的执行中都避免这个问题而选择正确的方法会非常困难。
优点
虽然 AOT 编译代码具有上述的缺点和挑战,但是提前编译 Java 程序可以提高性能,尤其是在不能将动态编译器作为有效解决方案的环境中。
可以通过谨慎地使用 AOT 编译代码加快应用程序启动,因为虽然这种代码通常比 JIT
编译代码慢,但是却比解释代码快很多倍。此外,因为加载和绑定 AOT
编译代码的时间通常比检测和动态编译一个重要方法的时间少,所以能够在程序执行的早期达到那样的性能。类似地,交互式应用程序可以很快地从本地代码中获
益,无需使用引起较差响应能力的动态编译。
RT 应用程序也能从 AOT 编译代码中获得重要的收益:更具确定性的性能超过了解释的性能。WebSphere Real Time
使用的动态 JIT 编译器针对在 RT 系统中的使用进行了专门的调整。使编译线程以低于 RT
任务的优先级操作,并且作出了调整以避免生成带有严重的不确定性性能影响的代码。但是,在一些 RT 环境中,出现 JIT
编译器是不可接受的。此类环境通常需要最严格的时限管理控制。在这些例子中,AOT
编译代码可以提供比解释过的代码更好的原始性能,又不会影响现有的确定性。消除 JIT
编译线程甚至消除了启动更高优先级 RT 任务时发生的线程抢占所带来的性能影响。
优缺点统计
动态(JIT)编译器支持平台中立性,并通过利用应用程序执行的动态行为和关于加载的类及其层次结构的信息来生成高质量的代码。但是
JIT
编译器具有一个有限的编译时预算,而且会影响程序的运行时性能。另一方面,静态(AOT)编译器则牺牲了平台无关性和代码质量,因为它们不能利用程序的动
态行为,也不具有关于加载的类或类层次结构的信息。AOT 编译拥有有效无限制的编译时预算,因为 AOT
编译时间不会影响运行时性能,但是在实践中开发人员不会长期等待静态编译步骤的完成。
表 1 总结了本文讨论的 Java 语言动态和静态编译器的一些特性:
表 1. 比较编译技术
两种技术都需要谨慎选择编译的方法以实现最高的性能。对动态编译器而言,编译器自身作出决策,而对于静态编译器,由开发人员作出选择。让
JIT 编译器选择编译的方法是不是优点很难说,取决于编译器在给定情形中推断能力的好坏。在大多数情况下,我们认为这是一种优点。
因为它们可以最好地优化运行中的程序,所以 JIT 编译器在提供稳定状态性能方面更胜一筹,而这一点在大量的生产 Java
系统中最为重要。静态编译可以产生最佳的交互式性能,因为没有运行时编译行为来影响用户预期的响应时间。通过调整动态编译器可以在某种程度上解决启动和确
定性性能问题,但是静态编译在需要时可提供最快的启动速度和最高级别的确定性。表 2 在四种不同的执行环境中对这两种编译技术进行了比较:
表 2. 使用这些技术的最佳环境
图 3 展示了启动性能和稳定状态性能的总体趋势:
图 3. AOT 和 JIT 的性能对比
使用 JIT 编译器的初始阶段性能很低,因为要首先解释方法。随着编译方法的增多及 JIT
执行编译所需时间的缩短,性能曲线逐渐升高最后达到性能峰值。另一方面,AOT 编译代码启动时的性能比解释的性能高很多,但是无法达到 JIT
编译器所能达到的最高性能。将静态代码绑定到 JVM 实例中会产生一些开销,因此开始时的性能比稳定状态的性能值低,但是能够比使用 JIT
编译器更快地达到稳定状态的性能水平。
没有一种本地代码编译技术能够适合所有的 Java
执行环境。某种技术所擅长的通常正是其他技术的弱项。出于这个原因,需要同时使用这两种编译技术以满足 Java
应用程序开发人员的要求。事实上,可以结合使用静态和动态编译以便提供最大可能的性能提升 —— 但是必须具备平台无关性,它是 Java
语言的主要卖点,因此不成问题。
结束语
本文探讨了 Java 语言本地代码编译的问题,主要介绍了 JIT 编译器形式的动态编译和静态 AOT 编译,比较了二者的优缺点。
虽然动态编译器在过去的十年里实现了极大的成熟,使大量的各种 Java 应用程序可以赶上或超过静态编译语言(如 C++ 或
Fortran)所能够达到的性能。但是动态编译在某些类型的应用程序和执行环境中仍然不太合适。虽然 AOT
编译号称动态编译缺点的万能解决方案,但是由于 Java 语言本身的动态特性,它也面临着提供本地编译全部潜能的挑战。
这两种技术都不能解决 Java 执行环境中本地代码编译的所有需求,但是反过来又可以在最有效的地方作为工具使用。这两种技术可以相互补充。能够恰当地使用这两种编译模型的运行时系统可以使很大范围内的应用程序开发环境中的开发人员和用户受益。
B. JAVA中反射是什么
JAVA中反射是动态获取信息以及动态调用对象方法的一种反射机制。
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态语言的一个关键性质。
Java反射的功能是在运行时判断任意一个对象所属的类,在运行时构造任意一个类的对象,在运行时判断任意一个类所具有的成员变量和方法,在运行时调用任意一个对象的方法,生成动态代理。
(2)动态编译技术百度百科扩展阅读:
JAVA中反射实例:
1、Class superClass=clazz.getSuperclass();//获取父类。
System.out.println("getSuperclass:"+superClass)。
2、Class[] interfaces=clazz.getInterfaces();//获取实现接口。
System.out.println("getInterfaces:"+interfaces.length)。
3、Constructor[] cons=clazz.getConstructors();//构造方法。
System.out.println("getConstructors:"+cons.length)。
参考资料来源:网络: JAVA反射机制
C. NIO和TIJ是什么
JDK 1.4版本(包括之后的版本)最显着的新特性就是增加了NIO(New IO),能够以非阻塞的方式处理网络的请求,这就使得在Java中只需要少量的线程就能处理大量的并发请求了。但是使用NIO不是一件简单的技术,它的一些特点使得编程的模型比原来阻塞的方式更为复杂。
在JDK 1.4的新特性中,NIO无疑是最显着和鼓舞人心的。NIO的出现事实上意味着Java虚拟机的性能比以前的版本有了较大的飞跃。在以前的JVM的版本中,代码的执行效率不高(在最原始的版本中Java是解释执行的语言),用Java编写的应用程序通常所消耗的主要资源就是CPU,也就是说应用系统的瓶颈是CPU的计算和运行能力。在不断更新的Java虚拟机版本中,通过动态编译技术使得Java代码执行的效率得到大幅度提高,几乎和操作系统的本地语言(例如C/C++)的程序不相上下。在这种情况下,应用系统的性能瓶颈就从CPU转移到IO操作了。尤其是服务器端的应用,大量的网络IO和磁盘IO的操作,使得IO数据等待的延迟成为影响性能的主要因素。NIO的出现使得Java应用程序能够更加紧密地结合操作系统,更加充分地利用操作系统的高级特性,获得高性能的IO操作。
JIT Compiler(Just-in-time Compiler) 即时编译 最早的Java建置方案是由一套转译程式(interpreter),将每个Java指令都转译成对等的微处理器指令,并根据转译后的指令先后次序依序执行,由于一个Java指令可能被转译成十几或数十几个对等的微处理器指令,这种模式执行的速度相当缓慢。 针对这个问题,业界首先开发出JIT(just in time)编译器。当Java执行runtime环境时,每遇到一个新的类别(class:类别是Java程式中的功能群组),类别是Java程式中的功能群组-JIT编译器在此时就会针对这个类别进行编译(compile)作业。经过编译后的程式,被优化成相当精简的原生型指令码(native code),这种程式的执行速度相当快。花费少许的编译时间来节省稍后相当长的执行时间,JIT这种设计的确增加不少效率,但是它并未达到最顶尖的效能,因为某些极少执行到的Java指令在编译时所额外花费的时间可能比转译器在执行时的时间还长,针对这些指令而言,整体花费的时间并没有减少。 基于对JIT的经验,业界发展出动态编译器(dynamic compiler),动态编译器仅针对较常被执行的程式码进行编译,其余部分仍使用转译程式来执行。也就是说,动态编译器会研判是否要编译每个类别。动态编译器拥有两项利器:一是转译器,另一则是JIT,它透过智慧机制针对每个类别进行分析,然后决定使用这两种利器的哪一种来达到最佳化的效果。动态编译器针对程式的特性或者是让程式执行几个循环,再根据结果决定是否编译这段程式码。这个决定不见得绝对正确,但从统计数字来看,这个判断的机制正确的机会相当高。事实上,动态编译器会根据“历史资料”做决策,所以程式执行的时间愈长,判断正确的机率就愈高。以整个结果来看,动态编译器产生的程式码执行的速度超越以前的JIT技术,平均速度可提高至50%。
D. Java代码的静态编译和动态编译中的问题是什么
Java代码正常是静态编译成字节码,由对应平台的JVM加载执行,静态编译无法动态扩展功能。动态编译有两种方式实现:
从源码编译,需要调用Java Compiler,程序需要运行于JDK(而不是JRE)之上。
动态字节码生成技术(如CGLib、ASM)创建类。
动态编译可以简化代码,增强类功能,但也带来了代码复杂度,线上不易维护。
E. 什么是即时编译
JIT(just-in-time compilation)指计算机领域里,即时编译也被成为动态翻译,是一种通过在运行时将字节码翻译为机器码,从而改善字节码编译语言性能的技术。即时编译前期的两个运行时理论是字节码编译和动态编译。
在编译为字节码的系统如 Limb 编程语言,Smalltalk, UCSD P-System, Perl, GNU CLISP, 和 Java 的早期版本中, 源代码被翻译为一种中间表示即字节码。 字节码不是任何特定计算机的机器码, 它可以在多种计算机体系中移植。字节码被解释着运行在虚拟机里。
动态编译环境是一种在执行时使用编译器的编译环境。 例如, 多数 Common Lisp 系统有一个编译函数,他可以编译在运行时创建的函数。
F. 软件工程和数字媒体技术哪个专业比较好
软件工程和数字媒体技术比软件工程的培养要求更严格、就业前景更广,数字媒体技术核心课程更齐全。
一、培养要求
1、数字媒体技术:数字媒体技术要求学生掌握数字媒体技术相关专业理论与专业技能,具有较高艺术欣赏水准与创意思维、较强工科创新设计与实践开发能力。培养要求更宽松。
2、软件工程:软件工程要求学生掌握掌握 计算科学基础理论、软件工程专业的基础知识及应用知识,具有软件开发能力以及软件开发实践 的初步经验和项目组织的基本能力。培养要求更严格。
二、核心课程
1、数字媒体技术:数字媒体技术的核心课程有C语言、面向对象程序设计、数字媒体技术概论、程序设计、数据结构、计算机图形学、数据可视化、影视后期与特效技术、数字图像处理、人机交互技术、虚拟现实技术、人工智能与新媒体、游戏架构与技术基础。
移动游戏技术、Unity应用开发、数字媒体产业概论、动画设计原理、三维动画技术、Maya基础与建模等。核心课程更齐全。
2、软件工程:软件工程的核心课程有程序设计语言、数据结构、离散数学、操作系统、编译技术、软件工程概论、统一建模语言、软件体系结构、软件需求、软件项目管理。
离散数学、数据结构、算法分析、面向对象程序设计、现代操作系统、数据库原理与实现技术、编译原理、软件工程、软件项目管理、计算机安全等课程等。核心课程更缺失。
三、就业前景
1、数字媒体技术:数字媒体技术可到互联网企业、文化传播机构、新闻传媒或融媒体机构、影视、广告或动漫公司、游戏或软件公司、教育与培训机构、机关事业单位等相关岗位,从事信息内容或交互平台的设计与开发及项目管理等工作,或自主创业。就业前景更窄。
2、软件工程:软件工程可以从事各级各类企事业单位的办公自动化处理、计算机安装与维护、网页制作、计算机网络和专业服务器的维护管理和开发工作、动态商务网站开发与管理、软件测试与开发及计算机相关设备的商品贸易等方面的有关工作。就业前景更广。
参考资料来源:
网络——数字媒体技术
网络——软件工程
G. 动态链接,静态链接 动态编译,静态编译 动态链接库,静态链接库 这些两两间的区别是什么呢
有点儿乱……,分数少简单扼要的说说吧。
————————————
首先,传统的编译,也就是静态编译是把 源文件 翻译成目标文件,这个是一次性过程,也就是你所谓的静态编译。
后来的Java和.NET等语言,首先编译成中间形式,然后运行过程中根据需要编译成本地代码(注意这个过程不是一次性的,下次运行重新编译),这个就是JIT(即时编译)技术,从即时编译发展出了动态编译技术
————————————
(传统的)编译完成后,像C/C++、Fortran、汇编等语言,可以把多个目标文件合并到一个库文件中,这个就是静态库。比如常说的库函数printf就是libc里面的函数。
如果有了启动函数(main),main里面使用了printf,就可以通过静态链接技术,从libc中提取出printf所在的文件加入到可执行文件中,如果printf还需要其它函数,就继续搜索并加入列表,直到形成一个闭包。这个就是静态链接。
可是静态链接有个明显的缺点,如果每个程序都需要printf,那么printf这个函数的代码就会同时存在在每个程序中,这样也太占地方了吧。所以发明了动态连接技术,其实有两种形式。无论哪一种,都是首先记录下需要调用printf这个函数以及所在的动态库,等到运行的时候再加载动态库,从动态库中找到真正的printf去执行。
由于,动态链接技术需要一些额外的信息,传统的静态库是不具备的,这些额外信息主要是重复加载和卸载时所需要的一些代码,因此需要动态链接库。
H. 什么是虚拟化技术虚拟化技术有哪些分类和方法
要了解详情,请加我的号,或照片上有我的照片,我们私聊。
可以免费试用的哦!!!!!!!!!
自从虚拟化提出以后,至今虚拟化技术分类有很多,方法也有很多,下面来一起了解下什么是虚拟化技术,及分类和方法。
当今发达国家在设计、制造、加工技术等方面已经达到相当自动化的水平,其产品设计普遍采用CAD、CAM、CAE和计算机仿真等手段,企业管理也已采用了科学的规范化的管理方法和手段,目前其主要从制造系统自动化方面寻找出路,为此提出了一系列新的制造系统,如敏捷制造、并行工程、计算机集成制造系统等。近些年,从虚拟机的大量部署到成功案例逐渐涌现,越来越多的制造企业开始关注虚拟化技术给优化IT基础架构,推动业务创新带来的启发,希望将其与业务相结合,找到掌握新技术、革新先进制造系统和先进制造模式的方法。虚拟化目前应用于制造业信息化主要体现在IT整合和节约成本,在其他方面很少,而实际上由于虚拟化技术的特点,其应用价值可以在远程办公、虚拟制造、工业控制等制造业相关领域都能得到体现。本文主要对虚拟化技术及其在制造业的应用现状进行综述,提出虚拟化在制造业的应用框架,为相关人员提供该领域的应用研究进展与发展趋势方面的介绍。
1 虚拟化技术
虚拟化是指为运行的程序或软件营造它所需要的执行环境,在采用虚拟化技术后,程序或软件的运行不再独享底层的物理计算资源,它只是运行在一个完全相同的物理计算资源中,而底层的影响可能与之前所运行的计算机结构完全不同。虚拟化的主要目的是对IT基础设施和资源管理方式的简化。虚拟化的消费者可以是最终用户、应用程序、操作系统、访问资源或与资源交互相关的其他服务。由于虚拟化能降低消费者与资源之间的耦合程度,消费者不再依赖于资源的特定实现,因此在对消费者的管理工作影响最小的基础上,可以通过手工、半自动、或者服务级协定(SLA)等来实现对资源的管理。
1.1 虚拟化的分类
从虚拟化的目的来看,虚拟化技术主要分为以下几个大类:
(1)平台虚拟化(Platform Virtualization),它是针对计算机和操作系统的虚拟化,又分成服务器虚拟化和桌面虚拟化。服务器虚拟化是一种通过区分资源的优先次序,并将服务器资源分配给最需要它们的工作负载的虚拟化模式,它通过减少为单个工作负载峰值而储备的资源来简化管理和提高效率。桌面虚拟化是为提高人对计算机的操控力,降低计算机使用的复杂性,为用户提供更加方便适用的使用环境的一种虚拟化模式。平台虚拟化主要通过CPU虚拟化、内存虚拟化和I/O接口虚拟化来实现。
(2)资源虚拟化(Resource Virtualization),针对特定的计算资源进行的虚拟化,例如,存储虚拟化、网络资源虚拟化等。存储虚拟化是指把操作系统有机地分布于若干内外存储器,两者结合成为虚拟存储器。网络资源虚拟化最典型的是网格计算,网格计算通过使用虚拟化技术来管理网络上的数据,并在逻辑上将其作为一个系统呈现给消费者,它动态地提供了符合用户和应用程序需求的资源,同时还将提供对基础设施的共享和访问的简化。当前,有些研究人员提出利用软件代理技术来实现计算网络空间资源的虚拟化,如Gaia,Net Chaser[21],Spatial Agent。
(3)应用程序虚拟化(Application Virtualization),它包括仿真、模拟、解释技术等。Java 虚拟机是典型的在应用层进行虚拟化。基于应用层的虚拟化技术,通过保存用户的个性化计算环境的配置信息,可以实现在任意计算机上重现用户的个性化计算环境。服务虚拟化是近年研究的一个热点,服务虚拟化可以使业务用户能按需快速构建应用的需求,通过服务聚合,可屏蔽服务资源使用的复杂性,使用户更易于直接将业务需求映射到虚拟化的服务资源。现代软件体系结构及其配置的复杂性阻碍了软件开发生命周期,通过在应用层建立虚拟化的模型,可以提供最佳开发测试和运行环境。
(4)表示层虚拟化。在应用上与应用程序虚拟化类似,所不同的是表示层虚拟化中的应用程序运行在服务器上,客户机只显示应用程序的UI界面和用户操作。表示层虚拟化软件主要有微软的Windows 远程桌面(包括终端服务)、Citrix Metaframe Presentation Server和Symantec PcAnywhere等。
1.2 虚拟化的方法
通常所说的虚拟化主要是指平台虚拟化,它通过控制程序隐藏计算平台的实际物理特性,为用户提供抽象的、统一的、模拟的计算环境。通常虚拟化可以通过指令级虚拟化和系统级虚拟化来实现。
1.2.1 指令级虚拟化方法
在指令集层次上实现虚拟化,即将某个硬件平台上的二进制代码转换为另一个平台上的二进制代码,实现不同指令集间的兼容,也被称作“二进制翻译”。二进制翻译是通过仿真来实现的,即在一个具有某种接口和功能的系统上实现另一种与之具有不同接口和功能的系统。二进制翻译的软件方式,它可以有3 种方式实现:解释执行、静态翻译、动态翻译。
近年来,最新的二进制翻译系统的研究主要在运行时编译、自适应优化方面,由于动态翻译和执行过程的时间开销主要包括四部分:即磁盘访问开销、存储访问开销、翻译和优化开销、目标代码的执行开销,所以要提高二进制翻译系统的效率主要应减少后3个方面的开销。目前典型的二进制翻译系统主要有Daisy/BOA、Crusoe、Aeries、IA-32EL、Dynamo 动态优化系统和JIT编译技术等。
1.2.2 系统级虚拟化方法
系统虚拟化是在一台物理机上虚拟出多个虚拟机。从系统架构看,虚拟机监控器(VMM)是整个虚拟机系统的核心,它承担了资源的调度、分配和管理,保证多个虚拟机能够相互隔离的同时运行多个客户操作系统。系统级虚拟化要通过CPU虚拟化、内存虚拟化和I/O虚拟化实现。
(1)CPU虚拟化
CPU虚拟化为每个虚拟机提供一个或多个虚拟CPU,多个虚拟CPU分时复用物理CPU,任意时刻一个物理CPU只能被一个虚拟CPU使用。VMM必须为各虚拟CPU合理分配时间片并维护所有虚拟CPU的状态,当一个虚拟CPU的时间片用完需要切换时,要保存当前虚拟CPU的状态,将被调度的虚拟CPU的状态载入物理CPU。X86 的CPU虚拟化方法主要有:二进制代码动态翻译(dynamic binary translation)、半虚拟化(para-virtualization)和预虚拟化技术。为了弥补处理器的虚拟化缺陷,现有的虚拟机系统都采用硬件辅助虚拟化技术。CPU虚拟化需要解决的问题是:①虚拟CPU的正确运行,虚拟CPU正确运行的关键是保证虚拟机指令正确执行,各虚拟机之间不互相影响,即指令的执行结果不改变其他虚拟机的状态,目前主要是通过模拟执行和监控运行;②虚拟CPU的调度。虚拟CPU的调度是指由VMM决定当前哪一个虚拟CPU实际在物理CPU上运行,保证虚拟机之间的隔离性、虚拟CPU的性能、调度的公平。虚拟机环境的调度需求是要充分利用CPU资源、支持精确的CPU分配、性能隔离、考虑虚拟机之间的不对等、考虑虚拟机之间的依赖。常见的CPU调度算法有BVT、SEDF、CB等。
(2)内存虚拟化
VMM通常采用分块共享的思想来虚拟计算机的物理内存。VMM将机器的内存分配给各个虚拟机,并维护机器内存和虚拟机内存之间的映射关系,这些内存在虚拟机看来是一段从地址0 开始的、连续的物理地址空间。在进行内存虚拟化后,内存地址将有机器地址、伪物理地址和虚拟地址三种地址。在X86 的内存寻址机制中,VMM能够以页面为单位建立虚拟地址到机器地址的映射关系,并利用页面权限设置实现不同虚拟机间内存的隔离和保护。为了提高地址转换的性能,X86 处理器中加入TLB,缓存已经转换过的虚拟地址,在每次虚拟地址空间切换时,硬件自动完成切块TLB。为了实现虚拟地址到物理地址的高效转换,通常采取复合映射的思想,通过MMU半虚拟化和影子页表来实现页表的虚拟化。虚拟机监控器的数据不能被虚拟机访问,因此需要一种隔离机制,这种隔离机制主要通过修改客户操作系统或段保护来实现。内存虚拟化的优化机制,包括按需取页、虚拟存储、内存共享等。
(3)I/O虚拟化
由于I/O设备具有异构性强,内部状态不易控制等特点,VMM系统针对I/O设备虚拟化有全虚拟化、半虚拟化、软件模拟和直接I/O访问等设计思路。近年来,更多的学者将I/O虚拟化的研究放在共享的网络设备虚拟化研究,提出将IOVM结构映射到多核心服务器平台。I/O设备除了增加吞吐量和固有的并行数据流、联系串行特性以及基于分组的协议外,还应该考虑到传统的PCI 兼容的PCI Express的硬件,建立相应的总线适配器,以弥补象单一主机无专门的驱动程序时的需要。有些研究人员专注于外存储虚拟化的研究,提出让存储虚拟化系统上的SCSI目标模拟器运行在SAN上,存储动态的目标主机的物理信息,并使用映射表方法来修改SCSI命令地址,使用位图的技术来管理可用空间等思想。存储虚拟化系统应提供诸如逻辑卷大小、各种功能、数据镜像和快照,并兼容集群主机和多个操作系统。由于外存储虚拟化能全面提升存储区域网络的服务质量,而带外虚拟化与带内虚拟化相比具有性能高和扩展性好等优点,通过运用按序操作、Redo日志以及日志完整性鉴别,设计基于关系模型的磁盘上虚拟化元数据组织方式,可以形成一致持久的带外虚拟化系统。
1.3 虚拟化的管理
虚拟化的管理主要指多虚拟机系统的管理,多虚拟机系统是指在对多计算系统资源抽象表示的基础上,按照自己的资源配置构建虚拟计算系统,其主要包括虚拟机的动态迁移技术和虚拟机的管理技术。
(1)虚拟机之间的迁移
将虚拟化作为一种手段管理现有的资源和加强其在网络计算的利用率,通过构建分布式可重构的虚拟机,必要时在物理服务器运行时迁移服务。通过移动代理技术、分布式虚拟机等提高资源利用率和服务可用性,通过寻找服务最优的策略在可重构和分布式虚拟机上迁移。为了将虚拟机运行的操作系统与应用程序从一个物理结点迁移到另外一个运行结点,同时保持客户操作系统和应用程序不受干扰,有些研究者提出以数据为中心的可迁移的虚拟运行环境,使得用户操作环境实现异地迁移、无缝重构;
也有研究人员提出程序执行环境的动态按需配置机制。在跨物理服务器迁移虚拟机,进行自动化的虚拟服务器的管理,必须考虑高层次的服务质量要求和资源管理成本。有些研究人员提出了通过管理程序控制的方法,以支持移动IP的实时迁移虚拟机在网络上,使虚拟机实时迁移其分布计算资源,从而改善迁移性能,降低网络恢复延迟,提供高可靠性和容错。有些研究机构通过设计一个通用的硬件抽象层,实现多个虚拟机的移植,具有高效率执行环境中的移动设备。虚拟机的迁移步骤一般有启动迁移、内存迁移、冻结虚拟机、虚拟机恢复执行。
(2)虚拟机的管理
对于多虚拟机来说,一个非常重要的方面是减少用户对动态的和复杂的物理设备的管理和维护,通过软件和工具来实现任务管理。当前典型的多虚拟机服务器管理软件是Virtual Infrastructure,它通过Virtual Center管理服务器的虚拟机池,通过VMotion完成虚拟机的迁移,通过VMFS管理多虚拟机文件系统。其次,Parallax 是针对Xen 的多虚拟机管理器,它通过采用消除写共享,增强客户端的缓存等方式并利用模板映像来建立整个系统;同时使用快照(snapshot)以及写时复制(-on-write)机制来实现块级共享,并使用副本来保证可用性。虚拟机监控器直接控制parallax 使用的物理盘,它们运行物理设备驱动器,并给虚拟磁盘镜像VDI 的本地虚拟机提供一个普通的块接口。
2 虚拟化在制造业信息化中的应用
2.1 虚拟化在制造业信息化中的应用框架
当今制造业正朝着精密化、自动化、柔性化、集成化、网络化、信息化和智能化的方向发展,在这种趋势下,诞生了许多先进制造技术和先进制造模式。这些先进制造技术和先进制造模式要求现有的IT基础设施能提供更高的计算服务水平,因此在制造业信息化中,需要建立以虚拟化为导向的资源分配体系结构,提供客户驱动的服务管理和计算风险管理,维持以服务水平协议(SLA)为导向的资源分配体系。虚拟化在制造业信息化中主要用于集中IT管理、应用整合、工业控制、虚拟制造等。
处在最底层的是制造业企业的虚拟计算资源池(VirtualCluster),它由多台物理服务器(PhysicsMachine)形成,各物理服务器上运行着虚拟化软件(VMM),虚拟化软件上运行着完成各种任务需求的虚拟机,虚拟计算资源池的虚拟化管理软件(VMS)为IT环境提供集中化、操作自动化、资源优化的功能,可以快速部署向导和虚拟机模板。虚拟计算资源池中的虚拟机将不同类型的客户操作系统(Guest OS)和运行其上的数据层、服务层应用程序(App)封装在一起,形成一个企业协同设计制造的完整系统,为表示层的用户提供多种形态的数据处理和显示功能。在图1 的框架中,虚拟计算资源池的动态资源调度(DRS)模块可以跨越物理机不间断地监控资源利用率,并根据反映业务需要和不断变化的优先级的预定规则,在多个虚拟机之间分配可用资源。在制造业信息化中,集中IT管理、应用整合、工业控制、虚拟制造等多种应用需求都将以各种服务的形式被封装到了虚拟机中,例如制造任务协同服务、资源管理服务、信息访问服务、WWW服务、工业控制服务、应用系统集成服务、数据管理服务、高效能计算服务、工具集服务等;同时支撑所有应用需求的数据库也被封装到了虚拟机中,例如企业模型数据库、制造资源数据库、产品模型数据库、专业知识数据库、用户信息数据库等。虚拟化特有的优点使它能确保所有虚拟机中的关键业务连续可靠地运行。
2.2 虚拟化在制造业信息化应用框架中的作用
虚拟化在制造业信息化中的应用主要有:
I. Cpython是什么PyPy是什么Python和这两个东西有什么关系
CPython:是用C语言实现Pyhon,是目前应用最广泛的解释器。最新的语言特性都是在这个上面先实现,基本包含了所有第三方库支持,但是CPython有几个缺陷,一是全局锁使Python在多线程效能上表现不佳,二是CPython无法支持JIT(即时编译),导致其执行速度不及Java和Javascipt等语言。于是出现了Pypy。
Pypy:是用Python自身实现的解释器。针对CPython的缺点进行了各方面的改良,性能得到很大的提升。最重要的一点就是Pypy集成了JIT。但是,Pypy无法支持官方的C/Python API,导致无法使用例如Numpy,Scipy等重要的第三方库。这也是现在Pypy没有被广泛使用的原因吧。
而PyPy与CPython的不同在于,别的一些python实现如CPython是使用解释执行的方式,这样的实现方式在性能上是很凄惨的。而PyPy使用了JIT(即时编译)技术,在性能上得到了提升。