JVM-內存結構

內存結構圖

  • Heap,Method Area內存可由GC回收。JVM調優針對Heap與Mehtod Area。
  • Stack, PC Register, Native Method Stack內存由JVM分配和回收,使用之後JVM自動釋放空間。不存在已使用的變量,因爲已經被JVM釋放。只存在當前使用以及將來即將使用的變量。

Stack (Java 虛擬機棧)

Java虛擬機棧是方法調用和執行的空間,每個方法會封裝成一個棧幀壓入佔中。Demo1.class執行後,有2個方法棧(Demo1()棧和math()棧)。

  • 局部變量表
    • 以字長爲單位的數組,存放當前線程(當前棧幀/當前方法)的變量、引用類型,使用的是索引。
    • 可看作是一個數組,每個數組元素可看作是一個槽,每個槽爲32位。
  • 操作數棧
    • 以字長爲單位的數組,通過彈棧/牙棧訪問變量。操作數棧可理解爲java虛擬機棧中的一個用於計算的臨時數據存儲區。
  • 動態鏈接
    • 在程序運行期間,由符號引用轉化爲直接引用。
    • 靜態鏈接:在解析階段,由符號引用轉化爲直接引用。
    • 轉化:就是加載。符號引用就是存了class的位置,根據位置直接找到實例對象就是直接引用。(真正使用的是對象,而不是class的位置)
  • 返回地址
    • 返回地址內容是一個指針(內存地址的索引),記錄調用者是誰。

符號引用

符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能夠無歧義的定位到目標即可。

2.txt 初始化Demol1()時顯示字符串Mehtod"<init>":V。這就是符號引用。

直接引用

Obeject ob = new Object();

直接引用是和虛擬機的佈局相關的,有了直接引用,那引用的目標必定已經被加載入內存中了。

(1)直接指向目標的指針(比如,指向“類型”【Class對象】、類變量、類方法的直接引用可能是指向方法區的指針)

(2)相對偏移量(比如,指向實例變量、實例方法的直接引用都是偏移量)

(3)一個能間接定位到目標的句柄

PC Register 程序計數器

 

程序計數器是一塊很小的內存空間,存儲內容爲數字,數字爲將要運行的代碼序號(如上圖)。

7與9之間的8不見了,是因爲新版本的JDK(1.8)做了優化,舊版本JDK可以顯示。

本地方法棧

 
啓動線程,調用PThread()來調用系統線程。
 

實例分析

package basic;
public class Demo1 {
      public int math() {
            int a = 1;
            int b = 2;
            int c = (a+b) * 10;
            return c;
      }
      public static void main(String[] args) {
            Demo1 demo1 = new Demo1();
            demo1.math();
      }
}

javap -c Demo1.class > 1.txt

Compiled from "Demo1.java"
public class basic.Demo1 {
  public basic.Demo1();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public int math();
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: bipush        10
       9: imul
      10: istore_3
      11: iload_3
      12: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class basic/Demo1
       3: dup
       4: invokespecial #22                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #23                 // Method math:()I
      12: pop
      13: return
}

javap -v Demo1.class > 2.txt

Classfile /C:/Users/zhengby/workspace/JavaPractice/bin/basic/Demo1.class
  Last modified 2020-5-12; size 564 bytes
  MD5 checksum d51ee4bb7cfab6a3ded541fa5c1ef871
  Compiled from "Demo1.java"
public class basic.Demo1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // basic/Demo1
   #2 = Utf8               basic/Demo1
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lbasic/Demo1;
  #14 = Utf8               math
  #15 = Utf8               ()I
  #16 = Utf8               a
  #17 = Utf8               I
  #18 = Utf8               b
  #19 = Utf8               c
  #20 = Utf8               main
  #21 = Utf8               ([Ljava/lang/String;)V
  #22 = Methodref          #1.#9          // basic/Demo1."<init>":()V
  #23 = Methodref          #1.#24         // basic/Demo1.math:()I
  #24 = NameAndType        #14:#15        // math:()I
  #25 = Utf8               args
  #26 = Utf8               [Ljava/lang/String;
  #27 = Utf8               demo1
  #28 = Utf8               SourceFile
  #29 = Utf8               Demo1.java
{
  public basic.Demo1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lbasic/Demo1;

  public int math();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: iconst_1
         1: istore_1
         2: iconst_2
         3: istore_2
         4: iload_1
         5: iload_2
         6: iadd
         7: bipush        10
         9: imul
        10: istore_3
        11: iload_3
        12: ireturn
      LineNumberTable:
        line 5: 0
        line 6: 2
        line 7: 4
        line 8: 11
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   Lbasic/Demo1;
            2      11     1     a   I
            4       9     2     b   I
           11       2     3     c   I

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #1                  // class basic/Demo1
         3: dup
         4: invokespecial #22                 // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #23                 // Method math:()I
        12: pop
        13: return
      LineNumberTable:
        line 12: 0
        line 13: 8
        line 14: 13
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  args   [Ljava/lang/String;
            8       6     1 demo1   Lbasic/Demo1;
}
SourceFile: "Demo1.java"

分析math()的執行

  public int math();
    Code:
       0: iconst_1                #第1個操作數壓如操作數棧頂
       1: istore_1                #第1個操作數從操作數棧彈出,存入局部變量表第1個槽中
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: bipush        10
       9: imul
      10: istore_3
      11: iload_3
      12: ireturn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章