在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以, Java 程序运行时相对来说还是高效的(不过,和 C++,Rust,Go 等语言还是有一定差距的),而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

Java 程序从源代码到运行的过程如下图所示:

我们需要格外注意的是 .class->机器码 这一步。在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT(just-in-time compilation) 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言

HotSpot 采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是 JIT 所需要编译的部分。JVM 会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9 引入了一种新的编译模式 AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了 JIT 预热等各方面的开销。JDK 支持分层编译和 AOT 协作使用。

为什么不全部使用 AOT 呢?

AOT 可以提前编译节省启动时间,那为什么不全部使用这种编译方式呢?

长话短说,这和 Java 语言的动态特性有千丝万缕的联系了。举个例子,CGLIB 动态代理使用的是 ASM 技术,而这种技术大致原理是运行时直接在内存中生成并加载修改后的字节码文件也就是 .class 文件,如果全部使用 AOT 提前编译,也就不能使用 ASM 技术了。为了支持类似的动态特性,所以选择使用 JIT 即时编译器。

相关阅读:Java基础常见面试题总结(上)

什么是 Java 字节码?采用字节码的好处是什么?的更多相关文章

  1. java编译过程(字节码编译和即时编译)

    Javac编译与JIT编译 简介: 编译包括两种情况: 1,源码编译成字节码 2,字节码编译成本地机器码(符合本地系统专属的指令) 解释执行也包括两种情况: 1,源码解释执行 2,字节码解释执行 解释 ...

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

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

  3. JVM总括三-字节码、字节码指令、JIT编译执行

    JVM总括三-字节码.字节码指令.JIT编译执行 目录:JVM总括:目录 java文件编译后的class文件,java跨平台的中间层,JVM通过对字节码的解释执行(执行模式,还有JIT编译执行,下面讲 ...

  4. 原码、补码,反码以及JAVA中数值采用哪种码表示

    原码.补码,反码以及JAVA中数值采用哪种码表示 1.原码定义(摘自百度百科):一种计算机中对数字的二进制定点表示方法,原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位 ...

  5. JAVA上百实例源码以及开源项目

    简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级.中级.高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情.执着,对IT的憧憬. ...

  6. Java基础try-with-resource语法源码分析

    众所周知,所有被打开的系统资源,比如流.文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故. 在Java的江湖中,存在着一种名为finally ...

  7. JAVA上百实例源码网站

    JAVA源码包1JAVA源码包2JAVA源码包3JAVA源码包4 JAVA开源包1 JAVA开源包2 JAVA开源包3 JAVA开源包4 JAVA开源包5 JAVA开源包6 JAVA开源包7 JAVA ...

  8. java.lang.instrument: 一个Java对象占用多少字节?

    一.对象头包括两部分信息:Mark Word(标记字段)和 Klass Pointer(类型指针)   1. Mark Word 用于存储对象自身的运行时数据,如哈希码(HashCode).GC分代年 ...

  9. 学习:二维码、QR码、J4L-QRCode、java

    开源码 Java 解码器(编码解码)下载:http://sourceforge.jp/projects/qrcode/downloads/28391/qrcode.zip Java QR Code O ...

  10. Java IO 之 OutputStream源码

    Writer      :BYSocket(泥沙砖瓦浆木匠) 微         博:BYSocket 豆         瓣:BYSocket FaceBook:BYSocket Twitter   ...

随机推荐

  1. 【短道速滑二】古老的基于亮度平均值的自动Gamma校正算法。

    在github上搜索代码Auto Gamma Correction,找到一个比较古老的代码,详见:https://github.com/PedramBabakhani/Automatic-Gamma- ...

  2. 基于C++11特性的线程池

    写在前面:本文学习自基于C++11实现线程池,代码部分均属于该博主,自己只是想记录以下自己的认知,并以这种方式加深一下自己对于多线程的理解 1 前置知识 RAII管理机制 简单来说RAII机制是一种对 ...

  3. Go--日志

    一.Logger go语言默认提供的日志功能,包为ttps://golang.org/pkg/log/ 优势: 使用非常简单,可以设置任何io.Writer作为日志记录输出并向其发送要写入的日志 劣势 ...

  4. Java 使用 slf4j + log4j 写日志

    没有SpringBoot等框架的情况下 pom.xml: <properties> <slf4j.version>1.7.26</slf4j.version> &l ...

  5. 核心工具之 ideavim

    对于个人的核心工具集的选择,因为编程中熟练使用主力IDE能够大大提高效率,所以IDE是一个必选项.而IDE与VIM结合的插件,对于VIM使用者,常常是一个必选项. 在Jetbrains系列工具中,插件 ...

  6. POJ 3259 Wormholes(bellman_ford、Floyd、SPFA判断负环)

    POJ 3259 http://poj.org/problem?id=3259 题意: 农夫 FJ 有 N 块田地[编号 1...n] (1<=N<=500) 田地间有 M 条路径 [双向 ...

  7. Spring EL 表达式

    本篇讲述了Spring Expression Language -- 即Spring3中功能丰富强大的表达式语言,简称SpEL. SpEL是类似于OGNL和JSF EL的表达式语言,能够在运行时构建复 ...

  8. 上海丨阿里云 Serverless 技术实战营邀你来玩!

    活动简介 本次沙龙深度探讨 "Serverless 在中国企业的落地和开发者实操" 主题,我们特别邀请了来自阿里云 一线技术专家,分享当前 Serverless 趋势和落地实践过程 ...

  9. C#将日期格式化为指定格式

    private void btn_GetTime_Click(object sender, EventArgs e) { lab_time.Text = DateTime.Now.ToString(& ...

  10. 最近遇到的问题记录:UrlEncode、UrlDecode

    本文阅读前了解知识:什么时候需要使用UrlEncode和UrlDecode函数 作者使用谷歌浏览器,通过按下F12对第三方网站http协议的接口抓包进行分析操作. 场景 运维小哥哥偶尔使用某某外包公司 ...