一段java代码是如何执行的

网友投稿 525 2022-05-30

1. 编译成class

众所周知,java代码是不能直接在jvm上执行的,执行的是class文件,将java代码编程class文件,需要编译

常用的编译方法是:javac xxx.java

但目前常见的java编辑工具,如eclipse和ideal都自带自动编译动能

2. jvm的构成

让我们回忆一下jvm的构成:

主题上分为五个部分:

方法区,本地方法栈,java堆,java栈,程序计数器

其中,java栈,本地方法栈,程序计数器为线程私有,其余为线程共享

那么,方法在哪个地方执行呢?

java栈。

栈的遵循的方式是先进后出,java栈中方法的执行也遵循此规律,方法执行的步骤又称为栈帧。

3. 方法的顺序执行和栈帧

上代码:

-Java 代码

public class Main { public static void a(){ b(); } public static void b(){ c(); } public static void c(){ System.out.println("Hello world!"); } public static void main(String[] args) { a(); } }

上面是一段很简单的代码,主体上就是:

(1)一个Main类

(2)上面定义了一个main方法

(3)该main方法调用了静态方法a

(4)方法a调用方法b

(5)方法b调用方法c

(6)方法c打印了“Hello world!”

前文说过,java定义的非本地方法都是在java栈内执行的,一方法一栈帧

所以假设

mian方法对应栈帧m

a方法对应栈帧a

b方法对应栈帧b

c方法对应栈帧c

根据方法的调用,入栈顺序为:m,a,b,c

所以,栈帧出栈(即方法执行)顺序为:c,b,a,m

4. class文件反编译过后的样子

上一节,方法或栈帧在java栈的执行顺序

但在方法体内的内容是怎么执行的呢。

前文提到,jvm执行的是class文件,而class文件内是什么?

class文件内是一组指令集

如何证明呢,还是再看一段代码。

-Java 代码

public class Calculator{ public int add(){ int n = 10; int m = 20; int r = n + m; return r; } public static void main(String[] args) { Calculator calculator = new Calculator(); int a = calculator.add(); System.out.println(a); } }

如上代码,实现的功能是:

(1)定义两个变量,相加

(2)main方法new对象,调用方法

但,class文件是不可以直接查看的。

我们可以采用反编译的方法,反编译命令:、

javap -c xxx.class

上述文件反编译后的样子如下:

每个方法下面的Code,都是一组指令集。

5. 指令集详解

在讨论指令集之前,首先要讲一个概念,那就是对栈帧进一步拆分。

栈帧一共分为四个部分:局部变量表、操作数栈、动态链接、方法返回地址

其中,局部变量表和操作数栈是最重要的两个部分

局部变量表存放在方法中定义的局部变量

操作数栈相当于jvm的一个缓存

所有的操作都必须在此处进行

所有的变量都必须加载到操作数栈才能被使用

所以,所谓指令,就是在局部变量表和操作数栈来回倒腾的过程。

下面对指令进行分类讲解:

(1)入栈指令

整型入栈指令:

取值-1~5采用iconst指令;

取值-128~127采用bipush指令;

取值-32768~32767采用sipush指令;

取值-2147483648~2147483647采用ldc指令。

非整型入栈指令:

float,String类型也使用ldc指令

double和long类型使用ldc_2w

boolean类型视作0和1

null的入栈指令为:aconst_null

(2)存储指令

一段java代码是如何执行的

将操作数栈中的常量保存在局部变量表中的某个位置

如:

istore_1:将上面入栈的整型常量保存在局部变量表中的第1个位置

fstore_2:将上面入栈的浮点常量保存在局部变量表中的第2个位置

dstore_10:将上面入栈的双浮点常量保存在局部变量表中的第10个位置

lstore_20:将上面入栈的长整常量保存在局部变量表中的第20个位置

astore_100:将上面入栈的引用常量保存在局部变量表中的第100个位置

(3)变量入栈指令

iload_1:局部变量表中的第1个位置的整型变量入栈

fload_2:局部变量表中的第1个位置的浮点型变量入栈

dload_10:局部变量表中的第1个位置的双浮点型变量入栈

lload_20:局部变量表中的第1个位置的长整型变量入栈

aload_100:局部变量表中的第100个位置的引用型变量入栈

(4)计算指令

加:iadd、ladd、fadd、dadd

减:isub、lsub、fsub、dsub

乘:imul、lmul、fmul、dmul

除:idiv、ldiv、fdiv、ddiv

注意:栈顶计算,一次只能计算一个表达式

Java JVM

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java杂记(二)
下一篇:华为担纲建设基础软硬件国家新一代AI开放创新平台
相关文章