• JVM字节码


    将.java源文件编译成.class二进制字节码文件,运行该字节码文件

    1.将class字节码文件内容输出到文本文件当中
    javap -v xxx.class > xxx.txt

    第一个部分:显示生成class的java源文件的基本信息
           Classfile /C:/Users/FLC/Desktop/授课内容/授课案例/Y2170/day22/jvm_project/jvm_day01/target/classes/com/wdksoft/ClassTest.class
           Last modified 2020-3-11; size 585 bytes
           MD5 checksum 39fa2636495e5b4bf08da6decc537381
           Compiled from "ClassTest.java"
           public class com.wdksoft.ClassTest
           minor version: 0
           major version: 51
           flags: ACC_PUBLIC, ACC_SUPER
     
    第二个部分:显示该类所涉及到的常量池,共有35个常量
      Constant pool:
             #1 = Methodref #5.#23 // java/lang/Object."<init>":()V
             #2 = Fieldref #24.#25 // java/lang/System.out:Ljava/io/PrintStream;
             #3 = Methodref #26.#27 // java/io/PrintStream.println:(I)V
             #4 = Class #28 // com/wdksoft/ClassTest
             #5 = Class #29 // java/lang/Object
             #6 = Utf8 <init>
             #7 = Utf8 ()V
             #8 = Utf8 Code
             #9 = Utf8 LineNumberTable
             #10 = Utf8 LocalVariableTable
             #11 = Utf8 this
             #12 = Utf8 Lcom/wdksoft/ClassTest;
             #13 = Utf8 main
             #14 = Utf8 ([Ljava/lang/String;)V
             #15 = Utf8 args
             #16 = Utf8 [Ljava/lang/String;
             #17 = Utf8 a
             #18 = Utf8 I
             #19 = Utf8 b
             #20 = Utf8 c
             #21 = Utf8 SourceFile
             #22 = Utf8 ClassTest.java
             #23 = NameAndType #6:#7 // "<init>":()V
             #24 = Class #30 // java/lang/System
             #25 = NameAndType #31:#32 // out:Ljava/io/PrintStream;
             #26 = Class #33 // java/io/PrintStream
             #27 = NameAndType #34:#35 // println:(I)V
             #28 = Utf8 com/wdksoft/ClassTest
             #29 = Utf8 java/lang/Object
             #30 = Utf8 java/lang/System
             #31 = Utf8 out
             #32 = Utf8 Ljava/io/PrintStream;
             #33 = Utf8 java/io/PrintStream
             #34 = Utf8 println
             #35 = Utf8 (I)V


    第三个部分:显示该类的构造器,编译器自动生成一个无参构造
    public com.wdksoft.ClassTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
    stack=1, locals=1, args_size=1
    0: aload_0
    1: invokespecial #1 // Method java/lang/Object."<init>":()V
    4: return
    LineNumberTable:
    line 3: 0
    LocalVariableTable:
    Start Length Slot Name Signature
    0 5 0 this Lcom/wdksoft/ClassTest;

    第四部分:显示main方法的信息
    public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V 方法的描述,V代表返回值为void
    flags: ACC_PUBLIC, ACC_STATIC 方法修饰符 public static
    Code:
    stack=2, locals=4, args_size=1 stack代表操作栈的大小 locals本地变量表大小 args_size代表参数个数
    0: iconst_2 将数据2压入到操作栈当中,位于栈顶
    1: istore_1 从操作栈当中弹出一个数据,放到本地变量表当中,下标为1,0是this,操作栈当中数据清空
    2: iconst_5 将数据5压入到操作栈当中,位于栈顶
    3: istore_2 从操作栈当中弹出一个数据,放到本地变量表当中,下标为2,0是this,操作栈当中数据清空
    4: iload_2 将本地变量表中的下标为2的数据压入到操作站
    5: iload_1 将本地变量表中的下标为1的数据压入到操作站
    6: isub 将操作栈中的两个数据相减
    7: istore_3 将相减的结果压入到本地本地变量表当中,下标为3
    8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
    11: iload_3 将本地变量表中下标为3的数据压入到操作站
    12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
    15: return 返回
    LineNumberTable: 行号列表
    line 5: 0
    line 6: 2
    line 7: 4
    line 8: 8
    line 9: 15
    LocalVariableTable:
    Start Length Slot Name Signature
    0 16 0 args [Ljava/lang/String;
    2 14 1 a I
    4 12 2 b I
    8 8 3 c I

    研究 i++ 与 ++i 的不同
        我们都知道,i++表示,先返回再+1,++i表示,先+1再返回。

         i++:

                    0: iconst_1 //将数字1压入到操作栈
                    1: istore_1 //将数字1从操作栈弹出,压入到本地变量表中,下标为1
                    2: iload_1 //从本地变量表中获取下标为1的数据,压入到操作栈中
                    3: iinc 1, 1 // 将本地变量中的1,再+1
                    6: istore_2 // 将数字1从操作栈弹出,压入到本地变量表中,下标为2
                    7: getstatic #6 // Field
                    java/lang/System.out:Ljava/io/PrintStream;
                    10: iload_2 //从本地变量表中获取下标为2的数据,压入到操作栈中
                    11: invokevirtual #7 // Method
                    java/io/PrintStream.println:(I)V
                    14: return        


                      
                 ++i:

                    0: iconst_1 //将数字1压入到操作栈
                    1: istore_1 //将数字1从操作栈弹出,压入到本地变量表中,下标为1
                    2: iinc 1, 1// 将本地变量中的1,再+1
                    5: iload_1 //从本地变量表中获取下标为1的数据(2),压入到操作栈中
                    6: istore_2 //将数字2从操作栈弹出,压入到本地变量表中,下标为2
                    7: getstatic #6 // Field
                    java/lang/System.out:Ljava/io/PrintStream;
                    10: iload_2 //从本地变量表中获取下标为2的数据(2),压入到操作栈中
                    11: invokevirtual #7 // Method
                    java/io/PrintStream.println:(I)V
                    14: return


               区别:
                        i++   只是在本地变量中对数字做了相加,并没有将数据压入到操作栈将前面拿到的数字1,再次从操作栈中拿到,压入到本地变量中
                   
                        ++i   将本地变量中的数字做了相加,并且将数据压入到操作栈将操作栈中的数据,再次压入到本地变量中
                     
              





    二.动态字节技术
             在程序运行或者编译时期,通过动态字节码技术对类新增,删除,修改类的内部结构,包括字段和方法
             动态字节码技术应用场景:AOP,Lombok,动态修改class文件等等

    字节码操作类库:
              1.BCEL
              2.ASM:轻量级的Java字节码操作框架,SpringAOP底层基于ASM字节码技术
              3.CGLIB 基于ASM
              4.javassist

  • 相关阅读:
    【SSM电商项目后台开发】004-用户模块
    【SSM电商项目后台开发】003-项目架构概览
    C#面向对象编程「字段与属性」
    C#基本语法
    C#学习笔记-简介
    软件工程团队作业展示
    “消灭选择困难症”软件设计规格说明书
    “消灭选择困难APP”软件需求规格说明书
    消灭选择困难APP
    消灭选择困难
  • 原文地址:https://www.cnblogs.com/liuying23/p/12463408.html
Copyright © 2020-2023  润新知