• 认识JVM,看看java代码的一生


    语言发展过程

    先来看看编程语言是如何一步步发展的

    • 机器码
      最开始是机器码,就是机器能够认识的语言

    • 指令
      由于机器码是由0和1组成的二进制序列,可读性实在太差,于是人们发明了指令
      指令就是把机器码中特定的0和1序列,简化成对应的指令,可读性稍好
      由于不同的硬件平台,执行同一个操作,对应的机器码可能不同,所以不同的硬件平台的同一种指令(比如mov),对应的机器码也可能不同。
      指令集
      不同的硬件平台支持的指令是有差别的。因此每个平台所支持的指令,称之为对应平台的指令集
      如常见的

      • x86指令集,对应的是x86架构的平台
      • ARM指令集,对应的是ARM架构的平台
    • 汇编语言
      由于指令的可读性还是太差,于是人们又发明了汇编语言。
      用汇编语言编写的程序需要翻译成指令码,计算机才能识别和执行。

    • 高级语言
      为了使编写代码更容易些,后来就出现了各种高级计算机语言。
      高级语言也不是直接翻译成 机器指令,而是翻译成汇编语言,然后经过汇编过程变成机器语言
      在这里插入图片描述

    Java虚拟机

    什么是java虚拟机?

    Java虚拟机负责将java源文件编译成字节码文件,然后再通过解释+编译的方式转换为机器码,字节码文件使得java代码可以在不同的操作系统上运行,可以一次编译到处运行。

    Java虚拟机有哪些特点?

    • 跨平台:一次编译,到处运行
    • 语言无关:不止可以运行java语言,所有可以编译成字节码文件的语言都可以
    • 自动垃圾回收,这个是java程序员的福音,相比写c++时,写java真的幸福太多了~

    JVM内存模型

    先对JVM内存模型有个整体的概念,下面再详细讲解java代码是如何度过自己一生的
    在这里插入图片描述
    运行时数据区图解:
    在这里插入图片描述

    java代码的一生

    先看编译期和运行期的概念

    编译期:java源程序—字节码

    在编译期,Java编译器会把Java代码编译成字节码文件
    这期间编译期并没有把代码放在内存中运行起来,而只是做了一些翻译,检查错误,泛型擦除(所以java是伪泛型,c++才是真泛型)等工作。

    流程图如下所示:
    在这里插入图片描述

    运行期:Java字节码——机器码——运行

    运行期是指:把编译后的字节码文件执行引擎翻译成机器码,然后交给计算机执行,直到程序运行结束的整个流程。

    从jvm加载字节码文件,使用,然后到最后的卸载过程,都是属于运行期的范畴。
    在这里插入图片描述
    类加载过程由类加载器完成,加载完成之后就是初始化(堆栈方法区)和使用(执行引擎将字节码文件解释+编译成机器码交给计算机真正执行)阶段,使用完成之后卸载(垃圾回收)

    如何做到 “一次编译,到处运行”(即平台无关)

    比喻: Java程序比做“汉语”的话,字节码就相当于“世界语”(实际不存在但是理解就行),世界语不和具体的“国家”关联,只要这个“国家”提供了“翻译”(JVM),就可以快速地把世界语翻译成本地语言(机器码)。

    看了这个比喻应该能大概明白了吧,其实说白了就是java源程序经过编译器编译产生一种与平台无关的二进制的字节码文件,这个字节码文件可以在不同的平台运行。

    在这里插入图片描述

    jvm居然能编译这么多语言

    那你有没有想过,既然jvm这么强大,能帮我们屏蔽os之间的差异,为什么不直接将java源代码翻译成机器码,而要在中间加一个字节码呢?
    这是因为jvm的格局比我们以为的要大,它不仅想编译java代码,还想编译更多的代码,jvm提供一个字节码作为标准,只要是按照这个标准设计的语言,我都可以编译。

    所以说,jvm根本不关心运行的程序是何种编程语言编写的,它只关心“字节码”文件
    只要一种语言可以转换成符合要求的字节码文件,就能够被虚拟机所识别并装载运行。
    在这里插入图片描述

    Java语言是编译型语言还是解释型语言?

    jvm说:我都要!
    先解释下什么是编译型语言和解释型语言:

    1. 编译型语言:将源代码一次全部转换成机器码的过程,类似全文翻译
      优点:优化更充分,程序运行时速度更快,但是编译过程本身比较慢
    2. 解释型语言:将源代码逐条转换成机器码同时逐条运行的过程,类似同声传译
      优点:当程序启动后,解释器可以马上发挥作用,不用像编译那样需要等,所以比编译语言要更快的执行,注意是更快的执行,而实际的运行速度要慢一些
      缺点:优化不够充分,整体的运行速度也要慢一些。

    Java语言是半解释半编译的语言,综合了解释执行和即时编译两者的优点。
    实际工作过程如下:
    当Java虚拟器启动时,解释器首先发挥作用,随着时间的推移,编译器编译好了之后开始发挥作用,将其中反复执行的热点代码,以方法为单位进行编译,获得更高的执行效率

    之所以可以提升编译效率,是建立在程序符合二八定律的假设上,也就是20%代码占据了80%的计算资源。

    • 对于大部分的不常用代码,我们无需耗费时间将其编译成机器码,可以采用解释执行的方式运行;
    • 另一方面,对于小部分的热点代码,我们则可以将其编译成机器码,以达到理想的运行速度。

    流程图:
    在这里插入图片描述
    流程图如下所示
    在这里插入图片描述

  • 相关阅读:
    Spring Boot | Spring Boot 实现 “Redis缓存管理“
    py-运算符
    Sass常用语法
    预编译、函数变量提升
    使用EasyExcel进行读写操作
    jdk 线程池任务提交机制&&任务执行流程详解
    程序化交易是科学和艺术的结合
    NetSuite知识会汇编-管理员篇&顾问篇2023
    5. Python 文件操作
    CTF 全讲解:[SWPUCTF 2022 新生赛]webdog1__start
  • 原文地址:https://blog.csdn.net/qq_40337086/article/details/126494990