标签:
编译器
Java是编译型语言,按照编译的时期不同,编译器可分为:
前端编译器做了许多针对编码过程的优化措施来改善程序员的编码风格和提高编码效率,如相当多新生的Java语法特性,都是靠前端编译器的“语法糖”来实现 的;而虚拟机设计团队把性能的优化集中到了JIT编译器,这样可以让那些不是有Javac产生的Class文件也同样能享受到编译器优化所带来的好处。
Java程序最初是通过解释器(Interpreter)进行解释执行的,后来在部分的商用虚拟机(Sun HotSpot、IBM J9)中,当虚拟机发现某个方法或代码块的运行特别频繁,就会把这些代码认定为“热点代码(Hot Spot Code)”,为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器 称为即时编译器(Just In Time Compiler)。
尽管并不是所有的Java虚拟机都采用解释器和编译器并存的架构,但许多主流的商用虚 拟机如HotSpot、J9等都同时包含解释器和编译器:当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。当程序运 行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。
HotSpot虚拟机中内置了两个即时编译器分别是Client Compiler和Server Compiler,或者分别称为C1和C2。但无论是采用的编译器是Client Compiler还是Server Compiler,解释器和编译器搭配使用的方式在虚拟机中都被称为“混合模式(Mixed Mode)”,不过可以通过参数-Xint强制虚拟机运行于“解释模式(Interpreted Mode)”,此时编译器完全不介入工作,全部代码都使用解释方式执行;另外也可以使用参数-Xcomp强制虚拟机运行于“编译模式(Compiled Mode)”,这时将优先采用编译方式执行,但解释器仍然要在编译无法进行的情况下介入执行。
编译优化
由于即时编译器编译本地代码需要占用程序运行时间,要编译出优化程度更高的代码,所花 费的时间就可能越长;而且想要编译出优化程度更高的代码,解释器可能还要替编译器收集性能监控信息,这对解释执行的速度也有影响。为了在程序启动响应速度 和运行效率之间达到最佳平衡,HotSpot虚拟机将会逐渐启用分层编译策略,分层编译的概念在JDK1.6时期出现,后来一直处于改进阶段,最终在 JDK1.7的Server模式虚拟机中作为默认编译策略开启。分层编译根据编译器编译、优化的规模与耗时,划分出不同的编译层次,其中包括:
实施分层编译后,Client Compiler和Server Compiler将会同时工作,许多代码都可能会被多次编译,用Client Compiler获取更高的编译速度,用Server Compiler来获取更好的编译质量,在解释执行的时候也无需再承担收集性能监控信息的任务。
在运行过程中被即时编译器编译的“热点代码”有两类:被多次调用的方法和被多次执行的循环体,但不管是那种都是以整个方法作为编译对象的,因为这种编译方式发生在方法的执行过程中,因此be形象地称为栈上替换(On Stack Replacement,OSR)。
要知道一段代码是不是热点代码,是不是需要触发即时编译,这个行为称为热点探测,目前主要的热点探测判定方式有两种:
HotSpot虚拟机中使用的是第二种——基于计数器的热点探测方法,因此它为每个方法准备了两个计数器:方法调用计数器和回边计数器。在确定了虚拟机运行参数的前提下,这两个计数器都有一个确定的阈值,当计数器超过了阈值,就会触发JIT编译。
方法内联编译器优化重要优化手段,因为它不仅消除了方法调用成本,更重要的意义是它是其他优化手段的基础,因为只有把代码集中了才能更方便和有效地进行优化。如果想查看即时编译的情况可以使用参数:-XX:+PrintCompilation。
JVM内存模型
主内存和工作内存
内存间交互操作:java内存模型定义了8种原子操作,jvm要报保证每一个操作为原子操作:
如果要把一个变量从主内容复制到工作内存,那就要顺序地执行read和load操作,如果把变量从工作内存同步回主内存,就要顺序地执行store和write操作。注意java内存模型只要求上述两个操作必须按顺序执行,而没有保证是连续执行。
以上8中操作必须满足的规则:
volatile
volatile--java虚拟机提供的轻量级的同步机制。2个重要特性。1是保证此变量对所有线程可见,2是禁止指令重排序优化,
性能方面:volatile的读操作的性能消耗与普通变量几乎没有差别,但是写操作则可能会慢一些,因为他需要在本地代码中插入许多内存屏蔽指令来保证处理器不发生乱序执行。
以下场景仍需要同步:
原子性、可见性和有序性(总结):
逃逸分析:当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。(来自互联网)
现行发生原则
指的是java内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到,“影响”包括修改了内存中共享变量的值、发送了消息、调用了方法等。
java内存模型下的“天然的”先行发生关系:
线程状态
线程安全的实现方法
锁优化
标签:
原文地址:http://www.cnblogs.com/shangxiaofei/p/4505816.html