JVM 之 字节码指令

客官°小女子只卖身不卖艺 2023-07-23 04:55 108阅读 0赞

字节码

JVM指令(操作码)由一个字节长度,后面跟着0或者多个参数构成。

操作码的长度为1字节,所以最大有256条操作码。为了支持更多的指令,字节码有时一个会表示多个类型。

指令集架构种类

基于栈(JVM)
基于寄存器

字节码与数据类型
大多数指令包含数据类型,也有不包含的(Goto, ArrayLength操作数据类型)
iload fload,字节码指令前面是数据类型

字节码指令

解析class文件

javap -verbose Hello.class

1.加载和存储指令

作用:将数据在栈帧中的局部变量表操作数栈之间来回传输。
加载:
iload:将局部变量表加载到操作数栈
ipush:将常量加载到操作数栈

存储:
istore

  1. public class Hello{
  2. public int hello(int a, int b){
  3. return 1+1;
  4. }
  5. }

20200407094924467.png

2.运算指令

add, sub, mul, div, rem(取余), neg(取反)

  1. public class Hello{
  2. public int hello(int a, int b){
  3. int c = a+b;
  4. int d = a-b;
  5. int e = a*b;
  6. int f = a/b;
  7. int g = a%b;
  8. int h = -a;
  9. return 1+1;
  10. }
  11. }

20200407095457345.png

3.类型转换指令

什么时候出现
1.用户代码区显示转换
2.字节码中类型转换指令(指令不够)

宽化类型窄化类型处理(向下向上转换)

  1. public class Hello{
  2. public int hello(int a, int b){
  3. long c = a;
  4. byte d = (byte)b;
  5. return 1+1;
  6. }
  7. }

20200407095709317.png

4.对象创建与访问

创建类实例的指令:new
创建数据的指令:newarray, anewarray, multianewarray
访问类字段:getfield putfield getstatic putstatic
把数组元素加载到操作数栈:baload
将操作数栈存到数组元素:astore
取数组长度:arraylength
检查实例类型的指令:instanceof checkcast

  1. public class Hello{
  2. public static void hello(int a, int b){
  3. User user = new User();
  4. User[] us = new User[5];
  5. user.name = "hello";
  6. }
  7. }
  8. class User{
  9. String name;
  10. static int age;
  11. }

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM5MTkxNTM_size_16_color_FFFFFF_t_70

5.操作数栈管理指令

出栈:pop pop2
复制栈顶一个或者两个数值并将复制或者双份复制值重新压入栈顶:dup dup2 dup_x1 dup_x2
将栈顶的两个数值替换:swap

6.控制转移指令

没有顺序依次执行,而是跳转到其他地方执行。

条件分支:ifeq ifit ifle ifne ifgt ifnull ifcmple
复合分支:tableswitch lookupswitch
无条件分支:goto goto_w jsr jsr_w ret

  1. public class Hello{
  2. public static void hello(int a, int b){
  3. if (a == b){
  4. System.out.println("a == b");
  5. }else{
  6. System.out.println("a != b");
  7. }
  8. }
  9. }

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM5MTkxNTM_size_16_color_FFFFFF_t_70 1

7.方法调用指令

invokevirtual:调用对象的实例方法
invokeinterface:用于调用接口方法
invokespecial:用户调用一些特殊处理的实例方法
(实例初始化方法,私有方法,父类方法等)
invokestatic:用于调用类方法(static方法)

方法返回指令
ireturn(int char short boolean) return(void) freturn dreturn areturn

  1. public class Hello{
  2. public static void hello(int a, int b){
  3. Service service = new ServiceImpl();
  4. service.add(1,2);
  5. }
  6. }
  7. interface Service {
  8. public int add(int a, int b);
  9. }
  10. class ServiceImpl implements Service{
  11. public int add(int a, int b){
  12. return a+b;
  13. }
  14. }

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM5MTkxNTM_size_16_color_FFFFFF_t_70 2

8.异常处理指令

athrow:抛出异常

  1. public class Hello{
  2. public static void hello(int a, int b){
  3. throw new RuntimeException("ddddd");
  4. }
  5. }

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM5MTkxNTM_size_16_color_FFFFFF_t_70 3

如果除以0发现没有athrow,因为异常由除操作抛出

try-catch:出现异常,影响程序性能。不出现异常几乎不影响性能。

9.同步指令

同步一段指令集序列由java中synchronized块来表示,JVM中有monitorenter和monitorexit两条指令来支持synchronized关键字的语义。

  1. public class Hello{
  2. public static void hello(int a, int b){
  3. synchronized (Hello.class){
  4. System.out.println("dddddd");
  5. }
  6. }
  7. }

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM5MTkxNTM_size_16_color_FFFFFF_t_70 4

发表评论

表情:
评论列表 (有 0 条评论,108人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JVM字节指令简介

    引言 众所周知,Java程序是运行在Java虚拟机上的,而这里的“虚拟”是对什么东西进行虚拟呢?答案当然就是对“实体”机进行虚拟啦,虚拟机可以看做是对实体机进行了进一步的封装

    相关 JVM字节指令

    加载和存储指令 加载和存储指令用于将数据在栈帧中的局部变量表和操作数栈之间来回传输,这类指令包括如下内容。 将一个局部变量加载到操作栈: > iload、ilo