关于java:一段java代码是如何执行的

6次阅读

共计 2203 个字符,预计需要花费 6 分钟才能阅读完成。

摘要:当你学会了 java 语言之后,你写了一些代码,而后你想要执行你的代码,来达成某些性能。那么,你都晓得这段 java 代码都是如何执行的吗?

本文分享自华为云社区《一段 java 代码是如何执行的》,原文作者:技术火炬手。

当你学会了 java 语言之后,你写了一些代码,而后你想要执行你的代码,来达成某些性能。那么,你都晓得这段代码都是如何执行的吗?

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)存储指令

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

如:

  • 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

留神:栈顶计算,一次只能计算一个表达式

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0