龙空技术网

一文读懂 JVM 为何被称之为跨语言的平台

愿天堂没有代码 100

前言:

眼前看官们对“java语言是跨平台的吗”大约比较着重,你们都需要分析一些“java语言是跨平台的吗”的相关文章。那么小编也在网摘上网罗了一些关于“java语言是跨平台的吗””的相关内容,希望小伙伴们能喜欢,你们一起来学习一下吧!

初识JVM——跨语言的平台

首先理解JVM的两个特性

跨平台

通过不同平台指令集、不同机器码下的虚拟机,可以运行同样的字节码文件,达到同样的结果,以此达到虚拟机跨平台的特性

语言无关性

通过不同的编译器,可以编译出符合统一字节码规范的字节码文件,交由JVM处理,屏蔽了不同编程语言的特性

JVM是什么?

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成

引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译; Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行

JDK、JRE和JVM的关系

JDK(Java Development Kit,Java开发工具包)是用来编译、调试Java程序的开发工具包;包括Java工具(javac/java/jdb等)和Java基础的类库(java API )

JRE(Java Runtime Environment, Java运行环境) 是Java平台,所有的程序都要在JRE下才能够运行;包括JVM和Java核心类库和支持文件

JVM(Java Virtual Machine, Java虚拟机) 是JRE的一部分;JVM主要工作是解释自己的指令集(即字节码)并映射到本地的CPU指令集和OS的系统调用;Java语言是跨平台运行的,不同的操作系统会有不同的JVM映射规则,使之与操作系统无关,完成跨平台性

类加载过程

当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化; 如果没有意外,JVM将会连续完成3个步骤,所以有时也把这个3个步骤统称为类加载或类初始化

执行引擎

interpreter(解释器)

每跑一行就编译一行,对于每条Java代码逐一转译、执行,性能较差,一般情況下,执行引擎都是先用interpreter来执行Java代码,等到某些条件成立后才会使用JIT优化

JIT(即时编译器)

加速方法很直观,JIT会在所有需要执行的代码里面找执行频率高的,把这些代码编译成机器语言之后存在高速缓存里,这样只要每次一执行这部分的代码都是跑机器语言

GC(垃圾回收)

java的堆是在虚拟机启动时自动创建,运行过程中出案件的对象和数组都放在这个内存空间里,如果那没有及时清理责则会造成内存溢出;在垃圾回收的时候通常所有的程序都被强制中断

系统会根据内存使用情况动态决定什么时候需要自动进行垃圾回收,所以这个时间是不可控的;当然也可以手动清理

运行时数据区Program Counter(程序计数器)

存放一个线程当先在执行的指令地址,改变程序计数器来确定下一步要执行的指令的地址; 因为程序的线程数不可能超过CPU的线程数,所以当多个线程并行的时候会导致各线程争夺CPU资源;当不同线程争夺CPU资源时,会出现交替运行的现象,这时就需要PC来记录线程执行记录,用来恢复某个线程执行的位置

JVM Stack(虚拟机栈)

当一个线程需要执行一个方法的时候会创建一个栈帧丢到虚拟机栈中,用于存储局部变量表、操作栈、动态链接、方法出口等信息; 每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程

在Java 虚拟机规范中,对这个区域规定了两种异常状况: 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常;如果虚拟机栈可以动态扩展(当前大部分的Java 虚拟机都可动态扩展,只不过Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError 异常

Native Method stack(本地方法栈)

本地方法栈的作用和虚拟机栈作用类似,区别是虚拟机栈为虚拟机执行java方法服务,本地方法栈为虚拟机用到的native方法服务; 甚至有的虚拟机(譬如Sun HotSpot 虚拟机)直接就把本地方法栈和虚拟机栈合二为一;与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError 和OutOfMemoryError异常

Java Heap(堆)

Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建; 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存

这一点在Java 虚拟机规范中的描述是: 所有的对象实例以及数组都要在堆上分配,但是随着JIT 编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也渐渐变得不是那么“绝对”了

Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”(GarbageCollected Heap)

堆空间接口:

左侧 为 年轻代(Young Generation Space),右侧为 老年代(Old Generation Space);年轻代又分为 Eden区和Survivor区 (from /to 即 Survivor0和Survivor1 区)

新生代: 有Eden、两块大小相同的survivor(又称为from/to,s0/s1)构成,to总为空

老年代: 存放新生代中经历多次GC仍然存活的对象

进一步认识Java

相信各位来阅读JVM之前已经对Java语言有了不浅的理解,所以这里对于Java的安装、环境变量配置、语法特性等基础就不再多做描述

Oracle JDK与Open JDK

背景:

Oracle JDK已经更新到JKD18,最新的LTS(长期支持)版本为JDK17,市场最多使用的仍然是JDK8(主流的 JDK 8 在2019年01月之后就被宣布停止更新了)

Oracle JDK

Oracle JDK 由 Oracle 维护和开发; 它符合 OpenJDK 规范,但不是开源代码;Oracle JDK 在 JVM 响应能力和生产力方面要好得多;由于其对企业客户的重要性,它更注重稳定性

OpenJDK

OpenJDK是开放源代码,由Oracle维护和开发,但允许社区和其他公司参与开发,如Red Hat、Azul Systems、IBM、Apple Inc等; OpenJDK既是一种JDK产品,也是一种规范,任何想要使用OpenJDK创建新变体的公司或组织都必须遵守这些规范

Oracle JDK和OpenJDK的异同点

Oracle JDK 比 OpenJDK 更稳定; 在JDK11中,我们可以认为OpenJDK和OracleJDK代码实质上已经完全一致的程度 OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复

二者共同使用Hotspot虚拟机(它采用解释器与编译器并存的架构)

许可协议不同: Oracle JDK 根据二进制代码许可协议获得许可,而 OpenJDK 根据 GPL v2 许可获得许可

如何对二者做出选择?

Oracle JDK的特点是单版本长期支持; 如开发企业/商业软件,一般建议选择Oracle JDK,因为它经过了彻底的测试和稳定OpenJDK的特点是更新频繁,实现快速迭代和高效试错,为Oracle JDK LTS版本打下基础

商用收费,学习研究免费; 如需在开源基础上开发及问题优化维护或不那么注重稳定性,则可以选择OpenJDK

Java语言的地位

每年都有很多新、旧编程语言的兴起躁动与消失,说明必然有其需求动力所在,譬如互联网之于JavaScript、人工智能之于Python,微服务风潮之于Golang等; 大家都清楚不太可能有哪门语言能在每一个领域都尽占优势,Java已是距离这个目标最接近的选项,但若“天下第一”还要百尺竿头更进一步的话,似乎就只能忘掉Java语言本身,踏入无招胜有招的境界

Java代码的执行流程

Java上层框架与JVM的关系

Java是目前用户最多、使用范围最广的软件开发技术; Java的技术体系主要由支撑Java程序运行的虚拟机、提供各开发领域接口支持的Java类库、Java编程语言及许许多多的第三方Java框架(如Spring、MyBatis等)构成

在国内,有关Java类库API、Java语言语法及第三方框架的技术资料和书籍非常丰富,相比而言,有关Java虚拟机的资料却显得异常贫乏

这种状况很大程度上是由Java开发技术本身的一个重要优点导致的: 在虚拟机层面隐藏了底层技术的复杂性以及机器与操作系统的差异性;运行程序的物理机千差万别,而Java虚拟机则在千差万别的物理机上面建立了统一的运行平台,实现了在任意一台Java虚拟机上编译的程序,都能在任何其他Java虚拟机上正常运行

这一极大的优势使得Java应用的开发比传统C/C++应用的开发更高效快捷,程序员可以把主要精力放在具体业务逻辑,而不是放在保障物理硬件的兼容性上

即便如此,我认为正如大树扎根一样,对于内功和底层的修炼,才是我们能立足于越来越内卷的环境的根本

以上就是JVM的详细分析,此外,作为开发人员为用户带去操作流畅丝滑的APP,是漫长职业生涯当中的终极目标

好了,文章基本上就到这里,JVM的相关知识点已经分析完毕了!,如有地方不对或者有不同理解的可以提出来

有需要更多Android资讯的同学 可以 私信 发送 “进阶” 或 “笔记” 即可 免费获取

现在私信发送还可以获得 更多《Android 学习笔记+源码解析+面试视频》

最后我想说:

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

标签: #java语言是跨平台的吗