1. 总体流程

简单来讲,一款编程语言想兼容底层(跨操作系统)的方式大概有两种:一是通过编译器,如C或C++。但是要针对不同硬件平台和操作系统开发不同的编译器,这样实现十分麻烦。二是通过中间语言,如Java、C#。代码被编译后生成中间语言,后由虚拟机负责解释和运行,虚拟机在运行期间将中间语言实时翻译成与特定底层平台匹配的机器指令并运行。
java语言声称可以“一次编译,到处运行(write once , run everywhere)”,那么具体是如何实现的呢?
主体流程大约如下:一个java代码文件,首先被编译器(javac)编译成一个特定格式的二进制字节码文件(class文件),然后被虚拟机(jvm)的加载器加载到内存中,再由执行引擎将将二进制字节码转换为可直接运行的本地机器码并运行。流程图如下:

JVM也会根据使用场景划分内存区域,当内存不足时会自动触发垃圾回收(GC)。为了将主机的性能最大化发挥,有时我们还需要进行JVM调优。
下面依次对上面的内容进行展开说明。

2. 字节码生成

通过上面的简述我们已经知道,java语言中是用过javac程序将java文件编译成class文件的,编译的过程大约分为如下四步:
(1)词法分析器:将代码(字符流)中关键字和标识符等内容解析转换成Token流,token流就是一组对应源码字符集和的单词序列;
(2)语法分析器:解析Token流中package关键字声明、import关键字声明和class主体信息,组建成更加结构话的语法树;
(3)语义分析器:对语法树进一步处理,包括添加默认构造函数、检查变量初始化、常量合并处理、检查操作变量类型是否匹配、检查操作语句是否可达、异常是否捕获或抛出、接触java语法糖等;
(4)代码生成器:调用com.sun.tools.javac.jvm.Gen类遍历语法树,生成最终字节码;
过程图如下:

3. Class文件结构

Class文件是一组以8位字节为基础范围的二进制刘,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符。一个Class文件主要包含如下内容:

魔数和Class文件版本

头4个字节为魔数,0xCAFEBABE。
紧跟着魔数的4个字节存储的是Class文件的版本号,其中第7、8位保存的是主版本号。

常量池

可理解为Class文件之中的资源仓库,由于常量池中常量的数量是不固定的,所以在常量池入口放置一个u2类型的数据,代表常量池计数值。常量池中主要存放两类常量:字面量和符号引用。字面量即常量,符号引用包含类和接口的全限定名、字段的名称和描述符和方法的名称和描述符。

访问标识

紧跟在常量池后的2个字节,标识一些类或接口层次的访问信息,如:是类还是接口、是否为public类型、是否为abstract类型,是否为final等。

类索引、父索引与接口索引集合

类索引和父索引都是u2类型,而接口索引是一组u2类型数据集合。class文件用这三个数据来确定这个类的继承关系。

字段表集合

字段表用于描述接口或者声明的变量,字段包括类变量和实例变量,但不包括局部变量。

方法表集合

结构和字段表一致,保存方法的属性。注意,不包含方法的代码。

属性表集合

包含若干个属性。其中,
code属性储存方法的代码,
Exceptions属性存储throws关键字后的列举的异常,
lineNumberTablee属性存储java源码和字节码行号的对应关系,
localVariableTable属性记录栈帧中局部变量表中的变量和java源码中定义的变量之间的关系,
sourceFile属性记录生成这个class文件的源码文件名称,
ConstantValue属性通知JVM自动为静态变量赋值,
InnerClasses属性记录内部类信息。

4. 动态编程与静态编程

静态编程:类型检查是在编译时完成的。

动态编程:类型检查是在运行时完成的。

所谓动态编程就是绕过编译过程在运行时进行操作的技术,在Java中有如下几种方式:

反射
这个搞Java的应该比较熟悉,原理也就是通过在运行时获得类型信息然后做相应的操作。

动态编译
动态编译是从Java 6开始支持的,主要是通过一个JavaCompiler接口来完成的。通过这种方式我们可以直接编译一个已经存在的java文件,也可以在内存中动态生成Java代码,动态编译执行。

调用JavaScript引擎
Java 6加入了对Script(JSR223)的支持。这是一个脚本框架,提供了让脚本语言来访问Java内部的方法。你可以在运行的时候找到脚本引擎,然后调用这个引擎去执行脚本。这个脚本API允许你为脚本语言提供Java支持。

动态生成字节码
这种技术通过操作Java字节码的方式在JVM中生成新类或者对已经加载的类动态添加元素。

操作java字节码的工具有两个比较流行,一个是ASM,一个是Javassit 。

ASM :直接操作字节码指令,执行效率高,要是使用者掌握Java类字节码文件格式及指令,对使用者的要求比较高。

Javassit 提供了更高级的API,执行效率相对较差,但无需掌握字节码指令的知识,对使用者要求较低。

应用层面来讲一般使用建议优先选择Javassit,如果后续发现Javassit 成为了整个应用的效率瓶颈的话可以再考虑ASM.当然如果开发的是一个基础类库,或者基础平台,还是直接使用ASM吧,相信从事这方面工作的开发者能力应该比较高。

Java 字节码以二进制的形式存储在 .class 文件中,每一个 .class 文件包含一个 Java 类或接口。Javaassist 就是一个用来 处理 Java 字节码的类库。它可以在一个已经编译好的类中添加新的方法,或者是修改已有的方法,并且不需要对字节码方面有深入的了解。同时也可以去生成一个新的类对象,通过完全手动的方式。

java虚拟机 — 字节码生成相关推荐

  1. Java虚拟机字节码指令概述

    虚拟机字节码指令 Java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成. 一 基 ...

  2. java 虚拟机 字节码,JAVA虚拟机:虚拟机字节码执行引擎

    "虚拟机"是一个相对"物理机"的概念,这两种机器都有代码执行能力. 物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的. 虚拟机的执行引擎由自己 ...

  3. 深入理解Java虚拟机 - 字节码指令集

    Java虚拟机的指令由一个字节长度的. 代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成. 字节码与数据类型 在J ...

  4. Java虚拟机字节码指令

    Java字节码指令 Java 字节码指令及javap 使用说明 ### java字节码指令列表 字节码 助记符 指令含义 0x00 nop 什么都不做 0x01 aconst_null 将null推送 ...

  5. java 虚拟机字节码指令表

    字节码 助记符 指令含义 0x00 nop 什么都不做. 0x01 aconst_null 将 null 推送至栈顶. 0x02 iconst_m1 将 int 型-1 推送至栈顶. 0x03 ico ...

  6. java虚拟机调用linux_Java虚拟机字节码执行引擎

    定义 Java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...

  7. 深入理解Java虚拟机(周志明第三版)- 第八章:虚拟机字节码执行引擎

    系列文章目录 第一章: 走近Java 第二章: Java内存区域与内存溢出异常 第三章: Java垃圾收集器与内存分配策略 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言 ...

  8. 深入理解java虚拟机-第五章:虚拟机字节码执行引擎

    本章将介绍虚拟机如何调用方法 一.java虚拟机字节码执行引擎 执行引擎在执行代码的时候可能有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种. 执行流程:输入的是字节码文件 ...

  9. 虚拟机字节码执行引擎

    1 概述 执行引擎是Java虚拟机核心的组成部分之一."虚拟机"是一个相对于"物理机"的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处 ...

最新文章

  1. JDBC连接执行MySQL存储过程报空指针或权限错误
  2. spring框架学习(三)junit单元测试
  3. nginx反向代理和负载均衡
  4. 问题解决:java.sql.SQLException:Value '0000-00-00' can not be represented as java.sql.Date
  5. dw2020表格不可见_【分享表格模板】手把手教你算小目标实际本金和综合年化收益率...
  6. 更适合私有云的网络部署模式-动态路由
  7. Angr安装与使用之使用篇(二)
  8. Windows XP下用Modem发送传真(ZZ)
  9. android 设置圆形图片,android 圆形头像,自定义圆形ImageView
  10. 随机数生成方法总计(附代码
  11. Tabs | jQuery UI
  12. 解决 “VS2015 的warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失”的方法
  13. 使用JLink SEGGER_RTT_printf()函数实现打印浮点数
  14. 双服务器架构实战飞桨部署-自动上色和老相片修复
  15. Flightmare: A Flexible Quadrotor Simulator 无人机仿真器
  16. 腾讯云服务器违规封禁数据恢复和迁移教程,腾讯云账号违规被封如何解封迁移数据
  17. 常用的Latex格式(overleaf中使用)
  18. 如何设置Exchange-Ecp的管理员
  19. XBee ZB模块常见问题
  20. 利用iStylePDF的API实现在PDF文档中动态插入一幅图片

热门文章

  1. jquery双重循环
  2. 为什么有的.pth文件储存的是数字有些.pth储存的是网络结构?
  3. 插入排序与希尔排序(数据结构)
  4. 2018, say goodbye!
  5. 这是一本书名“自学是门手艺:没有自学能力的人没有未来”
  6. 大学谈恋爱是否应该门当户对
  7. 台式计算机购买cpu,如何选购台式机电脑CPU?看完你就会明白
  8. LOL峡谷之巅前500爬取
  9. 小红书笔试-3.26
  10. C++项目目录组织结构