`

JVM学习笔记-程序优化与代码编译

    博客分类:
  • jvm
JVM 
阅读更多

1. Java 语言编译过程中比较有代表性的编译器:

1)  前端编译器:把 *.java 文件转变成 *.class 文件的过程,如 Sun Javac Eclipse JDT 中得增量式编译器。

2)  JIT 编译器:虚拟机的后端运行期编译器把字节码转化成机器码的过程,如 HotSpot VM C1 C2 编译器。

3)  AOT 编译器:静态提前编译器直接把 *.java 文件编译成本地机器代码的过程,如 GUN Compiler for the Java GCT )、 Excelsior JET

 

2. 在部分的商用虚拟机( Sun Hotspot IBM J9 )中, Java 程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁,就会把这些代码认定为“热点代码”,为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器。

 

3. 当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。当程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。当程序运行环境中内存资源限制较大,可以使用解释执行节约内存,反之可以使用编译执行来提升效率。

 

4. Hotspot 虚拟机中内置了两个即时编译器,称为 Client Compiler Server Compiler ,或者简称 C1 编译器和 C2 编译器。

 

5. 基于计数器的热点探测:采用这种方法的虚拟机会为每个方法建立计数器,统计方法的执行次数,如果执行次数超过一定的阀值就认为它是“热点方法”。

 

6. HotSpot 虚拟机中使用的是基于计数器的热点探测方法,因此它为每个方法准备了两个计数器:方法调用计数器和回边计数器。

 

7. 方法调用计数器:用于统计方法别调用的次数,默认阀值在 Client 模式下是 1500 次,在 Server 模式下 10000 次,这个阀值可以通过虚拟机参数 -XX:CompileThreshold 来人工设定。

 

8. 当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器就会减少一半,这个过程称为方法调用计数器的热度衰减,而这段时间就称为半衰周期,可以使用虚拟机参数 -XX:UseCounterDecay 来关闭热度衰减,另外可以使用 -XX:CounterHalfLifeTime 参数设置半衰周期的时间,单位是秒。

 

9. 回边计数器:用于统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令就称为“回边”。回边计数器没有计数热度衰减的过程,因此这个计数器统计的就是该方法循环执行的绝对次数。

 

10. Client Compiler 又称为 C1 ,只做少量性能开销比高的优化,它占用内存较少,适合于桌面交互式应用。在寄存器分配策略上, JDK6 以后采用的为线性扫描寄存器分配算法,在其他方面的优化主要有:方法内联、去虚拟化、冗余消除等。

1)  方法内联:对于 Java 类面向对象的语言,通常要调用多个方法来完成功能。执行时,要经历多次参数传递、返回值传递及跳转等,于是 C1 采取了方法内联的方式,即把调用到的方法的指令直接植入当前方法中。小于 -XX:MaxInlineSize=35 字节的函数指令直接植入 -XX:+PrintInlining 可以查看内联信息;如:

bar(){
     small();
} 
small(){
    ...Code;
}
->
bar(){
    ...Code;
}
 

2)  去虚拟化:去虚拟化是指在装载 class 文件后,进行类层次的分析,如发现类中的方法只提供一个实现类,那么对于调用了此方法的代码,也可进行方法内联,从而提升执行的性能。接口只有一个实现类时,直接植入实现方法指令;如:

execute(IFoo foo){foo.bar(Code)} ->execute(){Code}
 

3)  冗余消除:根据运行时状况进行代码折叠或消除,如:

if(true){Code}->Code
 

 

11. Server Compiler 又称为 C2 C2 采用了大量的传统编译优化技巧来进行优化,占用内存相对会多些,适合与服务器端的应用。寄存器分配策略上 C2 采用的为传统的图着色寄存器分配算法,由于 C2 会收集程序的运行信息,因此其优化的范围更多在于全局的优化。收集的信息主要有:分支的跳转 / 不跳转的频率、某条指令上出现过的类型、是否出现过空值、是否出现过异常。

1)  逃逸分析:当一个对象在方法里面被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中,这种行为称为方法逃逸。甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,这种行为称为线程逃逸。用户可以使用参数 -XX:+DoEscapeAnalysis 来手动开启逃逸分析。

2)  栈上分配:如果确定一个对象不会逃逸出方法之外,那让这个对象在栈上分配内存将会是一个很不错的主意,对象所占用的内存空间就可以随栈帧出栈而销毁。

3)  同步消除:线程同步本身就是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问,那这个变量的读写肯定就不会有竞争,对这个变量实施的同步措施也就可以消除掉。

4)  标量替换:如果把一个 Java 对象拆散,根据程序访问的情况,将其使用到的成员变量恢复原始类型来访问就叫做标量替换。如果逃逸分析证明一个对象不会被外部访问,并且这个对象可以被拆散的话,那程序真正执行的时候将可能不创建这个对象,而改为直接创建它的若干个被这个方法使用到的成员变量来代替。

出了 C1 C2 外,还有一种较为特殊的编译为: OSR On Stack Replace )。 OSR 编译和 C1 C2 最主要的不同点在于 OSR 编译只替换循环代码的入口,而 C1 C2 替换的是方法调用的入口,因此在 OSR 编译后会出现的现象是方法的整段代码被编译了,但只有在循环代码体部分才执行编译后的机器码,其他部分则仍然是解释执行方式。

0
1
分享到:
评论

相关推荐

    JVM学习笔记

    JVM学习笔记(一)--------基本结构 JVM学习笔记(二)----java代码编译和执行的整个过程 JVM学习笔记(三)---------内存管理和垃圾回收 JVM学习笔记(四)------内存调优

    java学习笔记 - 1

    1.java开发环境--java编译运行过程(常见面试题) 2.名词解释--JVM;JRE,JDK 3.配置环境变量 4.eclipse: 开发环境 开发步骤 注释

    jvm指令手册 +JVM必知必会,掌握虚拟机编译过程.rar

    Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行 《JVM必知必会》记录了对JVM的总结及学习笔记,详解...

    JVM教程之Java代码编译和执行的整个过程(二)

    主要介绍了JVM学习笔记第二篇,关于Java代码编译和执行的整个过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    java jdk8 学习笔记

    Java编译语言将Java代码编译成.class文件(只有一种形式),而C/C++语言将代码编译成01码,不同的操作系统的01码指令不同,这造成了不能跨平台,而Java将这个任务交给JVM,不同操作系统上的JVM将.class文件编译成不同...

    java7rt.jar源码-Java_JVM:这是我的JavaJVM学习笔记

    java7 rt.jar源码 ...来依次编译每一行代码解释为本地机器指令; 后者是通过 寻找热点代码 进行即时编译为本地机器指令; GC: 垃圾回收器 主要的三款商用虚拟机JVM: 1) HotSpot JVM 特点: 热点代码探索

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

     《Java JDK 7学习笔记》详细介绍了JVM、JRE、Java SE API、JDK与IDE之间的对应关系。必须要时从Java SE API的源代码分析,了解各种语法在Java SE API中如何应用。  《Java JDK 7学习笔记》将IDE操作纳为教学内容...

    net学习笔记及其他代码应用

    答:启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。 40.接口是否可...

    笔记 — JVM内存结构

    Java虚拟机(Java Virtual Machine,简称JVM),Java的“一处编译,处处运行”,就是因为Java程序编译成字节码文件后可以在任何计算机的JVM上执行,所以JVM是我们学习Java的重点之一。 JVM = 类加载器(classloader) + ...

    java基础学习笔记 java整合技术 java工具类.rar

    DOS操作 切换盘符: d: 进入文件夹:cd 文件夹名 命令提示: tab 一次性进入多个文件夹: cd\文件夹\文件夹 返回上级目录: cd … 进入当前目录: cd . ...java xx文件名(不要后缀) 运行编译后的java程序

    springboot学习思维笔记.xmind

    springboot学习笔记 spring基础 Spring概述 Spring的简史 xml配置 注解配置 java配置 Spring概述 Spring的模块 核心容器CoreContainer Spring-Core Spring-Beans ...

    Java学习笔记

    JAVA语言跨平台执行,它必须先编译后解释执行,它能提供程序运行(JVM)的虚拟环境,使程序代码独立于平台 JAVA吸收C和C++的优点,基础语法与C语言模式完全一样,容易掌握 JAVA健壮性高,它去掉指针、内存申请和释放...

    scala.rar学习笔记和心得

    Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。...Scala 源代码被编译成Java字节码,所以它可以运行于JVM之上,并可以调用现有的Java类库。

    Java学习笔记(一)

    程序代码经过编译之后转换成一种称为Java字节码的中间语言,Java虚拟机(JVM)将对字节码进行解释和运行。编译只进行一次,而解释在每次运行程序都会进行。编译后的字节码采用一种针对JVM优化过的机器码形式保存,...

    记录各种学习笔记(算法、Java、数据库、并发......).zip

    它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持Java的任何平台上无需重新编译即可运行,这得益于其独特的跨平台性,通过Java虚拟机(JVM)...

    关于学习笔记整理,包括Linux、Java、数据结构和算法,和一些IT工具的使用.zip

    它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持Java的任何平台上无需重新编译即可运行,这得益于其独特的跨平台性,通过Java虚拟机(JVM)...

    Golang学习笔记(一):缘起及一个不一样的HelloWorld

    Golang学习笔记(一):缘起及一个不一样的HelloWorld1 缘起2 安装go3 Hello World也是可以好好说道说道滴 :)3.1 编写hollo.go源代码3.2 hello.go代码说明3.3 执行程序3.4 编译程序4 结语 1 缘起 本人公司的项目后端...

    积分java源码-java-11:Java11OCP学习笔记

    类是使用javac程序编译的。 根据 Java 源文件的内容,编译会生成一个或多个类文件。 一个例子如下所示: javac TestClass . java 使用java程序执行 Java 类。 一个例子如下所示: java TestClass a b c Java 虚拟机 ...

Global site tag (gtag.js) - Google Analytics