没有合适的资源?快使用搜索试试~ 我知道了~
深入JVM即时编译器JIT,优化Java编译
需积分: 0 0 下载量 130 浏览量
2023-04-12
19:11:57
上传
评论
收藏 963KB DOCX 举报
温馨提示
试读
13页
说到编译,我猜你一定会想到 .java 文件被编译成 .class 文件的过程,这个编译我们一般称为前端编译。Java 的编译和运行过程非常复杂,除了前端编译,还有运行时编译。由于机器无法直接运行 Java 生成的字节码,所以在运行时,JIT 或解释器会将字节码转换成机器码,这个过程就叫运行时编译。
资源推荐
资源详情
资源评论
深入 JVM 即时编译器 JIT,优化 Java 编译
说到编译,我猜你一定会想到 .java 文件被编译成 .class 文件的过程,这个编译我们一般
称为前端编译。Java 的编译和运行过程非常复杂,除了前端编译,还有运行时编译。由于
机器无法直接运行 Java 生成的字节码,所以在运行时,JIT 或解释器会将字节码转换成机
器码,这个过程就叫运行时编译。
类文件在运行时被进一步编译,它们可以变成高度优化的机器代码,由于 C/C++ 编译器的
所有优化都是在编译期间完成的,运行期间的性能监控仅作为基础的优化措施则无法进行,
例如,调用频率预测、分支频率预测、裁剪未被选择的分支等,而 Java 在运行时的再次编
译,就可以进行基础的优化措施。因此,JIT 编译器可以说是 JVM 中运行时编译最重要的
部分之一。
然而许多 Java 开发人员对 JIT 编译器的了解并不多,不深挖其工作原理,也不深究如何检
测应用程序的即时编译情况,线上发生问题后很难做到从容应对。今天我们就来学习运行时
编译如何实现对 Java 代码的优化。
类编译加载执行过程
在这之前,我们先了解下 Java 从编译到运行的整个过程,为后面的学习打下基础。请看下
图:
类编译
在编写好代码之后,我们需要将 .java 文件编译成 .class 文件,才能在虚拟机上正常运行
代码。文件的编译通常是由 JDK 中自带的 Javac 工具完成,一个简单的 .java 文件,我们
可以通过 javac 命令来生成 .class 文件。
下面我们通过 javap 反编译来看看一个 class 文件结构中主要包含了哪些信息:
看似一个简单的命令执行,前期编译的过程其实是非常复杂的,包括词法分析、填充符号表、
注解处理、语义分析以及生成 class 文件,这个过程我们不用过多关注。只要从上图中知道,
编译后的字节码文件主要包括常量池和方法表集合这两部分就可以了。
常量池主要记录的是类文件中出现的字面量以及符号引用。字面常量包括字符串常量(例如
String str=“abc”,其中"abc"就是常量),声明为 final 的属性以及一些基本类型(例如,范
围在 -127-128 之间的整型)的属性。符号引用包括类和接口的全限定名、类引用、方法引
用以及成员变量引用(例如 String str=“abc”,其中 str 就是成员变量引用)等。
方法表集合中主要包含一些方法的字节码、方法访问权限(public、protect、prviate 等)、
方法名索引(与常量池中的方法引用对应)、描述符索引、JVM 执行指令以及属性集合等。
类加载
当一个类被创建实例或者被其它对象引用时,虚拟机在没有加载过该类的情况下,会通过类
加载器将字节码文件加载到内存中。
不同的实现类由不同的类加载器加载,JDK 中的本地方法类一般由根加载器(Bootstrp loader)
加载进来,JDK 中内部实现的扩展类一般由扩展加载器(ExtClassLoader )实现加载,而程
序中的类文件则由系统加载器(AppClassLoader )实现加载。
在类加载后,class 类文件中的常量池信息以及其它数据会被保存到 JVM 内存的方法区中。
类连接
类在加载进来之后,会进行连接、初始化,最后才会被使用。在连接过程中,又包括验证、
准备和解析三个部分。
验证:验证类符合 Java 规范和 JVM 规范,在保证符合规范的前提下,避免危害虚拟机安
全。
准备:为类的静态变量分配内存,初始化为系统的初始值。对于 final static 修饰的变量,
直接赋值为用户的定义值。例如,private final static int value=123,会在准备阶段分配内存,
并初始化值为 123,而如果是 private static int value=123,这个阶段 value 的值仍然为 0。
解析:将符号引用转为直接引用的过程。我们知道,在编译时,Java 类并不知道所引用的
类的实际地址,因此只能使用符号引用来代替。类结构文件的常量池中存储了符号引用,包
括类和接口的全限定名、类引用、方法引用以及成员变量引用等。如果要使用这些类和方法,
就需要把它们转化为 JVM 可以直接获取的内存地址或指针,即直接引用。
类初始化
类初始化阶段是类加载过程的最后阶段,在这个阶段中,JVM 首先将执行构造器 <clinit>
方法,编译器会在将 .java 文件编译成 .class 文件时,收集所有类初始化代码,包括静态
变量赋值语句、静态代码块、静态方法,收集在一起成为 <clinit>() 方法。
初始化类的静态变量和静态代码块为用户自定义的值,初始化的顺序和 Java 源码从上到下
剩余12页未读,继续阅读
资源评论
AE86Jag
- 粉丝: 43
- 资源: 18
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- pta题库答案c语言之排序4统计工龄.zip
- pta题库答案c语言之树结构7堆中的路径.zip
- pta题库答案c语言之树结构3TreeTraversalsAgain.zip
- pta题库答案c语言之树结构2ListLeaves.zip
- pta题库答案c语言之树结构1树的同构.zip
- 基于C++实现民航飞行与地图简易管理系统可执行程序+说明+详细注释.zip
- pta题库答案c语言之复杂度1最大子列和问题.zip
- 三维装箱问题(Three-Dimensional Bin Packing Problem,3D-BPP)是一个经典的组合优化问题
- 以下是一些关于Linux线程同步的基本概念和方法.txt
- 以下是一个简化的示例,它使用pygame库来模拟烟花动画的框架.txt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功