• 通过查看字节码来学习Java代码


    最近学习java的一些知识, 通过学习编译后的字节码可以更好的了解java的编译.

    1. 安装查看字节码的插件

    在eclipse上直接通过Eclipse Marketplace安装, 直接搜索bytecode就可以看到插件

    最后通过Window-> Show View -> Other -> Java -> Bytecode打开查看字节码

    image

    在IntelliJ IDEA上也通过安装插件方式

    image

    IntelliJ IDEAL安装好插件后, 通过下面方法查看选中文件的字节码.

    image


    2. 通过字节码学习java字符串的操作

    下面写了一段简单的字符操作, 最后判断两个字符串是否相同. 最后输出的答案是false、true、true

    image

    下面是上面代码生成的字节码文件(红色字体是我添加的注释):

    // access flags 0x9
      public static main([Ljava/lang/String;)V
       L0
        LINENUMBER 5 L0
        LDC "abc"    //第一个字符串常量
        ASTORE 1
       L1
        LINENUMBER 6 L1
        NEW java/lang/StringBuilder
        DUP
        ALOAD 1
        INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
        INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
        LDC "def"    // 在连接字符串def的时候,相当于操作 String test2 = new StringBuilder().append(test1).append("def").toString();
        INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
        INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
        ASTORE 2
       L2
        LINENUMBER 7 L2
        LDC "abcdef"   //第三个字符串常量
        ASTORE 3
       L3
        LINENUMBER 8 L3
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        ALOAD 2
        ALOAD 3
        IF_ACMPNE L4
        ICONST_1
        GOTO L5
       L4
    
       FRAME FULL [[Ljava/lang/String; java/lang/String java/lang/String java/lang/String] [java/io/PrintStream]
        ICONST_0
       L5
       FRAME FULL [[Ljava/lang/String; java/lang/String java/lang/String java/lang/String] [java/io/PrintStream I]
        INVOKEVIRTUAL java/io/PrintStream.println(Z)V
       L6
        LINENUMBER 9 L6
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        ALOAD 2
        ALOAD 3
        INVOKEVIRTUAL java/lang/String.equals(Ljava/lang/Object;)Z
        INVOKEVIRTUAL java/io/PrintStream.println(Z)V
       L7
        LINENUMBER 10 L7
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        ALOAD 2
        INVOKEVIRTUAL java/lang/String.intern()Ljava/lang/String;
        ALOAD 3
        IF_ACMPNE L8
        ICONST_1
        GOTO L9
       L8
       FRAME SAME1 java/io/PrintStream
        ICONST_0
       L9
       FRAME FULL [[Ljava/lang/String; java/lang/String java/lang/String java/lang/String] [java/io/PrintStream I]
        INVOKEVIRTUAL java/io/PrintStream.println(Z)V
       L10
        LINENUMBER 11 L10
        RETURN
       L11
        LOCALVARIABLE args [Ljava/lang/String; L0 L11 0
        LOCALVARIABLE test1 Ljava/lang/String; L1 L11 1
        LOCALVARIABLE test2 Ljava/lang/String; L2 L11 2
        LOCALVARIABLE test3 Ljava/lang/String; L3 L11 3
        MAXSTACK = 3
        MAXLOCALS = 4

    通过以上的分析可以知道, 在创建test2字符串的时候, 是通过下面方式获取的.

    String test2 = new StringBuilder().append(test1).append(“def”).toString();

    这样的话字符串test2是放在堆里的, 而test1和test3是放在字符串的常量池当中的.

    (这里涉及到JVM虚拟机几个大部分: 方法区、Java虚拟机栈、本地方法栈、堆、程序寄数器、字符串常量池)

    这样的话,

    test2 == test3 是不相等, 返回false;

    test2.equals(test3)时比较值 是否相等;这里是相等, 返回true;

    test2.intern()是把test2放入到字符串常量池中, 则test2.intern() == test3 是相同的, 返回true;


    个人学习java知识总结:

    在学习java的时候, 有时候只知道这样写是正确的, 但不知道jvm是怎么做到的.

    知道是这么回事, 但是不知道为什么会是这么回事.

    所以在以后学习java知识的时候, 希望自己多深入了解一下, 不能只知道表面现象, 要看到本质.

  • 相关阅读:
    牛顿迭代法
    C语言补遗
    Manjaro添加开机启动脚本
    tensorboard查看pytorch模型
    Kindle最佳排版记录
    01背包问题详解
    差分法介绍
    BFS详解
    UVA11732 "strcmp()" Anyone?
    LA3942 Remember the Word
  • 原文地址:https://www.cnblogs.com/xumBlog/p/12209893.html
Copyright © 2020-2023  润新知