码迷,mamicode.com
首页 > 编程语言 > 详细

java字节码

时间:2019-09-28 18:25:11      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:notepad++   ++   href   flags   style   try   版本   lang   str   

一、“一处编译到处运行”

    原因就是字节码,由于不同的平台编译出来的机器码0,1是不同的,java采用不直接编译成机器码(0,1)而是把他们编译成字节码。再由不同平台上的JVM翻译成对应平台的机器码(0,1)。如今,JVM也不再只支持Java,由此衍生出了许多基于JVM的编程语言,如Groovy, Scala, Koltin等等。

技术图片

 

 

 而字节码命令所能提供的语义描述能力是要明显强于Java本身的,所以有其他一些同样基于JVM的语言能提供许多Java所不支持的语言特性。

二、如何看.class文件的十六进制文件格式

技术图片

 

 

 用NotePad++直接打开显示乱码,我们点开插件--插件管理。然后选择上面标记的地方,然后点安装。

安装后重新打开.class文件,我们发现还是乱码。点插件---HEX-Editor然后选择View in HEX就可以了

三、如何看字节码文件,我们可以使用JDK提供的javap命令进行反编译.class,具体用法如下。实际过程中我们直接利用IDE看就可以了,例如IDEA直接选中java文件然后View---Show Bytecode就可以看了(首先这个java文件得编译,没有编译在Build中选重新编译一下即可)

技术图片

四:解读字节码

技术图片
package test;
public class ReadBytecode {
    private boolean bo;
    private byte b;
    private char c;
    private short s;
    private float f;
    private double d;
    private int i;
    private long l;
    private Integer id;
    private String name;
    public void m1(){}
    public int m2(){
        return 1;
    }
    public static void main(String[] args) {

    }
}


//字节码
// class version 52.0 (52)
// access flags 0x21
public class test/ReadBytecode {

  // compiled from: ReadBytecode.java

  // access flags 0x2
  private Z bo

  // access flags 0x2
  private B b

  // access flags 0x2
  private C c

  // access flags 0x2
  private S s

  // access flags 0x2
  private F f

  // access flags 0x2
  private D d

  // access flags 0x2
  private I i

  // access flags 0x2
  private J l

  // access flags 0x2
  private Ljava/lang/Integer; id

  // access flags 0x2
  private Ljava/lang/String; name

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 8 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Ltest/ReadBytecode; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public m1()V
   L0
    LINENUMBER 19 L0
    RETURN
   L1
    LOCALVARIABLE this Ltest/ReadBytecode; L0 L1 0
    MAXSTACK = 0
    MAXLOCALS = 1

  // access flags 0x1
  public m2()I
   L0
    LINENUMBER 21 L0
    ICONST_1
    IRETURN
   L1
    LOCALVARIABLE this Ltest/ReadBytecode; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x9
  public static main([Ljava/lang/String;)V
    // parameter  args
   L0
    LINENUMBER 25 L0
    RETURN
   L1
    LOCALVARIABLE args [Ljava/lang/String; L0 L1 0
    MAXSTACK = 0
    MAXLOCALS = 1
}
View Code

分析上面代码我们可以得到,52是版本号代表java8,因为java的版本号从45开始,除1.0和1.1都是使用45.x外,以后每升一个大版本,版本号加一。也就是说,编译生成该class文件的jdk版本为1.8.0。

大多数的基本数据类型用其首字母大写 (除了long 类型用J,boolean用Z),引用类型用L表示并且以;结束。变量名会在后面写。方法返回值类型中多了V(void)。init方法返回值为V。init方法除了执行构造方法,还会进行初值的赋值等例如我们上面给一个变量赋一个初值,那么动作也是在这里执行的。从主方法的参数我们可以看出数组用[lxx类型.   二位数组[[L依次类推。

分析上面的构造方法:

L0 L1是方法中字节码行号依次类推L2 L3。。。

LINENUMBER         字节码偏移量,即字节码和源码行数的偏移量。在发生异常的时候可以找到对应的源码位置(可以通过修改编译参数去掉,去掉的话出现异常编译器不会找到源代码异常发生处)

ALOAD 0                 将引用型变量压入栈顶,此处就是把调用的方法压入栈顶

INVOKESPECIAL   调用后面的方法

RETURN                 弹栈

LOCALVARIABLE   帧栈中定义的局部变量与源码定义的变量之间的关系。如果没有这项信息(通过修改编译参数可以去掉),别人引用这个方法的时候无法获取参数名称,取而代之的是arg0,arg1这样的占位符。

每个实例方法中,都会有一个默认参数this. LOCALVARIABLE  后第一个参数为参数名称,第二个参数类型,第三第四个参数为这个参数在字节码中的可见行范围,最后一个参数表示这个参数在这个桢栈中的位置,例如上面的0。

MAXSTACK     最大操作数栈,JVM会根据这个值来分配栈桢中的操作栈深度,上面为1

MAXLOCALS   局部变量所需的存储空间,单位为Slot。Slot为JVM为局部变量分配内存的最小单位,大小为4个字节。这里的局部变量包括方法参数(包括隐藏的this)、方法内的局部变量、try--catch中catch()定义的参数。注意MAXLOCALS 并不一定等于所有局部变量的Slot和,因为局部变量中的Slot可以重用。

分析下面的m1()方法。很简单因为没有执行语句所以直接弹栈,MAXSTACK为0;

分析m2()方法:

   ICONST_1    将int型1推送到栈顶

   IRETURN     从当前方法返回int型数据

分析主方法:由于是static 方法所以不会有this

更多字节码指令查询:https://blog.csdn.net/zqz_zqz/article/details/79484757

 

java字节码

标签:notepad++   ++   href   flags   style   try   版本   lang   str   

原文地址:https://www.cnblogs.com/chengxuyuan-liu/p/11603899.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!