小师妹学JVM之:java的字节码byte code简介

简介: 小师妹学JVM之:java的字节码byte code简介

目录



简介



Byte Code也叫做字节码,是连接java源代码和JVM的桥梁,源代码编译成为字节码,而字节码又被加载进JVM中运行。字节码怎么生成,怎么查看字节码,隐藏在Byte Code背后的秘密是什么呢?快跟小师妹一起来看看吧。


Byte Code的作用



小师妹:F师兄,为什么Java需要字节码呢?直接编译成为机器码不是更快吗?


小师妹,Java的设计初衷是一次编写,到处运行。为了兼容各个平台的运行环境,java特别为各种平台设计了JVM。


我们可以把JVM看做是一种抽象,对外提供了统一的接口。这样我们只需要编写符合JVM规范的代码,即可在JVM中运行。


回想下之前我们提到过的java的执行过程:


image.png


  1. 编写java代码文件比如Example.java
  2. 使用java编译器javac将源文件编译成为Example.class文件
  3. JVM加载生成的字节码文件,将其转换成为机器可以识别的native machine code执行


小师妹:F师兄,我有一个大胆的想法,JVM的作用是将字节码解释或者编译成为机器码。然后在相应的运行环境中执行。那么有没有可能,不需要JVM,不需要机器码,而是直接在对应的平台上执行字节码呢?


爱因斯坦说过没有想像力的灵魂,就像没有望远镜的天文台。小师妹你这个想法很好,这种实现有个专业的说法叫做:Java processor。


Java processor就是用硬件来实现的JVM。因此字节码可以直接在Java processor中运行。


其中比较出名的是Jazelle DBX,这是一个主要支持J2ME环境的硬件架构。为了提升java在手机端的执行速度。


但是这样做其实也是有缺点的,后面我们会讲到,java字节码中的指令非常非常多。所以如果用硬件来实现的话,就会非常非常复杂。


一般来说Java processor不会实现全部的字节码中的功能,只会提供部分的实现。


查看Byte Code字节码



小师妹:F师兄,那使用javac编译过后的class文件跟字节码有什么关系呢?


class文件中大部分都是byte code,其他的部分是一些meta data元数据信息。这些组合在一起就是class文件了。


小师妹:F师兄,你说class文件是byte code,为什么我在IDE中打开的时候,直接显示的是反编译出来的源文件呢?


小师妹,这是IDE的一个便利功能。因为大多数情况下,没有人想去看class文件的Byte code的,大家都是想去看看这个class文件的源文件是什么样的。


我们举个最简单的例子:


image.png


这个类中,我们定义了一个很简单的testByteCode方法,里面定义了两个变量,然后返回他们两个的和。


现在有两种方法来查看这个类的Byte Code:


第一种方法是用javap命令:


javap -c ByteCodeUsage.class


image.png


生成的结果如上所示。


第二种方法就是在IDEA中,选中class文件,然后在view中选中show Bytecode:


image.png


我们看下输出结果:


image.png


两个的结果在显示上面可能有细微的差异,但是并不影响我们后面对其的解析。


java Byte Code是怎么工作的



小师妹:F师兄,能讲解一下这些byte code到底是怎么工作的吗?


首先我们要介绍一下JVM的实现是基于栈的结构的。为什么要基于栈的结构呢?那是因为栈是最适合用来实现function互相调用的。


我们再回顾一下上面的testByteCode的字节码。里面有很多iconst,istore的东西,这些东西被称作Opcode,也就是一些基于栈的操作指令。


上面讲了java bytecode的操作指令其实有很多个。下面我们列出这些指令的部分介绍:


image.png


实在是太多了,这里就不把所有的列出来了。


我们看到的指令名字其实是一个助记词,真实的Opcode是一个占用两个字节的数字。


下面我们来详细解释一下testByteCode方法:


public int testByteCode();
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: ireturn


第一步,iconst_1将int 1加载到stack中。


第二步,istore_1将入栈的int 1出栈,并存储到变量1中。


第三步,iconst_2将int 2入栈。


第四步,istore_2将入栈的int 2出栈,并存储到变量2中。


第五步,iload_1将变量1中的值入栈。


第六步,iload_2将变量2中的值入栈。


第七步,iadd将栈中的两个变量出栈,并相加。然后将结果入栈。


第八步,ireturn将栈中的结果出栈。


这几步实际上完美的还原了我们在testByteCode方法中定义的功能。


当然我们只介绍了最贱的byte code命令,通过这些简单的命令可以组合成为更加复杂的java命令。


总结



本文介绍了java byte code的作用和具体的指令,并分析了一个简单的例子来做说明。希望大家能够掌握。


本文的例子https://github.com/ddean2009/learn-java-base-9-to-20

相关文章
|
安全 Oracle Java
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
753 0
JAVA高级开发必备·卓伊凡详细JDK、JRE、JVM与Java生态深度解析-形象比喻系统理解-优雅草卓伊凡
|
存储 运维 Kubernetes
Java启动参数JVM_OPTS="-Xms512m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError"
本文介绍了Java虚拟机(JVM)常用启动参数配置,包括设置初始堆内存(-Xms512m)、最大堆内存(-Xmx1024m)及内存溢出时生成堆转储文件(-XX:+HeapDumpOnOutOfMemoryError),用于性能调优与故障排查。
1377 0
|
人工智能 安全 Java
Go与Java泛型原理简介
本文介绍了Go与Java泛型的实现原理。Go通过单态化为不同类型生成函数副本,提升运行效率;而Java则采用类型擦除,将泛型转为Object类型处理,保持兼容性但牺牲部分类型安全。两种机制各有优劣,适用于不同场景。
675 24
|
人工智能 Java
java中static关键字简介
`static`关键字用于修饰类的成员变量和方法,使其属于类而非对象。静态成员可通过类名直接访问,无需实例化对象。静态方法只能访问静态成员,不能直接访问非静态成员或使用`this`关键字。此外,静态代码块在类首次加载时执行且仅执行一次,适用于初始化操作。
299 0
Java程序员必学:JVM架构完全解读
Java 虚拟机(JVM)是 Java 编程的核心,深入理解其架构对开发者意义重大。本文详细解读 JVM 架构,涵盖类加载器子系统、运行时数据区等核心组件,剖析类加载机制,包括加载阶段、双亲委派模型等内容。阐述内存管理原理,介绍垃圾回收算法与常见回收器,并结合案例讲解调优策略。还分享 JVM 性能瓶颈识别与调优方法,分析 Java 语言特性对性能的影响,给出数据结构选择、I/O 操作及并发同步处理的优化技巧,同时探讨 JVM 安全模型与错误处理机制,助力开发者提升编程能力与程序性能。
Java程序员必学:JVM架构完全解读
|
监控 Java Unix
6个Java 工具,轻松分析定位 JVM 问题 !
本文介绍了如何使用 JDK 自带工具查看和分析 JVM 的运行情况。通过编写一段测试代码(启动 10 个死循环线程,分配大量内存),结合常用工具如 `jps`、`jinfo`、`jstat`、`jstack`、`jvisualvm` 和 `jcmd` 等,详细展示了 JVM 参数配置、内存使用、线程状态及 GC 情况的监控方法。同时指出了一些常见问题,例如参数设置错误导致的内存异常,并通过实例说明了如何排查和解决。最后附上了官方文档链接,方便进一步学习。
3340 4
|
存储 缓存 算法
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
826 29
JVM简介—1.Java内存区域
|
Java Linux API
课时3:Java简介(Java主要特点)
本文介绍了Java的主要特点及其运行机制。Java结合了编译型和解释型语言的优点,通过Java虚拟机(JVM)实现跨平台移植,简化了不同操作系统间的开发流程。Java的特点包括可移植性、简单易用、支持多线程编程、自动垃圾收集和面向对象编程。随着硬件技术的发展,Java的性能问题已大大改善,成为行业标准之一,广泛应用于各种商用平台开发。
464 1
|
开发框架 移动开发 Java
课时2:Java简介(Java发展概述)
课时2:Java简介(Java发展概述) 摘要: 1. Java基础知识:介绍Java作为编程语言及其思想。 2. Java的发展历史:从1991年GREEN项目到1995年正式推出,历经网景公司、HotJava浏览器等关键节点。 3. Java的版本信息:涵盖从JDK 1.0到JDK 1.8的主要版本及特性,如Lambda表达式和模块化支持。
436 0
|
存储 Java C语言
课时11:Java数据类型简介
本文介绍了Java中的数据类型划分,主要分为基本数据类型和引用数据类型。基本数据类型包括数值型(整型、浮点型)、布尔型和字符型,每种类型有固定的默认值和存储范围。引用数据类型涉及内存使用,如数组、类和接口,默认值为Null。文中还提供了不同类型的选择原则,帮助开发者在实际编程中合理选用数据类型。
210 0