草庐IT

读Java性能权威指南(第2版)笔记07_即时编译器上

躺柒 2023-03-28 原文

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. 僵尸代码的小规模重新编译,不会对大多数应用程序产生显著的影响

有关读Java性能权威指南(第2版)笔记07_即时编译器上的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. ruby - 即时确定方法的可见性 - 2

    我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust

  3. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  4. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  5. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  6. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  7. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  8. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

随机推荐