字节码
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;
}
}
![](/qrcode.jpg)
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");
}
}
}