JVM 之 字节码指令

字节码

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

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

指令集架构种类

基于栈(JVM)
基于寄存器

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

字节码指令

解析class文件

javap -verbose Hello.class

1.加载和存储指令

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

存储:
istore

public class Hello{
    public int hello(int a, int b){
        return 1+1;
    }
}

2.运算指令

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

public class Hello{
    public int hello(int a, int b){
        int c = a+b;
        int d = a-b;
        int e = a*b;
        int f = a/b;
        int g = a%b;
        int h = -a;
        return 1+1;
    }
}

3.类型转换指令

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

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

public class Hello{
    public int hello(int a, int b){
        long c = a;
        byte d = (byte)b;
        return 1+1;
    }
}

4.对象创建与访问

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

public class Hello{
    public static void hello(int a, int b){
        User user = new User();
        User[] us = new User[5];
        user.name = "hello";
    }
}

class User{
    String name;
    static int age;
}

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

public class Hello{
    public static void hello(int a, int b){
        if (a  == b){
            System.out.println("a == b");
        }else{
            System.out.println("a != b");
        }
    }
}

7.方法调用指令

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

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

public class Hello{
    public static void hello(int a, int b){
        Service service = new ServiceImpl();
        service.add(1,2);
    }
}

interface Service {
   public int add(int a, int b);
}

class  ServiceImpl implements Service{
   public int add(int a, int b){
        return a+b;
    }
}

8.异常处理指令

athrow:抛出异常

public class Hello{
    public static void hello(int a, int b){
        throw new RuntimeException("ddddd");
    }
}

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

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

9.同步指令

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

public class Hello{
    public static void hello(int a, int b){
        synchronized (Hello.class){
            System.out.println("dddddd");
        }
    }
}

发布了194 篇原创文章 · 获赞 13 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013919153/article/details/105357510
今日推荐