JVM体系结构101:了解您的虚拟机

Java虚拟机(JVM)架构和Java字节码101的初学者速成班

Java应用程序无处不在,它们在我们的手机,平板电脑和计算机上。 在许多编程语言中,这意味着要多次编译代码才能使其在不同的OS上运行。 对于作为开发人员的我们来说,关于Java的最酷的事情可能是Java的设计与平台无关(俗话说“写一次,在任何地方运行”),因此我们只需要编写和编译一次代码。

这怎么可能? 让我们深入研究Java虚拟机(JVM)进行查找。

JVM架构

这听起来可能令人惊讶,但是JVM本身对Java编程语言一无所知。 相反,它知道如何执行自己的称为Java字节码的指令集,该指令集以二进制类文件形式组织。 Java代码由javac命令编译为Java字节码,然后由JVM在运行时将其翻译成机器指令。

线程数

Java被设计为并发的,这意味着可以通过在同一进程中运行多个线程来同时执行不同的计算。 当新的JVM进程启动时,将在JVM中创建一个新线程(称为main thread )。 从该主线程开始运行代码,并可以生成其他线程。 实际的应用程序可以具有成千上万个运行线程,这些线程可以满足不同的目的。 有些服务于用户请求,另一些则执行异步后端任务,等等。

堆栈和框架

每个Java线程都会与框架堆栈一起创建,该框架堆栈用于保存方法框架并控制方法的调用和返回。 方法框架用于存储数据及其所属方法的部分计算。 方法返回时,其框架将被丢弃。 然后,将其返回值传递回调用程序框架,现在可以使用它来完成自己的计算。

JVM流程结构

用于执行方法的JVM游乐场是方法框架。 框架包括两个主要部分:

  1. 局部变量数组 –存储方法的参数和局部变量的位置
  2. 操作数堆栈 –执行方法的计算的位置

框架结构

几乎每个字节码命令都会操纵这两个命令中的至少一个。 让我们看看如何。

怎么运行的

让我们来看一个简单的示例,以了解不同元素如何一起运行以运行我们的程序。 假设我们有一个简单的程序来计算2 + 3的值并打印结果:

class SimpleExample {public static void main(String[] args) {int result = add(2,3);System.out.println(result);}public static int add(int a, int b) {return a+b;}
}

要编译此类,我们运行javac SimpleExample.java ,生成编译文件SimpleExample.class 。 我们已经知道这是一个包含字节码的二进制文件。 那么我们如何检查类字节码呢? 使用javap

javap是JDK附带的命令行工具,可以反汇编类文件。 调用javap -c -p会打印出该类的反汇编字节码(-c),包括私有(-p)成员和方法:

Compiled from "SimpleExample.java"
class SimpleExample {SimpleExample();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."":()V4: returnpublic static void main(java.lang.String[]);Code:0: iconst_21: iconst_32: invokestatic  #2                  // Method add:(II)I5: istore_16: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;9: iload_110: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V13: returnpublic static int add(int, int);Code:0: iload_01: iload_12: iadd3: ireturn
}

现在,JVM在运行时会发生什么? java SimpleExample启动一个新的JVM进程,并创建了主线程。 为main方法创建一个新框架,并将其推入线程堆栈。

public static void main(java.lang.String[]);Code:0: iconst_21: iconst_32: invokestatic  #2                  // Method add:(II)I5: istore_16: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;9: iload_110: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V13: return

main方法具有两个变量: argsresult 。 两者都驻留在局部变量表中。 main的前两个字节码命令iconst_2iconst_3将常量值2和3分别加载到操作数堆栈中。 下一个命令invokestatic调用静态方法add。 由于此方法期望将两个整数用作参数,因此invokestatic从操作数堆栈中弹出两个元素,并将它们传递给JVM为add添加的新帧。 此时主操作数堆栈为空。

public static int add(int, int);Code:0: iload_01: iload_12: iadd3: ireturn

添加框架中,这些参数存储在局部变量数组中。 前两个字节码命令iload_0iload_1将第0个和第1个局部变量加载到堆栈中。 接下来, iadd从操作数堆栈中弹出顶部的两个元素,对其求和,然后将结果推回堆栈中。 最后, ireturn弹出顶部元素,并将其作为方法的返回值传递给调用框架,并丢弃该框架。

public static void main(java.lang.String[]);Code:0: iconst_21: iconst_32: invokestatic  #2                  // Method add:(II)I5: istore_16: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;9: iload_110: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V13: return

main的堆栈现在保存add的返回值。 istore_1弹出它并将其设置为索引1处的变量的值,即resultgetstatic将类型为java / io / PrintStream的静态字段java / lang / System.out推入堆栈。 iload_1将索引1处的变量(现在等于5的结果值)压入堆栈。 因此,此时堆栈拥有2个值:“ out”字段和值5。现在invokevirtual将要调用PrintStream.println方法。 它从堆栈中弹出两个元素:第一个是对将要调用println方法的对象的引用。 第二个元素是要传递给println方法的整数参数,该参数需要一个参数。 这是main方法打印add结果的地方。 最后, 返回命令完成该方法。 主机被丢弃,JVM进程结束。

就是这个。 总而言之,不太复杂。

“一次编写,随处运行”

那么,什么使Java与平台无关? 全部都在字节码中。

如我们所见,任何Java程序都可以编译为标准Java字节码。 然后,JVM在运行时将其转换为特定的机器指令。 我们不再需要确保我们的代码与机器兼容。 相反,我们的应用程序可以在装有JVM的任何设备上运行,并且JVM将为我们完成此操作。 JVM维护人员的工作是提供不同版本的JVM以支持不同的机器和操作系统。

这种体系结构使任何Java程序都可以在安装了JVM的任何设备上运行。 这样魔术就发生了。

最后的想法

Java开发人员可以在不了解JVM如何工作的情况下编写出色的应用程序。 但是,深入研究JVM体系结构,学习其结构并了解其如何解释代码将有助于您成为更好的开发人员。 它还将帮助您不时解决非常复杂的问题

PS。 如果您想更深入地研究JVM以及所有这些与Java异常的关系,那就别无所求! ( 这里可以。 )

翻译自: https://www.javacodegeeks.com/2018/05/jvm-architecture-101-get-to-know-your-virtual-machine.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flask对mysql数据库增删改查_Flask学习(三) - Flask-SQLAlchemy对数据库增删改查

Flask-SQLAlchemy对数据库增删改查安装pip install flask-sqlalchemy具体不多说了,主要是对数据库进行简单的增删改查,上代码,看注释app.route(/)def index():#增加article1 Article(titletest1, contentthe first test)db.session.add(arti…

带有Jersey的JAX-RS教程,用于RESTful Web服务

在当今世界,数据扮演着非常重要的角色。 如此众多的应用程序将各种类型的数据用于不同的操作,所以最重要的方面是应用程序之间的通信。 当应用程序可以通信时,它们之间的数据共享变得容易。 就像在亚洲运行的应用程序向在欧洲运行的应用程序…

java swing 打开文件_java swing实现打开Excel文件并进行处理

这里选择Excel文件是业务需要,话不多说1、引入对Excel处理的相关依赖org.apache.poipoi3.16org.apache.poipoi-ooxml3.162、进行swing的相关布局代码:package com.mozarta;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.xssf.usermodel…

java的对象对象映射_Java对象到对象映射器

java的对象对象映射我在该项目上使用了Dozer一段时间。 但是,最近我遇到了一个非常有趣的错误,这促使我环顾四周,并尝试使用其他“对象到对象”映射器。 这是我找到的工具列表: 推土机:推土机是Java Bean到Java Bea…

java parallelstream_关于Java8 parallelStream并发安全的深入讲解

背景Java8的stream接口极大地减少了for循环写法的复杂性,stream提供了map/reduce/collect等一系列聚合接口,还支持并发操作:parallelStream。在爬虫开发过程中,经常会遇到遍历一个很大的集合做重复的操作,这时候如果使…

使用Google Cloud Storage托管您的Maven工件

如果您使用Google Cloud并将Java用于项目,那么Google Cloud Storage是托管团队工件的理想场所。 它很容易设置,而且很便宜。 如果您对它们的功能不特别感兴趣,那么它比设置现有存储库选项(jfrog,nexus,arc…

java+map对象判断空值_java判断map中是否存在指定对象

Map判断是否包含指定的value使用containsValue方法。(推荐:java视频教程)定义containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true示例:/**** Map集合判断是否包含value**/public class MapDemo{public static vo…

excel查重复_毕业季 | 如何降低论文的查重率

毕业季吾日三省吾身实验做完了吗?论文写完了吗?查重能通过吗?学术圈的前辈告诉我们,只有站在巨人的肩膀上才能看得更远。在撰写一篇论文时,为保证质量和可靠性,难免需要引用前人的成果,这也反映…

Java,JavaFX的流畅设计风格进度栏

按照承诺,刚刚发布的Java JavaFX主题JMetro 4.6版为进度栏带来了新样式。 进度栏有两种可能的状态:确定和不确定,新的JMetro版本具有这两种状态。 在本文中,我还将详细介绍一些我在JMetro中遵守的API设计原则。 JMetro API设计原…

安卓最新系统_成纺移动校园(移动办公系统)V3.2.1 安卓最新版

成纺移动校园(移动办公系统)是额一个非常实用的办公工具。您可以使用该软件及时浏览最新的校园信息,同时涵盖许多功能,例如时间表查询,会议安排,校园地图,校车等。有需要的用户欢迎来绿色先锋网下载。 成纺移动校园简介…

pyqt 获取 UI 中组件_你想知道的React组件设计模式这里都有(上)

本文梳理了容器与展示组件、高阶组件、render props这三类React组件设计模式往期回顾:HBaseCon Asia 2019 Track 3 概要回顾随着 React 的发展,各种组件设计模式层出不穷。React 官方文档也有不少相关文章,但是组织稍显凌乱,本文就…

typora导出word指定样式_(二)最简洁的Markdowd编辑器:Typora

(提醒:前面都是介绍和语法,想下载了就能用的直接看最后总结)大家好,半瓶醋同学又来误人子弟了。现在办公文档或者邮件的处理,一般都是用微软的office word或者邮件自带的编辑器。但是用word或者邮件自带编辑…

使用数据库中的Java流制作数据透视表

来自数据库行和表的原始数据不能为人类读者提供太多了解。 相反,如果我们对数据执行某种聚合,则人类更有可能看到数据模式 在展示给我们之前。 数据透视表是聚合的一种特定形式,我们可以在其中应用排序,求平均值或求和之类的操作…

asynchttpclient 超时_dnf这才是混子的毕业套装,却发现超时空漩涡不买账!

dnf这才是混子的毕业套装,却发现超时空漩涡不买账!按道理来说,光兵和帕拉丁穿这套装备去混团是最好的,结果现在超时空漩涡不要!虽然说兵法套是95最好的魂之涛,但是这个混子套属性真心弱爆,不如正…

win7亮度怎么调_揭秘极米NEW Z8X投影仪怎么样?千万不要上当?!!!!【揭秘反馈

反馈测评极米NEW Z8X投影仪怎么样?求真实点评注意事项极米NEW Z8X投影仪怎么样?靠谱真实回答 外形外观:简约时尚大气,手感不错!\n投影亮度:1080P、4K,都能做到!\n投影色彩:非常好,…

Paw 百度ai_直面落地!百度EasyDL产业智能创新大赛成果覆盖能源、交通、水利民生重业...

物体检测模型实现高压线路隐患检测、图像分类实现短视频快速剪辑和量产、文本情感分类辅助潜在心理疾病患者自发检测、图片识别车辆轮轴数监管车辆载重……每一个创想都能简单快速实现,没有AI开发基础的小伙伴们也能做到!这一切都缘于百度零门槛AI开发平…

Java 9、10及更高版本:Java平台的未来

您紧跟Java平台新功能的秘密武器 自去年9月发布Java 9以来,感觉整个平台都经历了重大变化。 在我们甚至无法确定Java 9所能提供的一切之前,我们已经在标记Java 10的发布。现在,我们已经开始期待Java 11在2018年9月发布。 Oracle决定为Java平…

c fread 快读 详解_奔驰ACC(自适应巡航系统)详解

什么是ACC自适应巡航?ACC自适应巡航( Adaptive Cruise Control ),又可称为智能巡航控制系统,简称ACC系统,它是在传统巡航控制基础上发展起来的新一代汽车驾驶员辅助驾驶系统。它将汽车自动巡航控制系统CCS 和车辆前向撞击报警系统…

php使用邮件找回密码,php利用Zend_Mail发送邮件(实现邮件重设密码功能)

[php]代码库<?php include_once conn/conn.php;require_once Zend/Mail.php;//调用发送邮件的文件require_once Zend/Mail/Transport/Smtp.php;//调用SMTP验证文件$reback 0;$name $_GET[foundname];$question $_GET[question];$answer $_GET[answer];$sql "sele…

_Linux 最常用命令整理,建议收藏!

Linux是目前应用最广泛的服务器操作系统&#xff0c;基于Unix&#xff0c;开源免费&#xff0c;由于系统的稳定性和安全性&#xff0c;市场占有率很高&#xff0c;几乎成为程序代码运行的最佳系统环境。linux不仅可以长时间的运行我们编写的程序代码&#xff0c;还可以安装在各…