最近学习java的一些知识, 通过学习编译后的字节码可以更好的了解java的编译.
1. 安装查看字节码的插件
在eclipse上直接通过Eclipse Marketplace安装, 直接搜索bytecode就可以看到插件
最后通过Window-> Show View -> Other -> Java -> Bytecode打开查看字节码
在IntelliJ IDEA上也通过安装插件方式
IntelliJ IDEAL安装好插件后, 通过下面方法查看选中文件的字节码.
2. 通过字节码学习java字符串的操作
下面写了一段简单的字符操作, 最后判断两个字符串是否相同. 最后输出的答案是false、true、true
下面是上面代码生成的字节码文件(红色字体是我添加的注释):
// 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知识的时候, 希望自己多深入了解一下, 不能只知道表面现象, 要看到本质.