Javap查看Class指令

  • Post author:
  • Post category:java



javac Hello.java

public class Hello{
   static int num = 1;
   void hello(){
        String s = "aa";
        System.out.println(s);
        String s2 = new String("aa");
        System.out.println(s2);
   }
}



javap -v Hello.class

Classfile /G:/workspace/Projects/Golang/Hello.class
  Last modified 2014-12-30; size 527 bytes
  MD5 checksum e84276bb63ef1ea05d80fa07852dfce2
  Compiled from "Hello.java"
public class Hello
  SourceFile: "Hello.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #9.#20         //  java/lang/Object."<init>":()V
   #2 = String             #21            //  aa
   #3 = Fieldref           #22.#23        //  java/lang/System.out:Ljava/io/PrintStream;
   #4 = Methodref          #24.#25        //  java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            //  java/lang/String
   #6 = Methodref          #5.#27         //  java/lang/String."<init>":(Ljava/lang/String;)V
   #7 = Fieldref           #8.#28         //  Hello.num:I
   #8 = Class              #29            //  Hello
   #9 = Class              #30            //  java/lang/Object
  #10 = Utf8               num
  #11 = Utf8               I
  #12 = Utf8               <init>
  #13 = Utf8               ()V
  #14 = Utf8               Code
  #15 = Utf8               LineNumberTable
  #16 = Utf8               hello
  #17 = Utf8               <clinit>
  #18 = Utf8               SourceFile
  #19 = Utf8               Hello.java
  #20 = NameAndType        #12:#13        //  "<init>":()V
  #21 = Utf8               aa
  #22 = Class              #31            //  java/lang/System
  #23 = NameAndType        #32:#33        //  out:Ljava/io/PrintStream;
  #24 = Class              #34            //  java/io/PrintStream
  #25 = NameAndType        #35:#36        //  println:(Ljava/lang/String;)V
  #26 = Utf8               java/lang/String
  #27 = NameAndType        #12:#36        //  "<init>":(Ljava/lang/String;)V
  #28 = NameAndType        #10:#11        //  num:I
  #29 = Utf8               Hello
  #30 = Utf8               java/lang/Object
  #31 = Utf8               java/lang/System
  #32 = Utf8               out
  #33 = Utf8               Ljava/io/PrintStream;
  #34 = Utf8               java/io/PrintStream
  #35 = Utf8               println
  #36 = Utf8               (Ljava/lang/String;)V
{
  static int num;
    flags: ACC_STATIC

  public Hello();
    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 1: 0

  void hello();
    flags:
    Code:
      stack=3, locals=3, args_size=1
         0: ldc           #2                  // String aa
         2: astore_1
         3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         6: aload_1
         7: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        10: new           #5                  // class java/lang/String
        13: dup
        14: ldc           #2                  // String aa
        16: invokespecial #6                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
        19: astore_2
        20: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        23: aload_2
        24: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        27: return
      LineNumberTable:
        line 4: 0
        line 5: 3
        line 6: 10
        line 7: 20
        line 8: 27

  static {};
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: iconst_1
         1: putstatic     #7                  // Field num:I
         4: return
      LineNumberTable:
        line 2: 0
}


static {};

静态初始化代码;


String s = “aa”;



new String(“aa”);


从同一常量池出获取值

Java的8中基本类型:boolen,char,byte,short,int,long,float,double,基本类型的值被存储在栈中,因为这样更快。


栈:


1、当定义 int a = 10 时,编译器会在栈中分配4个字节空间来存放值(10),内存地址(0x0001)。

2、创建变量a, a的内存地址(0x0005),

存放(10)的地址(0x0001)。

引用(10)。

3、再定义 int b = 10 时,b的内存地址(0x0006),

同样存放(10)的地址(0x0001)。

引用(10)。

所以栈中的数据是共享的。


堆:


内存池,存储所有使用new出来的Java对象。

创建一个对象通常包括两个步骤:

1、对象声明(即创建对象引用)。

2、实例化(即为对象在堆中分配存储空间)。


常量




堆,方法区,栈和本地方法栈

堆(-Xms和-Xmx)调节

new出来的对象实例,都在堆上分配内存。

方法区(-XX:PermSize和-XX:MaxPermSize)调节

存放:类、静态变量和常量。

静态变量、常量、类太多,永久带内存可能不够。

栈和本地方法栈(-Xss)调节

存放:局部变量、参数、操作,方法出口等与方法相关的信息。

方法调用层次太多(递归), 该区内存可能不够。

===============================================================

(heap, stack, data-seg, code-seg)

heap:–>new出来对象。

stack:–局部变量,用来计算的。

data-seg:–>静态变量、字符串常量

code-seg:–>代码

===============================================================

public void print(){


Object o = new Object();

}

这里这里程序会创建两个对象内存空间:

1、new Object()存在堆中。

2、o引用,存在栈中。

堆中的内存是由GC来管理回收的。(程序中没有对该对象存在引用)

栈中的内存是当方法的栈帧运行完后就释放的(引用占4个字节)。

程序运行时涉及:(指令栈,本地变量区、操作数区)

public void print(){


Integer l;

for (int i=1; i < 3; i++) {


l = 2;

}

}



public void print(){


for (int i=1; i < 3; i++) {


Integer l = 2;

}

}

后者Integer l 在同一goto指令内,栈对象都是复用的,刻意写成前者,对内存优化并没有任何实在意义。

用来o后设置 为o=null。

在同一方法栈内,o为局部变量,且为引用类型,对内存优化并没有任何实在意义。



版权声明:本文为xxb2008原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。