字节码文件该如何理解|Java中字节码文件怎么理解由解释器执行由浏览器执行

|

『壹』 java编程中source code和bytecode有什么区别,不要太详细的

1、表达不同

源代码是源代码。字节码称为字节码。它是源程序文件生成的类文件,在通过Java编译器后使用扩展名java生成。它的扩展是类。

2、角色是不同的

字节码是包含可执行程序的二进制文件,该可执行程序由一系列操作码/数据对组成。字节码是一种中间代码,它比机器代码更抽象,需要翻译器转换成机器代码的中间代码。无论硬件环境如何,字节码主要用于实现特定的软件操作和软件环境。字节码的实现是通过编译器和虚拟机实现的。

这是我们根据Java语言规范编写的源程序文件,扩展名为java。

3、用法不同

字节码是中间状态(中间代码)的二进制代码(文件)。您需要将解释器转换为机器代码。写入运行操作(WORA)实际上是由字节码实现的。

通常它已经编译,但它与特定的机器代码无关。字节码通常不像源代码那样可读,而是一系列编码数字常量,引用,指令等。

『贰』 什么是Java字节码

它是程序的一种低级表示,可以运行于Java虚拟机上。将程序抽象成字节码可以保证Java程序在各种设备上的运行Java号称是一门“一次编译到处运行”的语言,从我们写的java文件到通过编译器编译成java字节码文件(.class文件),这个过程是java编译过程;而我们的java虚拟机执行的就是字节码文件。不论该字节码文件来自何方,由哪种编译器编译,甚至是手写字节码文件,只要符合java虚拟机的规范,那么它就能够执行该字节码文件。JAVA程序的运行因为Java具有跨平台特性,为了实现这个特性Java执行在一台虚拟机上,这台虚拟机也就是JVM,Java通过JVM屏蔽了不同平台之间的差异,从而做到一次编译到处执行。JVM位于Java编译器和OS平台之间,Java编译器只需面向JVM,生成JVM能理解的代码,这个代码即字节码,JVM再将字节码翻译成真实机器所能理解的二进制机器码。字节码是怎么产生的?我们所编写的程序都是.java格式,通常在执行的时候也许点击一下eclipse的运行键就可以在控制台看到运行结果,但是也可以更酷一些,如果你装了JDK,那就可以直接在以命令行的方式编译运行你的.java文件,编译后会形成.class文件,这个.class文件即字节码。字节码怎么解读?上图是编译好的字节码文件,即一堆16进制的字节,如果使用IDE去打开,也许看到的是已经被反编译的我们所熟悉的java代码,但这才是纯正的字节码这里只介绍字节码由哪些部分组成, 具体的意思自行网络或者看文尾的连接, 有较为详细的讲解上图即字节码文件的组成部分, Class文件的结构不像XML等描述语言那样松散自由。由于它没有任何分隔符号,所以,以上数据项无论是顺序还是数量都是被严格限定的。哪个字节代表什么含义,长度是多少,先后顺序如何,都不允许改变, 如上图左侧即每一部分规定的长度魔数(Magic Number)魔数是用来区分文件类型的一种标志,一般都是用文件的前几个字节来表示。比如0XCAFE BABE表示的是class文件,那么有人会问,文件类型可以通过文件名后缀来判断啊?是的,但是文件名是可以修改的(包括后缀),那么为了保证文件的安全性,将文件类型写在文件内部来保证不被篡改。至于为什么是CAFE BABE估计大家也能猜到, 程序员与咖啡的不解之缘版本号(Version)版本号含主版本号和次版本号,都是各占2个字节。在此Demo种为0X0000 0033。其中前面的0000是次版本号,后面的0033是主版本号。通过进制转换得到的是次版本号为0,主版本号为51。高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件,即使文件格式未发生任何变化. 这就是target参数的用处,可以在使用JDK 1.7编译时指定-target 1.5常量池(Constant Pool)常量池是Class文件中的资源仓库, 量池中主要存储2大类常量:字面量和符号引用。字面量如文本字符串,java中声明为final的常量值等等,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符。常量池是一个表结构,在表的内容前有一个类型的计数器,表示常量池的长度上面的表中描述了11中数据类型的结构,其实在jdk1.7之后又增加了3种(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)。这样算起来一共是14种访问标志(Access_Flag)访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final。通过上面的源代码,我们知道该文件是类并且是public。0x 00 21:是0×0020和0×0001的并集。其中0×0020这个标志值涉及到字节码指令类索引(This Class Name)类索引用于确定类的全限定名0×00 03 表示引用第3个常量,同时第3个常量引用第19个常量,查找得”com/demo/Demo”。#3.#19父类索引(Super Class Name)0×00 04 同理:#4.#20(java/lang/Object)接口索引(Interfaces)通过上边字节码图可以看到,这个接口有2+n个字节,前两个字节表示的是接口数量,后面跟着就是接口的表。我们这个类没有任何接口,所以应该是0000。果不其然,查找字节码文件得到的就是0000。字段表集合(fields)字段表用于描述类和接口中声明的变量。这里的字段包含了类级别变量以及实例变量,但是不包括方法内部声明的局部变量。接下来就是2+n个字段属性。我们只有一个属性a,所以应该是0001。查找文件果不其然是0001。该区域含有字段的访问标志, 访问权限, 字段的名称索引, 字段的描述符索引, 属性表 描述符的作用就是用来描述字段的数据类型、方法的参数列表和返回值。而属性表就是为字段表和方法表提供额外信息的表结构。对于字段来说,此处如果将字段声明为一个static final msg = "aaa"的常量,则字段后就会跟着一个属性表,其中存在一项名为ConstantValue,指向常量池中的一个常量,值为的"aaa"。 方法(methods)包含访问标志表, 方法名索引 , 方法描述符索引, 属性表数量,等Attribute0×0001 :同样的,表示有1个Attributes了。0x000f : #15(“SourceFile”)0×0000 0002 attribute_length=20×0010 : sourcefile_index = #16(“Demo.java”)SourceFile属性用来记录生成该Class文件的源码文件名称。

『叁』 Hermes源码分析(二)——解析字节码

前面一节 讲到字节码序列化为二进制是有固定的格式的,这里我们分析一下源码里面是怎么处理的

这里可以看到首先写入的是魔数,他的值为

对应的二进制见下图,注意是小端字节序

第二项是字节码的版本,笔者的版本是74,也即 上图中的4a00 0000 第三项是源码的hash,这里采用的是SHA1算法,生成的哈希值是160位,因此占用了20个字节

第四项是文件长度,这个字段是32位的,也就是下图中的为0aa030,转换成十进制就是696368,实际文件大小也是这么多

后面的字段类似,就不一一分析了,头部所有字段的类型都可以在 BytecodeFileHeader.h 中看到,Hermes按照既定的内存布局把字段写入后再序列化,就得到了我们看到的字节码文件。

这里写入的数据很多,以函数头的写入为例,我们调用了visitFunctionHeader方法,并通过byteCodeMole拿到函数的签名,将其写入函数表(存疑,在实际的文件中并没有看到这一部分)。注意这些数据必须按顺序写入,因为读出的时候也是按对应顺序来的。

我们知道react-native 在加载字节码的时候需要调用hermes的prepareJavaScript方法, 那这个方法做了些什么事呢?

这里做了两件事情: 1. 判断是否是字节码,如果是则调用createBCProviderFromBuffer,否则调用createBCProviderFromSrc,我们这里只关注createBCProviderFromBuffer 2.通过BCProviderFromBuffer的构造方法得到文件头和函数头的信息(populateFromBuffer方法),下面是这个方法的实现。

BytecodeFileFields的populateFromBuffer方法也是一个模版方法,注意这里调用populateFromBuffer方法的是一个 ConstBytecodeFileFields对象,他代表的是不可变的字节码字段。

细心的读者会发现这里也有visitFunctionHeaders方法, 这里主要为了复用visitBytecodeSegmentsInOrder的逻辑,把populator当作一个visitor来按顺序读取buffer的内容,并提前加载到BytecodeFileFields里面,以减少后面执行字节码时解析的时间。

Hermes引擎在读取了字节码之后会通过解析BytecodeFileHeader这个结构体中的字段来获取一些关键信息,例如bundle是否是字节码格式,是否包含了函数,字节码的版本是否匹配等。注意这里我们只是解析了头部,没有解析整个字节码,后面执行字节码时才会解析剩余的部分。

evaluatePreparedJavaScript这个方法,主要是调用了HermesRuntime的 runBytecode方法,这里hermesPrep时上一步解析头部时获取的BCProviderFromBuffer实例。

runBytecode这个方法比较长,主要做了几件事情:

这里说明一下,Domain是用于垃圾回收的运行时模块的代理, Domain被创建时是空的,并跟随着运行时模块进行传播, 在运行时模块的整个生命周期内都一直存在。在某个Domain下创建的所有函数都会保持着对这个Domain的强引用。当Domain被回收的时候,这个Domain下的所有函数都不能使用。

未完待续。。。

『肆』 字节码文件

    .java源文件经过编译生成的.class便是字节码文件,但还不能被系统直接执行,通过JVM解释翻译后才可以被底层系统执行。     1.魔数:头四个字节,CAFEBABE     2.文件版本:java版本1.8 = 52,1.7 = 51……     3.常量池:包含两部分 — 字面量与符号引用         ① 字面量:字符串文本、用final修饰的基本数据类型的值。(如申明的:String s = "abc";中的"abc",int i = 1;中的1)。大白话:字面量是在编译期间就已有确定值的数据。         ② 符号引用:类、接口、方法、字段的全名与描述符。在编译时,java类并不知道引用类的实际内存地址,因此只能使用符号引用来代替。在类加载器链接阶段时才替换为具体的实际内存地址,即直接引用。     4.访问标志:(类、属性、方法)的访问标志         是class还是interface,是否public,是否abstract,是否定义了final等等。     5.类/父类索引与接口索引集合         类、父类、接口集合的全限定名。     6.字段表集合         声明的类变量与实例变量的描述与结构。     7.方法表集合         声明的方法的描述与结构。     8.属性表集合         描述class文件,字段表,方法表某些场景专有的信息。

『伍』 Java中字节码文件怎么理解由解释器执行,由浏览器执行

“java解释器就是把在java虚拟机上运行的目标代码(字节码)解释成为具体平台的版机器码的程序。”即jdk或权jre目录下bin目录中的java.exe文件,而javac.exe是编译器。 运行java程序的过程是先用javac编译,然后用java解释。而一经编译成功后,就可以直接用java.exe随处解释运行了。网页浏览器只是自带了javascript的解释器,其他语言的解释器没有。至于有些语言如java等可以在浏览器上运行是因为浏览器通过插件的形式支持的

『陆』 北大青鸟java培训:字节码指令的编译与执行

java编程开发是目前市场上使用范围非常广泛的一种编程开发语言。今天我们就一起来了解一下,在java编程中关于字节码的一些指令的编译与执行方法。java文件编译后的class文件,java跨平台的中间层,JVM通过对字节码的解释执行(执行模式,还有JIT编译执行,下面讲解),屏蔽对操作系统的依赖。一个字节(8位)可以储存256中不同的指令,这样的指令就是字节码,java所有指令有200个左右,这些指令组成了字节码文件(.class)。一、字节码的主要指令:.class文件里面的十六进制文件,其中CAFEBABE是标志这个文件为java的编译后的文件,00000034代表版本号,01670700一个字节(8位)就是一个字节指令,由于数值指令太难看懂,我们可以用javap将指令翻译为助记指令。1、加载或储存指令在栈帧中,通过指令操作数据在局部变量表与操作栈间传递。ILOAD、ALOAD:将int、对象引用类型从局部变量表压入操作栈顶;ISTORE、ASTORE:将int、对象引用类型从操作栈顶储存到局部变量表里;ICONST、BIPUSH、SIPUSH、LDC:将常亮加载到操作栈顶。2、运算指令对操作栈上的值进行运算,并把结果写入操作栈顶,如IADD、IMUL。3、类型转换指令I2L、D2F4、对象创建与访问指令NEW除了字节码指令外,湖北电脑培训http://www.kmbdqn.cn/认为还包括像LINENUMBER储存字节码与源码对应,方便调试定位;LOCALVARIABLE储存当前方法使用到的局部表量表。二、java源码文件转化为字节码(.class)文件的过程JAVA源文件———->词法解析———->语法解析———->语义分析———>生成字节码———>字节码文件词法分析:根据空格分割出单词、操作符等,形成token信息流;语法分析:根据token流和java语法规范生成语法树;语义分析:检查关键字、类型匹配是否正确;

『柒』 JVM_字节码文件(ClassFile)详解

我们知道 javac 命令可以将 .java 文件编译成 .class 文件,而这个 Class 文件 中包含了 Java虚拟机 指令集、符号表以及若干其他辅助信息;最终将在 Java虚拟机 运行。

本文是以 JVM8 为例的。

每一个 Class文件 都有如下的 ClassFile 文件结构:

先简单介绍一下 ClassFile 文件结构各部分含义:

描述符是表示字段或方法类型的字符串。

字段描述符表示类、实例或局部变量的类型。

从上面文法可以看出,字段描述符中一共有三个类型:

方法描述符包含 0 个或者多个参数描述符以及一个返回值描述符。

看了描述符,可能大家有点疑惑,泛型信息怎么表示啊?

常量池的通用格式如下:

目前 JVM8 中一共用 14 种常量类型,分别如下:

我们知道要使用一个字段或者调用一个方法,就必须知道字段或者方法所属类符号引用,和字段的名字和类型,方法的名字和方法参数类型以及方法返回值类型。 但是我们知道类是能继承的,那么子类调用父类的方法或者字段,这里的所属类符号引用,到底是子类本身还是父类的呢?

我们知道类,方法,字段都有不同的访问标志,在 Class 文件 中使用一个 u2 类型数据项来存储,也就是最多可以有 16 个不同标志位。 在类,方法,字段中有相同的标志,也有不同的标志,总体规划,我们可以借助 Modifier 类的源码来了解:

在 Modifier 类中,类的访问标志:

我们知道在 java 中类可以用的修饰符有: public , protected , private , abstract , static , final , strictfp 。

但是我们再看 Class 文件 中类的访问标志:

仔细看,你会发现有些不同点:

在 Modifier 类中,字段的访问标志:

我们知道在 java 中字段可以用的修饰符有: public , protected , private , static , final , transient 和 volatile 。

但是我们再看 Class 文件 中字段的访问标志:

Class 文件 中字段的访问标志和 java 中字段的修饰符差不多,只是多了 ACC_SYNTHETIC 和 ACC_ENUM 两个标志。

在 Modifier 类中,方法的访问标志:

我们知道在 java 中方法可以用的修饰符有: public , protected , private , abstract , static , final , synchronized , synchronized 和 strictfp 。

但是我们再看 Class 文件 中方法的访问标志:

字段详情 field_info 的格式如下:

方法详情 method_info 的格式如下:

关于 Class 文件 中属性相关信息,我们再后面章节介绍。

我们可以通过 javap 的命令来阅读 Class 文件 中相关信息。

这个是最简单的一个类,没有任何字段和方法,只继承 Object 类,我们来看看它编译后的字节码信息,通过 javap -p -v T.class 的命令:

我们重点关注常量池相关信息,会发现虽然 T.class 很干净,但是也有 15 个常量,来我们依次分析:

与之前的例子相比较,多了一个字段和方法,那么得到的字节码信息如下:

但是你会发现常量池中怎么没有这个字段 name 的 CONSTANT_Fieldref_info 类型的常量呢? 那是因为我们没有使用这个字段。

多写了一个方法 test1 来调用 name 字段和 test 方法,那么得到的字节码信息如下:

这里定义一个父类 TParent ,有一个公共字段 name 和方法 say 。子类

『捌』 JAVA编程中source code和bytecode有什么区别,不要太详细的

soucecode是源代码,也就是后缀名为java的文件bytecode是二进制文件,也就是后缀名为class的文件希望能看看我写的《java编程那些事儿》一书

『玖』 什么是字节码文件

字节码文件就是以.class文件结尾的文件,是通过javac命令编译过生成的。因为java不是编译型语言,所以它需要去解释字节码文件才能够运行。

『拾』 Java里的字节码和源代码分别啥意思,和起到什么左右

/*java是一门高级编程语言,是用来写程序代码的。用java写的文本(字符串序列)就是源代码。计算机不能直接执行源代码,必须用一个叫编译器的程序(javac.exe)将源代码翻译成字节码,然后让一个叫解释器的程序(java.exe)去执行字节码,即运行程序。下面的就是一个小程序的源代码,功能是输出九九乘法表。下图中的Test.class就是这个源代码文件翻译后的由字节码组成的文件。而最下面的那个黑框就是程序执行后的结果。java Test就是在执行Test.class字节码文件,即运行这个程序。*///这下面的就是源代码public class Test {public static void main(String[] args) {int i,j;for(i=1;i<=9;i++) {for(j=1;j<=i;j++)System.out.printf("%dx%d=%-4d",j,i,j*i);System.out.println();}}}


赞 (0)