zoukankan      html  css  js  c++  java
  • java字节码

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

        原因就是字节码,由于不同的平台编译出来的机器码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

  • 相关阅读:
    js中的标签运动
    js的窗口坐标及拖拽
    js中滑动门的实现方法和案例
    js中的键盘事件和触摸事件
    JavaScript中的鼠标事件
    JavaScript中DOM操作之获取元素占位
    JavaScript中DOM操作之设定标签属性
    JavaScript中DOM操作文档对象模型获取标签内容
    windows10下python安装+selenium
    主体数据管理
  • 原文地址:https://www.cnblogs.com/chengxuyuan-liu/p/11603899.html
Copyright © 2011-2022 走看看