一:两种解释器

JAVA字节码解释器:

java字节码===》c++代码==》硬编码。

首先.java文件编译成字节码,遍历每行的字节码指令,因为每个字节码指令的含义都是固定的所以可以根据每行字节码指令来转成c++代码调用,最后转成硬编码(机器码)来执行。

模板解释器:

由java字节码==》硬编码。可以从java字节码直接到硬编码。

模板解释器底层实现流程:

1)申请一块内存:可读可写可执行

2)将处理new字节码的硬编码(举个例子)拿过来,可以通过解析文件得到

3)将处理new字节码的硬编码写入申请的内存

4)申请一个函数指针,用这个函数指针执向这块内存

5)调用的时候,直接通过这个函数指针调用就可以了。

Mac中是无法使用JIT的!因为Mac无法申请一块可读可写可执行的内存块

二:三种运行模式

-Xint 纯字节码解释器

-Xcomp 纯模板解释器

-Xmixed 字节码解释器+模板解释器

默认是mixed,可以通过java -version查看

混合模式

纯字节码解释器

纯模板解释器:

三:三种运行模式的性能

1:-Xint 纯字节码解释器,  解释一行执行一行,其实属于解释执行了。如果代码多的话肯定效率不会太高。

2:-Xcomp 纯模板解释器,需要把.class编译成硬编码之后再执行,如果程序很大,启动时间耗时可能会较久。

3:-Xmixed 字节码解释器+模板解释器,所以现在都是混合模式的编译。刚启动的时候采用字节码解释器,这样只要解析执行启动相关的代码即可,等到程序运行一段时间之后,即时编译器收集到的代码越来越多就可以使用模板解释器提高运行效率。

2,3那个性能比较高,主要看程序的规模了。

四:模板解释器使用的硬编码谁来编译呢?编译后又是放在哪里呢?

即时编译器:属于JIT技术。

1)C1即时编译器。

c1编译器是client模式下的即时编译器。现在64bit机都是server模式了

(1)触发条件比C2宽松,需要收集的数据较少。

(2)编译的优化比较浅比如:基本运算在编译的时候运算掉了或这final 修饰的字符串的优化。

(3)c1编译器编译生成的代码执行效率比c2低些。

就算对其进行调优,性能的提升曲线也很平缓。

2)C2编译器

       c2编译器是server模式下的即时编译器。

(1)触发的条件比较严格,一般来说,程序运行一段时间以后触发。

(2)优化的比较深。比如编译的时候判断操作是否设计到堆栈,如果没有的话直接优化掉了。

(3)编译生成的代码执行效率比c1更高。

3) 混合编译

jdk6以前是没有混合编译的,后来根据两种编译器的使用场景组合起来使用进一步提升性能

程序运行初期触发c1编译器,程序运行一段之后触发c2编译器。

这里说明一点:

字节码解释器是解释执行的,和即时编译器无关。

模板解释器执行的硬编码就是即时编译器编译的。

即时编译触发的条件!

     硬编码在jvm中称为热点代码。

    触发即时编译的最小单位不是一个函数,而是一个代码块(for,while等)

    client模式下,默认值 1500。即一段代码执行1500次会触发即时编译。

    server模式下,默认值是10000。即一段代码执行10000次会触发即时编译。

热度衰减: 

    有一段代码执行了7000次,还有3001次触发即时编译,但是在一定时间内,这段代码没有被调用,这个次数会以两倍速递减变成3500,这时候就需要再执行6501次才会触发即时编译。这种就叫热度衰减。


补充知识点!!!!!!!

热机切冷故障。

热机:就是已经运行了一段时间的机器。

冷机:就是刚运行的机器。

问题:

当给已经运行了一段时间的热机集群中增加一个节点冷机的时候,冷机起到负载均衡的作用,但是会出现冷机一上线就会挂掉。

原因:

热机中有热点代码缓存,抗的并发更大,冷机中一边运行程序一边触发即时编译占用cpu。

解决方案:

冷机切流量,慢慢切,等到触发即时编译了就可以正常负载了。


热点代码缓存区,在方法区。这块也是调优需要调的地方,但是一般不动。

java -XX:+PrintFlagsFinal -version | grep CodeCacheSize

server 编译器模式下代码缓存大小则起始于 2496KB

client 编译器模式下代码缓存大小起始于 160KB

五:即时编译器是如何运行的

即时编译时通过VM_Thread线程执行的

1:将即时编译器任务写入队列

2:VM_THREAD从这个队列中读取任务并执行。

异步执行的。

可以查看编译线程有多少个?如果有必要可以调整这个大小。

java -XX:+PrintFlagsFinal -version | grep  CICompilerCount

六:如何理解java是半解释半编译型语言

1:javac 编译java文件,java运行

2:字节码解释器解释执行,模板解释器编译执行。

七:逃逸分析

逃逸:对象逃逸,直接解释逃逸不如直接说明不逃逸更直观。逃逸的话,对于对象如果是共享变量,返回值,参数,则对象是逃逸的,就是逃到了线程外,方法外。

对象不逃逸:对象的作用域是局部变量,对象就是不逃逸的。

-XX:+DoEscapeAnalysis//开始逃逸分析    -XX:-DoEscapeAnalysis//禁用

基于逃逸分析,JVM开发了三种优化技术:

栈上分配:

逃逸分析开启,栈上分配就是存在的,逃逸分析默认是开启的。我们可以测试下看栈上分配的存在。

我们在堆中创建20万个对象,如果堆里这个对象少于20个,说明有在栈上分配的。前提不会发生GC。

我们先测试只在堆上创建,我把逃逸分析关闭了。

   public static void main(String[] args) {
for (int i = 0; i <200000 ; i++) {
DriverDemo s1= new DriverDemo();
}
while (true);
}

执行之后,我们通过HSDB查看堆中创建了多少个对象。java -cp  sa-jdi.jar sun.jvm.hotspot.HSDB    。首先查找jvm线程。在HSDB中打开线程id.

看到堆里有20万个对象。说明此时没有发生栈上分配。

我们把逃逸分析打开再执行查看HSDB。此时堆中对象已经少于20万个了,所以出现了栈上分配。

标量替换:

标量:是不可拆分的变量,java中的基本数据类型就是标量的。

scalar replacement。Java中的原始类型无法再分解,可以看作标量(scalar);指向对象的引用也是标量;而对象本身则是聚合量(aggregate),可以包含任意个数的标量。如果把一个Java对象拆散,将其成员变量恢复为分散的变量,这就叫做标量替换。拆散后的变量便可以被单独分析与优化,可以各自分别在活动记录(栈帧或寄存器)上分配空间;原本的对象就无需整体分配空间了

聚合量:是可拆分的,就是引用数据类型。

锁消除:

锁消除是指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行削除。锁削除的主要判定依据来源于逃逸分析的数据支持,如果判断到一段代码中,在堆上的所有数据都不会逃逸出去被其他线程访问到,那就可以把它们当作栈上数据对待,认为它们是线程私有的,同步加锁自然就无须进行。

比如下面这段代码就会在编译的时候把同步锁去掉。

     synchronized (new Object()){
System.out.println("ddd");
}

JVM(八)执行引擎相关内容的更多相关文章

  1. jvm虚拟机---执行引擎子系统

    Java虚拟机只与Class文件相关联,它规定了Class文件应该具有的格式,而不论该文件是由什么语言编写并编译而来.所以,任何语言只要能够最终编译成符合Java虚拟机要求的Class文件,就可以运行 ...

  2. JVM调优一些相关内容

    JVM调优工具 Jconsole,jProfile,VisualVM Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪.详细说明参考这里 ...

  3. 【JVM第七篇】执行引擎

    写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 执行引擎是Java虚拟机中的核心组成部分. 执行引擎的作用就是解析虚拟机字节码指令, ...

  4. 一夜搞懂 | JVM 字节码执行引擎

    前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习字节码执行引擎? 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一 ...

  5. 执行引擎子系统——JVM之五

    一.JVM通过执行引擎来完成字节码的执行,在执行过程中JVM采用的是自己的一套指令系统,每个线程在创建后,都会产生一个程序计数器(pc)和栈(Stack). pc:存放了下一条将要执行的指令: Sta ...

  6. 深入理解java虚拟机(5)---字节码执行引擎

    字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...

  7. Java虚拟机执行引擎

    执行引擎 关于执行引擎相关的部分, 在之前的博文里 Java内存区域中已经有所提及. 回顾一下: 也只有几个概念, JVM方法调用和执行的基础数据结构是 栈帧, 是内存区域中 虚拟机栈中的栈元素, 每 ...

  8. 深入理解java:1.2. 字节码执行引擎

    执行引擎是Java虚拟机的核心组成部分之一. 首先,想想C++和Java在编译和运行时到底有啥不一样? 下图左边,C++发布的就是机器指令, 而下图右边Java发布的是字节码,字节码在运行时通过JVM ...

  9. JVM总结(五):JVM字节码执行引擎

    JVM字节码执行引擎 运行时栈帧结构 局部变量表 操作数栈 动态连接 方法返回地址 附加信息 方法调用 解析 分派 –“重载”和“重写”的实现 静态分派 动态分派 单分派和多分派 JVM动态分派的实现 ...

随机推荐

  1. C#中RDLC合并两个列的值

    使用 & 符号连接 =Fields!ID.Value & Fields!Name.Value

  2. Loki 初体验

    Loki 是什么 Loki 是 Grafana Lab开发的一套日志系统,使用Go语言实现.根据官方的介绍, Loki,高可用性,多租户的日志聚合系统,受到Prometheus的启发.它的设计非常经济 ...

  3. 常用java自带命令概览

    ref:http://www.hollischuang.com/archives/308 一.常用命令 jps: 查看本机的Java中进程信息. jstack: 打印线程的执行栈信息. jmap: 打 ...

  4. 手写一个简单的starter组件

    spring-boot中有很多第三方包,都封装成starter组件,在maven中引用后,启动springBoot项目时会自动装配到spring ioc容器中. 思考: 为什么我们springBoot ...

  5. [LeetCode]231. Power of Two判断是不是2\3\4的幂

    /* 用位操作,乘2相当于左移1位,所以2的幂只有最高位是1 所以问题就是判断你是不是只有最高位是1,怎判断呢 这些数-1后形成的数,除了最高位,后边都是1,如果n&n-1就可以判断了 如果是 ...

  6. LINUX五中IO模型

    阻塞IO模型 用户空间调用recvfrom命令 直到数据包到达且被复制到应用进程的缓冲区或发生错误时才返回,这个过程中 进程亦或线程一直处于等待阻塞状态. 2.非阻塞IO模型 用户空间调用内核指令re ...

  7. pxe过程和原理

    pxe过程和原理 概要 远程安装和启动操作系统 网卡固件支持pxe的接口,一般是有基本的ip/udp协议栈,支持dhcp, tftp协议:bios中可以设置通过pxe启动操作系统 启动过程,大致如下: ...

  8. ARM CPU的SVC模式

    关于ARM CPU模式中的SVC Arm中CPU的模式 [第一方面] 系统sys模式 VS 管理svc模式 首先,sys模式和usr模式相比,所用的寄存器组,都是一样的,但是增加了一些访问一些在usr ...

  9. kafka如何保证消息得顺序性

    1. 问题 比如说我们建了一个 topic,有三个 partition.生产者在写的时候,其实可以指定一个 key,比如说我们指定了某个订单 id 作为 key,那么这个订单相关的数据,一定会被分发到 ...

  10. Solon rpc 1.2.18 发布,突出Rpc特性

    Solon 是一个微型的Java RPC开发框架.项目从2018年启动以来,参考过大量前人作品:历时两年,3500多次的commit:内核保持0.1m的身材,超高的跑分,良好的使用体验.支持:Rpc. ...