返回顶部
首页 > 资讯 > 后端开发 > JAVA >JAVA虚拟机(JVM)详细介绍(七)——JVM优化
  • 584
分享到

JAVA虚拟机(JVM)详细介绍(七)——JVM优化

java教程JVM 2017-09-20 23:09:03 584人浏览 才女
摘要

还以这个图为例,从.java到.class是编译过程,从.class到机器码是解释过程。下面对其进行分别优化。在优化过程中,对编译阶段的优化主要是对前端编译器的优化,在运行阶段的优化,主要是对即时编译器的优化。编译器优化编译过程以上为jav

20190621172513514.png

还以这个图为例,从.java到.class是编译过程,从.class到机器码是解释过程。下面对其进行分别优化。在优化过程中,对编译阶段的优化主要是对前端编译器的优化,在运行阶段的优化,主要是对即时编译器的优化。

2019062117255488.png

编译器优化

编译过程

20190621172714334.jpg

以上为javac的编译过程图,以下为javac编译过程的主体代码。

20190621174151194.jpg

下面对其步骤进行详细解读
1、解析与填充符号表

词法分析

将源代码的字符流转变为标记(Token)集合,标记是编译过程中的最小元素,如a,=,b,int。

语法分析

根据Token序列构造抽象语法树。以后编译器基本不会再对源码文件进行操作了,后续的操作都是建立在抽象语法树上。抽象语法树是一种用来描述程序代码语法结构的树形表示方式,节点代表代码中的一个语法结构,例如修饰符,返回值等。

填充符号表

符号表是由一组符号地址和符号信息构成的表格,用于编译的不同阶段。如在语义分析中,用于语义检查和产生中间代码;在目标代码生成阶段,用于地址分配的依据。

2、注解处理器
这部分是插入式注解处理器在编译期间对注解进行处理的过程。其可以对语法树进行修改,一旦进行了修改,编译器将回到上面的第一步进行重新处理,每一次循环称为一个Round,也就是上图中的回环过程。

3、语义分析与字节码生成
在经过语法分析后,生成的语法树是一个结构正确的源程序的抽象,但无法保证源程序是符合逻辑的。语义分析的任务是对结构上正确的源程序进行上下文有关性质的审查。比如下面代码中的错误只能在语义分析阶段检查出来。

boolean a=false;
char b=2;
int c=a+b

此阶段包括如下4个步骤:

标注检查

变量使用前是否已被声明、变量与赋值之间的数据类型是否能够匹配等。还有一个常量折叠,即把a=1+2变为a=3。所以在代码中的a=1+2和a=3并不会增加程序运行期cpu指令的运算量。

数据及控制流分析

检查程序局部变量在使用前是否有赋值,方法的每条路径是否都有返回值,是否所有的受查异常都被正确处理了等问题。在类加载时也有一个数据及控制流分析,其目的基本是一致的,但校验的范围不同,有些校验项只有在编译期或运行期才能运行。

解语法糖

语法糖是在计算机语言中添加某种语法,其对语言的功能没有影响,但是能提高程序的可读性。语法糖包括泛型,自动拆装箱等。虚拟机运行时不支持这些语法,它们在编译阶段还原回基础语法结构。这个过程称为解语法糖。

字节码生成

将之前步骤生成的信息(语法树、符号表)转化成字节码写到磁盘中,然后添加和转换了少量的代码。如把字符串的加操作替换为StringBuffer或StringBuilder的append()操作。

至此,Class文件生成了。

语法糖

语法糖是java中添加某种语法,对语言的功能没有影响,但是可以增加程序的可读性。包括泛型、内部类、枚举类等。

泛型与类型擦除
泛型可用于类、接口和方法的创建中,用于对放入集合元素的类型的约束。泛型只在程序源码中存在,在编译阶段有解语法糖的步骤,所以在.Class文件中,已经变为了原来的原生类型了。这个过程叫做类型擦除。
泛型擦除前:

public static void main(String[] args){
    Map map=new HashMap<>();
    map.put("姓名","小明");
    map.put("性别","男");
    sout(map.get("姓名"));
    sout(map.get("性别"));
}

泛型擦除后:

public static void main(String[] args){
    Map map=new HashMap();
    map.put("姓名","小明");
    map.put("性别","男");
    sout((String)map.get("姓名"));
    sout((String)map.get("性别"));
}

所以ArrayList和ArrayList在运行期时是同一个类。

自动拆装箱、循环遍历
这些是java中使用最多的语法糖。编译前:

public static void main(String[] args){
      List list=Arrays.asList(1,2,3,4);
      int sum=0;
      for(int i:list){
              sum +=i;
      }
      System.out.println(sum);
}

编译后:

public static void main(String[] args){
      List list=Arrays.asList(new Integer[] {
                Integer.valueOf(1),
                Integer.valueOf(2),
                Integer.valueOf(3),
                Integer.valueOf(4)});
      int sum=0;
      for(Iterator localIterator=list.iterator();localIterator.hasNext();){
                   int i=((Integer)localIterator.next()).intValue();
                   sum +=i;
      }
      System.out.println(sum);
}

可见,自动拆装箱在编译后被转化为了对应的包装和还原方法,如Integer.valueOf()和Integer.intValue()。
遍历循环则把代码还原为了迭代器的实现。

条件编译
根据布尔常量值的真假,编译器会把分支中不成立的代码块消除掉。

public static void main(String[] args){
      if(true){
            sout("block 1");
      }else{
           sout("block 2");
     }
}

编译后,代码变为:

public static void main(String[] args){
     sout("block 1");
}

运行期优化

一般情况下,我们将.java编译成.class,.class再解释成机器码。但是也有特殊的情况。有些代码调用比较频繁,比如某个方法或代码块的运行特别频繁,为了提高程序的执行效率,在运行时,虚拟机会把这个代码直接编译成机器码,并进行各种层次的优化。这样的代码称为热点代码。完成这个任务的编译器被称为即时编译器。但是其并不是虚拟机必需的部分。

20190621173045527.png

即时编译器的概述

(1)为什么虚拟机要使用解释器和编译器并存的架构

虚拟机里包含着解释器和编译器。当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。

当程序运行环境中内存资源限制较大,可以使用解释执行节约内存,反之可以使用编译来提升效率。

(2)为什么虚拟机要实现两个不同的即时编译器?

虚拟机中内置了两个即时编译器,分别为Client Compiler和Server Compiler,又称为C1和C2。

默认只使用其中的一个,至于选择哪个,取决于虚拟机会根据自身版本和宿主机器的硬件性能自动选择运行模式。用户也可以使用“-client”、“-server”进行指定。

(3)程序何时使用解释器执行?何时使用编译器执行?

虚拟机有一个分层编译策略。

第0层:程序解释执行,解释器不开启性能监控功能,可触发第1层编译

第1层:也称为C1编译,将字节码编译为本地代码,进行简单、可靠的优化,如有必要将加入性能监控的逻辑。

第2层:也称为C2编译,将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。

(4)哪些程序代码会被编译为本地代码?如何编译为本地代码?

热点代码包括如下两类,其均把整个方法作为编译对象。

a、被多次调用的方法

b、被多次执行的循环体

热点探测是用来判断一段代码是否为热点代码,其方式有两种:

a、基于采样

b、基于计数器。HotSpot使用的是这种。它为每个方法准备了两类计数器:统计方法被调用次数的方法调用计数器和统计一个方法中循环体代码执行次数的回边计数器。

(5)如何从外部观察及时编译器的编译过程和编译结果?

可以使用 -xx:+PrintCompilation 查看哪些方法被即时编译器编译了。

优化技术有哪些?

虚拟机的即时编译器在生成代码时,采用了如下的代码优化技术。

(1)公共子表达式消除

如果一个表达式E已经计算过了,那如果再次出现E时就不会再对它进行计算。比如:

int d=(a*b)*12+c+(c+b*a)

如果这段代码交给javac编译器,则不会进行任何优化。如果交给即时编译器,会被进行如下步骤的优化:

第一步:消除公共子表达式

int d=E*12+c+(c+E)

第二步:代数化简:

int d=E*13+c*2

(2)数组边界检查消除

数组边界检查是什么?
如果有一个数组foo[],在java语言中访问数组元素foo[i]的时候,系统将会自动进行上下界的范围检查,检查i是否满足0≤i≤foo.length这个条件。

那怎么进行消除呢?
a、把运行期检查提到编译期完成。如foo[3],只要在编译期根据数据流分析来确定foo.length的值,并判断下标“3”没有越界,执行的时候就不用判断了。
b、隐式异常处理。这种思路通常用于空指针检查和算符运算中除数为零的情况。

if(foo!=null){
  return foo.value;
}else{
  throw new NullPointException();
}

被隐式异常处理优化后,变为如下代码:

try{
  return foo.value;
}catch(segment_fault){
  uncommon_trap();
}

除了数组边界检查消除,还有自动装箱消除、安全点消除、消除反射等。

(3)方法内联

把目标方法的代码“复制”到发起调用的方法之中,避免发生真实的方法调用。

public int add(int x1, int x2, int x3, int x4) {  
        return add1(x1, x2) + add1(x3, x4);  
 }  

public int add1(int x1, int x2) {  
        return x1 + x2;  
    }

运行一段时间后JVM会把add1方法去掉,并把代码翻译成:

public int add(int x1, int x2, int x3, int x4) {  
        return x1 + x2 + x3 + x4;  
}

(4)逃逸分析

当一个对象在方法中被定义后,它可能被外部方法所引用,比如作为调用参数传递到其它方法中,这称为方法逃逸。同理,如果被外部线程访问到,它就称为线程逃逸。

对变量进行相应分析就叫做逃逸分析。如果能证明别的方法或线程无法通过任何途径访问到这个对象,则可以为这个变量进行一些优化。

优化的手段有栈上分配、同步消除、标量替换等。以同步消除为例,如果逃逸分析能够确定一个变量不会逃逸出线程,即无法被其它线程访问到,那对这个变量实施的同步措施就可以消除掉了。

以上内容便是关于JAVA虚拟机中JVM优化的全部介绍,更多相关问题请访问PHP中文网:JAVA视频教程

--结束END--

本文标题: JAVA虚拟机(JVM)详细介绍(七)——JVM优化

本文链接: https://lsjlt.com/news/4197.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JAVA虚拟机(JVM)详细介绍(七)——JVM优化
    还以这个图为例,从.java到.class是编译过程,从.class到机器码是解释过程。下面对其进行分别优化。在优化过程中,对编译阶段的优化主要是对前端编译器的优化,在运行阶段的优化,主要是对即时编译器的优化。编译器优化编译过程以上为jav...
    99+
    2017-09-20
    java教程 JVM
  • JAVA虚拟机(JVM)详细介绍(一)——JVM概述
    首先,对以上的四部分进行解释。(1)自动内存管理讲的是java运行时数据区里的部分,分为内存划分和垃圾收集器。(2)执行子系统讲的是画红圈的三部分:类文件结构、类加载机制、字节码执行引擎。(3)优化分别为编译期优化和运行期优化。(4)并发讲...
    99+
    2016-06-30
    java教程 JVM
  • JAVA虚拟机(JVM)详细介绍(八)——高效并发
    内存模型内存模型是在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象。其主要目标是定义程序中各个变量的访问规则。主内存和工作内存所有的变量都存储在主内存中,每条线程还有自己的工作内存,其工作内存中是被线程使用到的变量的主内存副...
    99+
    2017-08-31
    java教程 JVM
  • JAVA虚拟机(JVM)详细介绍(五)——类加载机制
    上篇中我们讲解了Class文件,这篇我们说说虚拟机是如何加载这些Class文件的?Class文件中的信息进入到虚拟机后会发生什么变化?这就涉及到了类加载机制。类加载机制是把类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始...
    99+
    2015-12-28
    java教程 JVM
  • JAVA虚拟机(JVM)详细介绍(四)——类文件结构
    讲完了自动内存管理,我们来说说执行子系统。执行子系统讲解的是JVM如何执行程序。Class文件概述这篇我们只讲讲Class文件。Class文件又名类文件或字节码文件。javac将.java文件(源代码)编译成.class文件(字节码),jv...
    99+
    2016-02-29
    java教程 JVM
  • JAVA虚拟机(JVM)详细介绍(三)——垃圾收集机制
    在上一篇中我们说过,自动内存管理分为两部分:给对象分配内存和回收分配给对象的内存。这篇我们说说后者,即回收分配给对象的内存。回收内存要用到垃圾收集机制,英文名儿是GC(Garbage Collection)。在本部分我们要解决如下几个问题:...
    99+
    2017-01-27
    java教程 JVM
  • JAVA虚拟机(JVM)详细介绍(六)——字节码执行引擎
    JVM中的执行引擎在执行java代码的时候,一般有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择。栈帧定义:栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它位于虚拟机栈里面。作用:每个方法从调用开始到...
    99+
    2014-07-03
    java教程 JVM
  • Java JVM虚拟机调优详解
    目录jmap查看内存信息jstackjinfo查看jvm系统参数Jstat查看堆内存使用和类加载的数量信息内存泄漏jmap查看内存信息 jmap histo /pid > ./...
    99+
    2024-04-02
  • java虚拟机之JVM调优详解
    目录JVM常用命令行参数1. 查看参数列表2. 基本参数说明:3. 扩展参数说明:虚拟机参数分类什么是调优1.调优步骤:2.调优案例2.1案例一2.2案例二JVM优化总结JVM常用命...
    99+
    2024-04-02
  • Java虚拟机怎么利用JVM进行优化
    本篇文章为大家展示了Java虚拟机怎么利用JVM进行优化,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前言Java虚拟机是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最...
    99+
    2023-05-31
    java jvm ava
  • JAVA虚拟机(JVM)详细讲解(二)——内存的划分
    我们知道,在C++语言里,如果想使用一个对象,需要对其进行new操作;如果不用这个对象了,需要对其进行delete操作。一旦开发人员忘记写delete语句了,就会造成内存泄露。【内存被对象占用着不还,就叫内存泄露。】而java就聪明了,它从...
    99+
    2020-08-19
    java教程 JVM
  • JVM学习- - -虚拟机栈详解
    前言:今天学长带领大家走进JVM学习,让我们一起来学习认识虚拟机栈吧~ 目录 1 虚拟机栈概述 虚拟机栈出现的背景 初步印象 内存中的栈和堆 虚拟机栈基本内容 栈的优点 2 栈的存储单位 栈中存储什么? 栈运行原理 栈帧的内部结构 ...
    99+
    2023-09-12
    jvm 学习 java
  • JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)
    JVM(Java虚拟机) JVM 内存模型 结构图 jdk1.8 结构图(极简) jdk1.8 结构图(简单) JVM(Java虚拟机): 是一个抽象的计算模型。如同一台真实的机器,它有自己的指令集和执行引擎,可以在运行时操控内存区域。...
    99+
    2023-08-30
    jvm GC 直接内存 jvm性能调优
  • Java 虚拟机(JVM)之基本概念详解
    1、类加载子系统:负责从文件系统或者网络中加载Class信息,加载的信息存放在一块称之为方法区的内存空间。2、方法区:就是存放类信息、常量信息、常量池信息、包括字符串字面量和数字常量等。方法区是辅助堆栈的块永久区,解决堆栈信息的产生,是先决...
    99+
    2023-05-31
    java 虚拟机 基本概念
  • 深入理解JVM虚拟机12:JVM性能管理神器VisualVM介绍与实战
    微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站。作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术...
    99+
    2023-06-02
  • jvm虚拟机类加载机制详解
    目录1 概述2 类的加载时机3 类的加载过程3.1 加载3.2 验证3.3 准备3.4 解析3.5 初始化4 类加载器4.1 双亲委派模型4.2 破坏双亲委派模型1 概述 ​ Jav...
    99+
    2024-04-02
  • Java虚拟机栈jvm栈的作用
    目录1. 定义2. 栈的线程安全问题3. 栈内存溢出1. 定义 栈:线程运行时需要的内存空间,一个栈存在多个栈帧。栈具有先入后出,后入先出的特点。 栈帧:每个方法运行时需要的内存(局...
    99+
    2024-04-02
  • JVM(Java虚拟机)简介(动力节点Java学院整理)
    一、概要Java虚拟机(Jvm)是什么?Java虚拟机是用来干什么的?Java虚拟机它的体系结构是什么样子的?Java虚拟机在工作做扮演什么角色?Java虚拟机在运行时数据区?二、Jvm基础概念Java虚拟机(Jvm)是可运行Java代码的...
    99+
    2023-05-31
    java jvm 虚拟机
  • JVM类加载机制及生命周期的详细介绍
    这篇文章主要讲解了“JVM类加载机制及生命周期的详细介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JVM类加载机制及生命周期的详细介绍”吧!一.目标:什么是类的加载?类的生命周期?类加载...
    99+
    2023-06-02
  • java为什么需要虚拟机jvm原理详解
    曾几何时,我们还是初识Hello World的时候,我们哪曾知道,Java这门神奇的语言,在执行我们的代码的时候,不是直接将我们所编写的Java代码交付给操作系统底层进行解析编译,...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作