.class文件理解

原java文件:

package com.jyds;

/**
 *  * Created by jl on 2018/7/26 0026
 *   */
public class Test {
    public static void main(String[] args) {
        String a = "1";
        String b = "2";
        String c = a+b;
    }
}

javac编译后的class文件:

cafe babe 0000 0034 002e 0a00 0900 1509
0016 0017 0700 180a 0003 0015 0a00 0300
1908 001a 0a00 0300 1b0a 0003 001c 0700
1d0a 001e 001f 0a00 0300 2007 0021 0100
063c 696e 6974 3e01 0003 2829 5601 0004
436f 6465 0100 0f4c 696e 654e 756d 6265
7254 6162 6c65 0100 046d 6169 6e01 0016 ...

javap -verbose 将.class文件反编译为可读的字节码并输出:

Classfile /home/ljiang/com/jyds/Test.class
  Last modified Jul 26, 2018; size 458 bytes
  MD5 checksum 5bd08e536acec4ae68ee147fee12e206
  Compiled from "Test.java"
public class com.jyds.Test
  SourceFile: "Test.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #9.#18         //  java/lang/Object."<init>":()V
   #2 = String             #19            //  1
   #3 = String             #20            //  2
   #4 = Class              #21            //  java/lang/StringBuilder
   #5 = Methodref          #4.#18         //  java/lang/StringBuilder."<init>":()V
   #6 = Methodref          #4.#22         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #7 = Methodref          #4.#23         //  java/lang/StringBuilder.toString:()Ljava/lang/String;
   #8 = Class              #24            //  com/jyds/Test
   #9 = Class              #25            //  java/lang/Object
  #10 = Utf8               <init>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               SourceFile
  #17 = Utf8               Test.java
  #18 = NameAndType        #10:#11        //  "<init>":()V
  #19 = Utf8               1
  #20 = Utf8               2
  #21 = Utf8               java/lang/StringBuilder
  #22 = NameAndType        #26:#27        //  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #23 = NameAndType        #28:#29        //  toString:()Ljava/lang/String;
  #24 = Utf8               com/jyds/Test
  #25 = Utf8               java/lang/Object
  #26 = Utf8               append
  #27 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #28 = Utf8               toString
  #29 = Utf8               ()Ljava/lang/String;
{
  public com.jyds.Test();
    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 6: 0

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: ldc           #2                  // String 1
         2: astore_1      
         3: ldc           #3                  // String 2
         5: astore_2      
         6: new           #4                  // class java/lang/StringBuilder
         9: dup           
        10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
        13: aload_1       
        14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        17: aload_2       
        18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        21: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        24: astore_3      
        25: return        
      LineNumberTable:
        line 8: 0
        line 9: 3
        line 10: 6
        line 11: 25
}

上述字节码指令解释

ldc  将int, float或String型常量值从常量池中推送至栈顶
astore_1 将栈顶引用型数值存入第二个本地变量
invokevirtual 调用虚方法,具体实现在运行时会去判断的

从字节码可以看出上述代码是没有new String对象的(只new了一次StringBuilder,并可以看出编译器将"+"操作优化为StringBuilder.append了),没有new String对象是因为没有显示的new String(),这些值在字节码的常量池中可以找到,运行时会被直接保存到本地变量区(由astore指令可以看出)。

猜你喜欢

转载自blog.csdn.net/wo327865/article/details/81222852