设为首页 加入收藏

TOP

读Java性能权威指南(第2版)笔记07_即时编译器上
2023-07-25 21:40:09 】 浏览:34
Tags:Java 能权威 笔记 07_ 时编译

1. 概览

1.1. 即时编译器是Java虚拟机的核心

1.1.1. just-in-time compiler,简称JIT compiler

1.1.2. 即时编译器会频繁地使用寄存器

1.2. 编译型语言

1.2.1. 程序是以二进制(编译后的)代码的形式发布的

1.2.1.1. 汇编代码是针对特定CPU的

1.2.1.2. 兼容的CPU可以执行同一个二进制文件

1.2.2. C++和Fortran

1.3. 解释型语言

1.3.1. 同样的程序源代码就可以在任何CPU上运行

1.3.2. 如PHP和Perl

1.4. 中间地带

1.4.1. 编译为一种中间的低级语言

1.4.1.1. Java字节码

1.4.1.2. 由JVM进一步编译成汇编语言

1.4.2. 利用了脚本语言的平台独立性和编译型语言的原生性能

1.4.3. 在代码执行时将其编译为平台相关的二进制代码

1.4.3.1. 是“即时”的

1.5. 热点编译

1.5.1. 只有一小部分代码会频繁执行,应用程序的性能则主要取决于这些代码执行的快慢

1.5.2. 关键代码被称为应用程序的热点

1.5.2.1. 这部分代码执行得越多,就说这部分代码越热

1.5.3. 只执行一次的代码,解释执行Java字节码会更快一点

1.5.4. 代码是频繁调用的方法或者迭代多次的循环,编译它就是值得的

2. 分层编译

2.1. 现在所有JVM都在使用的技术

2.2. -XX:-TieredCompilation标志

2.2.1. 默认值是true

2.3. 两种类型

2.3.1. client编译器

2.3.1.1. C1编译器1

2.3.2. server编译器

2.3.2.1. C2编译器2

2.4. 编译代码的时机

2.4.1. 基于程序会运行多长时间和程序的启动时间有多重要

2.4.2. C1编译器比C2编译器更早开始编译

2.4.3. 在代码执行的开始阶段,C1编译器的速度更快

2.4.4. C2编译器在等待时获得了信息,这些信息让C2编译器能够对编译后的代码进行更好的优化

3. 编译器标志

3.1. 代码缓存

3.1.1. 一种设定了最大值的系统资源

3.1.2. 影响JVM可以运行的编译后的代码总量

3.1.3. 最大值

3.1.3.1. -XX:ReservedCodeCacheSize=N

3.1.3.2. 默认240 MB

3.1.4. 初始大小

3.1.4.1. -XX:InitialCodeCacheSize=N

3.1.4.2. 默认2496 KB

3.2. Java 11中

3.2.1. 非方法代码(nonmethod code)

3.2.1.1. -XX:NonMethodCodeHeapSize=N

3.2.2. 性能分析代码(profiled code)

3.2.2.1. -XX:ProfiledCodeHeapSize=N

3.2.3. 非性能分析代码(nonprofiled code)

3.2.3.1. -XX:NonProfiledCodeHeapSize=N

3.3. 检查编译过程

3.3.1. 不是用来优化的,它不会提升应用程序的性能

3.3.2. -XX:+PrintCompilation标志

3.3.2.1. 默认为false

3.3.3. attributes字段由5个字符构成,表示正在编译的代码状态

3.3.3.1. %

3.3.3.1.1. 栈上替换(on-stack replacement,OSR)

3.3.3.2. s

3.3.3.2.1. 方法是同步的

3.3.3.3. !

3.3.3.3.1. 方法有异常处理器

3.3.3.4. b

3.3.3.4.1. 在阻塞模式下发生的编译

3.3.3.5. n

3.3.3.5.1. 原生方法封装时发生的编译

4. 分层编译级别

4.1. 如果没有额外的CPU周期可用,你能做的就是尽量缩减应用程序的大小

4.2. C1编译器有3个级别,所有总共有5个编译级别

4.2.1. 0

4.2.1.1. 解释代码

4.2.2. 1

4.2.2.1. 简单C1编译代码

4.2.3. 2

4.2.3.1. 受限C1编译代码

4.2.4. 3

4.2.4.1. 完全C1编译代码

4.2.5. 4

4.2.5.1. C2编译代码

4.3. C1编译器得到代码是如何使用的信息之后,会利用这些信息进行优化,然后才开始编译

4.4. 如果C2编译器队列已满,那么队列中的方法会被取出,在级别2上编译

4.5. 如果C1编译器队列已满,那么计划在级别3上编译的方法在等待编译的同时,可以进行级别4的编译

4.5.1. 它会被快速编译到级别2,然后转到级别4

4.6. 不重要的方法可以从级别2或者级别3开始编译

4.6.1. 它们本质上不那么重要,所以会回到级别1

4.7. 如果代码发生了逆优化,就会回到级别0

5. 逆优化(deoptimization)

5.1. 编译器不得不“撤销”之前的编译

5.1.1. JVM替换之前编译的代码的过程

5.2. 发生情况

5.2.1. 代码被丢弃(made not entrant)

5.2.2. 产生僵尸代码(made zombie)

5.3. 代码被丢弃的原因

5.3.1. 类和接口的工作方式

5.3.1.1. 逆优化对性能并没有太大影响

5.3.2. 分层编译的工作方式

5.3.2.1. 当代码被C2编译器编译时,JVM必须替换已经被C1编译器编译的代码

5.3.2.2. 它将旧代码标记为丢弃,并用逆优化机制替换为新编译的(更高效的)代码

5.3.2.3. 让代码变得更快

5.4. 逆优化僵尸代码

5.4.1. 僵尸代码的小规模重新编译,不会对大多数应用程序产生显著的影响

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇《分布式技术原理与算法解析》学.. 下一篇1.2复习了一下MySQL的索引

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目