java 內存空間


 

堆:new 出的對象在堆上

java棧:java程序、線程運行數據、內存數據

每個方法都有自己的棧、運行時需要的數據存在自己的棧中

每個線程對立的是圖中淺藍色的部分(java棧、本地方法棧、程序計數器)

堆和方法區是所有線程共享的

java棧會對調用的每個方法生成一個棧幀

 

編寫一個簡單的Math.java 文件

package com.example.demo;

public class Math {
    public static final Integer CONSTANT_1 = 666;

    public int math() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 10;
        return c;
    }

    public static void main(String[] args) {
        Math math = new Math();
        System.out.println(math.math());
        System.out.println("end");
    }
}

Math.class

cafe babe 0000 0034 0030 0a00 0b00 1907
001a 0a00 0200 1909 001b 001c 0a00 0200
1d0a 001e 001f 0800 200a 001e 0021 0a00
2200 2309 0002 0024 0700 2501 000a 434f
4e53 5441 4e54 5f31 0100 134c 6a61 7661
2f6c 616e 672f 496e 7465 6765 723b 0100
063c 696e 6974 3e01 0003 2829 5601 0004
436f 6465 0100 0f4c 696e 654e 756d 6265
7254 6162 6c65 0100 046d 6174 6801 0003
2829 4901 0004 6d61 696e 0100 1628 5b4c
6a61 7661 2f6c 616e 672f 5374 7269 6e67
3b29 5601 0008 3c63 6c69 6e69 743e 0100
0a53 6f75 7263 6546 696c 6501 0009 4d61
7468 2e6a 6176 610c 000e 000f 0100 1563
6f6d 2f65 7861 6d70 6c65 2f64 656d 6f2f
4d61 7468 0700 260c 0027 0028 0c00 1200
1307 0029 0c00 2a00 2b01 0003 656e 640c
002a 002c 0700 2d0c 002e 002f 0c00 0c00
0d01 0010 6a61 7661 2f6c 616e 672f 4f62
6a65 6374 0100 106a 6176 612f 6c61 6e67
2f53 7973 7465 6d01 0003 6f75 7401 0015
4c6a 6176 612f 696f 2f50 7269 6e74 5374
7265 616d 3b01 0013 6a61 7661 2f69 6f2f
5072 696e 7453 7472 6561 6d01 0007 7072
696e 746c 6e01 0004 2849 2956 0100 1528
4c6a 6176 612f 6c61 6e67 2f53 7472 696e
673b 2956 0100 116a 6176 612f 6c61 6e67
2f49 6e74 6567 6572 0100 0776 616c 7565
4f66 0100 1628 4929 4c6a 6176 612f 6c61
6e67 2f49 6e74 6567 6572 3b00 2100 0200
0b00 0000 0100 1900 0c00 0d00 0000 0400
0100 0e00 0f00 0100 1000 0000 1d00 0100
0100 0000 052a b700 01b1 0000 0001 0011
0000 0006 0001 0000 0003 0001 0012 0013
0001 0010 0000 0031 0002 0004 0000 000d
043c 053d 1b1c 6010 0a68 3e1d ac00 0000
0100 1100 0000 1200 0400 0000 0700 0200
0800 0400 0900 0b00 0a00 0900 1400 1500
0100 1000 0000 3f00 0200 0200 0000 1bbb
0002 59b7 0003 4cb2 0004 2bb6 0005 b600
06b2 0004 1207 b600 08b1 0000 0001 0011
0000 0012 0004 0000 000e 0008 000f 0012
0010 001a 0011 0008 0016 000f 0001 0010
0000 0022 0001 0000 0000 000a 1102 9ab8
0009 b300 0ab1 0000 0001 0011 0000 0006
0001 0000 0004 0001 0017 0000 0002 0018

 

利用java命令

javap -c Maht.txt

  

 對應的字節碼

Compiled from "Math.java"
public class com.example.demo.Math {
  public static final java.lang.Integer CONSTANT_1;

  public com.example.demo.Math();
    Code:
       0: aload_0
       1: invokespecial #1                  // 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           #2                  // class com/example/demo/Math
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: aload_1
      12: invokevirtual #5                  // Method math:()I
      15: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
      18: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
      21: ldc           #7                  // String end
      23: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      26: return

  static {};
    Code:
       0: sipush        666
       3: invokestatic  #9                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       6: putstatic     #10                 // Field CONSTANT_1:Ljava/lang/Integer;
       9: return
}

 

jvm指令集

跳轉到class文件目錄,使用 

javap -c StringTest.class -> p.txt

1 

命令將編譯后的文件輸出到p.txt文件

棧和局部變量操作

將常量壓入棧的指令

aconst_null 將null對象引用壓入棧

iconst_m1 將int類型常量-1壓入棧

iconst_0 將int類型常量0壓入棧

iconst_1 將int類型常量1壓入棧

iconst_2 將int類型常量2壓入棧

iconst_3 將int類型常量3壓入棧

iconst_4 將int類型常量4壓入棧

iconst_5 將int類型常量5壓入棧

lconst_0 將long類型常量0壓入棧

lconst_1 將long類型常量1壓入棧

fconst_0 將float類型常量0壓入棧

fconst_1 將float類型常量1壓入棧

dconst_0 將double類型常量0壓入棧

dconst_1 將double類型常量1壓入棧

bipush 將一個8位帶符號整數壓入棧

sipush 將16位帶符號整數壓入棧

ldc 把常量池中的項壓入棧

ldc_w 把常量池中的項壓入棧(使用寬索引)

ldc2_w 把常量池中long類型或者double類型的項壓入棧(使用寬索引)

從棧中的局部變量中裝載值的指令

iload 從局部變量中裝載int類型值

lload 從局部變量中裝載long類型值

fload 從局部變量中裝載float類型值

dload 從局部變量中裝載double類型值

aload 從局部變量中裝載引用類型值(refernce)

iload_0 從局部變量0中裝載int類型值

iload_1 從局部變量1中裝載int類型值

iload_2 從局部變量2中裝載int類型值

iload_3 從局部變量3中裝載int類型值

lload_0 從局部變量0中裝載long類型值

lload_1 從局部變量1中裝載long類型值

lload_2 從局部變量2中裝載long類型值

lload_3 從局部變量3中裝載long類型值

fload_0 從局部變量0中裝載float類型值

fload_1 從局部變量1中裝載float類型值

fload_2 從局部變量2中裝載float類型值

fload_3 從局部變量3中裝載float類型值

dload_0 從局部變量0中裝載double類型值

dload_1 從局部變量1中裝載double類型值

dload_2 從局部變量2中裝載double類型值

dload_3 從局部變量3中裝載double類型值

aload_0 從局部變量0中裝載引用類型值

aload_1 從局部變量1中裝載引用類型值

aload_2 從局部變量2中裝載引用類型值

aload_3 從局部變量3中裝載引用類型值

iaload 從數組中裝載int類型值

laload 從數組中裝載long類型值

faload 從數組中裝載float類型值

daload 從數組中裝載double類型值

aaload 從數組中裝載引用類型值

baload 從數組中裝載byte類型或boolean類型值

caload 從數組中裝載char類型值

saload 從數組中裝載short類型值

將棧中的值存入局部變量的指令

istore 將int類型值存入局部變量

lstore 將long類型值存入局部變量

fstore 將float類型值存入局部變量

dstore 將double類型值存入局部變量

astore 將將引用類型或returnAddress類型值存入局部變量

istore_0 將int類型值存入局部變量0

istore_1 將int類型值存入局部變量1

istore_2 將int類型值存入局部變量2

istore_3 將int類型值存入局部變量3

lstore_0 將long類型值存入局部變量0

lstore_1 將long類型值存入局部變量1

lstore_2 將long類型值存入局部變量2

lstore_3 將long類型值存入局部變量3

fstore_0 將float類型值存入局部變量0

fstore_1 將float類型值存入局部變量1

fstore_2 將float類型值存入局部變量2

fstore_3 將float類型值存入局部變量3

dstore_0 將double類型值存入局部變量0

dstore_1 將double類型值存入局部變量1

dstore_2 將double類型值存入局部變量2

dstore_3 將double類型值存入局部變量3

astore_0 將引用類型或returnAddress類型值存入局部變量0

astore_1 將引用類型或returnAddress類型值存入局部變量1

astore_2 將引用類型或returnAddress類型值存入局部變量2

astore_3 將引用類型或returnAddress類型值存入局部變量3

iastore 將int類型值存入數組中

lastore 將long類型值存入數組中

fastore 將float類型值存入數組中

dastore 將double類型值存入數組中

aastore 將引用類型值存入數組中

bastore 將byte類型或者boolean類型值存入數組中

castore 將char類型值存入數組中

sastore 將short類型值存入數組中

wide指令

wide 使用附加字節擴展局部變量索引

通用(無類型)棧操作

nop 不做任何操作

pop 彈出棧頂端一個字長的內容

pop2 彈出棧頂端兩個字長的內容

dup 復制棧頂部一個字長內容

dup_x1 復制棧頂部一個字長的內容,然后將復制內容及原來彈出的兩個字長的內容壓入棧

dup_x2 復制棧頂部一個字長的內容,然后將復制內容及原來彈出的三個字長的內容壓入棧

dup2 復制棧頂部兩個字長內容

dup2_x1 復制棧頂部兩個字長的內容,然后將復制內容及原來彈出的三個字長的內容壓入棧

dup2_x2 復制棧頂部兩個字長的內容,然后將復制內容及原來彈出的四個字長的內容壓入棧

swap 交換棧頂部兩個字長內容

類型轉換

i2l 把int類型的數據轉化為long類型

i2f 把int類型的數據轉化為float類型

i2d 把int類型的數據轉化為double類型

l2i 把long類型的數據轉化為int類型

l2f 把long類型的數據轉化為float類型

l2d 把long類型的數據轉化為double類型

f2i 把float類型的數據轉化為int類型

f2l 把float類型的數據轉化為long類型

f2d 把float類型的數據轉化為double類型

d2i 把double類型的數據轉化為int類型

d2l 把double類型的數據轉化為long類型

d2f 把double類型的數據轉化為float類型

i2b 把int類型的數據轉化為byte類型

i2c 把int類型的數據轉化為char類型

i2s 把int類型的數據轉化為short類型

整數運算

iadd 執行int類型的加法

ladd 執行long類型的加法

isub 執行int類型的減法

lsub 執行long類型的減法

imul 執行int類型的乘法

lmul 執行long類型的乘法

idiv 執行int類型的除法

ldiv 執行long類型的除法

irem 計算int類型除法的余數

lrem 計算long類型除法的余數

ineg 對一個int類型值進行取反操作

lneg 對一個long類型值進行取反操作

iinc 把一個常量值加到一個int類型的局部變量上

邏輯運算

移位操作

ishl 執行int類型的向左移位操作

lshl 執行long類型的向左移位操作

ishr 執行int類型的向右移位操作

lshr 執行long類型的向右移位操作

iushr 執行int類型的向右邏輯移位操作

lushr 執行long類型的向右邏輯移位操作

按位布爾運算

iand 對int類型值進行“邏輯與”操作

land 對long類型值進行“邏輯與”操作

ior 對int類型值進行“邏輯或”操作

lor 對long類型值進行“邏輯或”操作

ixor 對int類型值進行“邏輯異或”操作

lxor 對long類型值進行“邏輯異或”操作

浮點運算

fadd 執行float類型的加法

dadd 執行double類型的加法

fsub 執行float類型的減法

dsub 執行double類型的減法

fmul 執行float類型的乘法

dmul 執行double類型的乘法

fdiv 執行float類型的除法

ddiv 執行double類型的除法

frem 計算float類型除法的余數

drem 計算double類型除法的余數

fneg 將一個float類型的數值取反

dneg 將一個double類型的數值取反

對象和數組

對象操作指令

new 創建一個新對象

checkcast 確定對象為所給定的類型

getfield 從對象中獲取字段

putfield 設置對象中字段的值

getstatic 從類中獲取靜態字段

putstatic 設置類中靜態字段的值

instanceof 判斷對象是否為給定的類型

數組操作指令

newarray 分配數據成員類型為基本上數據類型的新數組

anewarray 分配數據成員類型為引用類型的新數組

arraylength 獲取數組長度

multianewarray 分配新的多維數組

控制流

條件分支指令

ifeq 如果等於0,則跳轉

ifne 如果不等於0,則跳轉

iflt 如果小於0,則跳轉

ifge 如果大於等於0,則跳轉

ifgt 如果大於0,則跳轉

ifle 如果小於等於0,則跳轉

if_icmpcq 如果兩個int值相等,則跳轉

if_icmpne 如果兩個int類型值不相等,則跳轉

if_icmplt 如果一個int類型值小於另外一個int類型值,則跳轉

if_icmpge 如果一個int類型值大於或者等於另外一個int類型值,則跳轉

if_icmpgt 如果一個int類型值大於另外一個int類型值,則跳轉

if_icmple 如果一個int類型值小於或者等於另外一個int類型值,則跳轉

ifnull 如果等於null,則跳轉

ifnonnull 如果不等於null,則跳轉

if_acmpeq 如果兩個對象引用相等,則跳轉

if_acmpnc 如果兩個對象引用不相等,則跳轉

比較指令

lcmp 比較long類型值

fcmpl 比較float類型值(當遇到NaN時,返回-1)

fcmpg 比較float類型值(當遇到NaN時,返回1)

dcmpl 比較double類型值(當遇到NaN時,返回-1)

dcmpg 比較double類型值(當遇到NaN時,返回1)

無條件轉移指令

goto 無條件跳轉

goto_w 無條件跳轉(寬索引)

表跳轉指令

tableswitch 通過索引訪問跳轉表,並跳轉

lookupswitch 通過鍵值匹配訪問跳轉表,並執行跳轉操作

異常

athrow 拋出異常或錯誤

finally子句

jsr 跳轉到子例程

jsr_w 跳轉到子例程(寬索引)

rct 從子例程返回

方法調用與返回

方法調用指令

invokcvirtual 運行時按照對象的類來調用實例方法

invokespecial 根據編譯時類型來調用實例方法

invokestatic 調用類(靜態)方法

invokcinterface 調用接口方法

方法返回指令

ireturn 從方法中返回int類型的數據

lreturn 從方法中返回long類型的數據

freturn 從方法中返回float類型的數據

dreturn 從方法中返回double類型的數據

areturn 從方法中返回引用類型的數據

return 從方法中返回,返回值為void

線程同步

montiorenter 進入並獲取對象監視器

monitorexit 釋放並退出對象監視器

JVM指令助記符

變量到操作數棧:iload,iload_,lload,lload_,fload,fload_,dload,dload_,aload,aload_

操作數棧到變量:istore,istore_,lstore,lstore_,fstore,fstore_,dstore,dstor_,astore,astore_

常數到操作數棧:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,fconst_,dconst_

加:iadd,ladd,fadd,dadd

減:isub,lsub,fsub,dsub

乘:imul,lmul,fmul,dmul

除:idiv,ldiv,fdiv,ddiv

余數:irem,lrem,frem,drem

取負:ineg,lneg,fneg,dneg

移位:ishl,lshr,iushr,lshl,lshr,lushr

按位或:ior,lor

按位與:iand,land

按位異或:ixor,lxor

類型轉換:i2l,i2f,i2d,l2f,l2d,f2d(放寬數值轉換)

i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l,d2f(縮窄數值轉換)

創建類實便:new

創建新數組:newarray,anewarray,multianwarray

訪問類的域和類實例域:getfield,putfield,getstatic,putstatic

把數據裝載到操作數棧:baload,caload,saload,iaload,laload,faload,daload,aaload

從操作數棧存存儲到數組:bastore,castore,sastore,iastore,lastore,fastore,dastore,aastore

獲取數組長度:arraylength

檢相類實例或數組屬性:instanceof,checkcast

操作數棧管理:pop,pop2,dup,dup2,dup_xl,dup2_xl,dup_x2,dup2_x2,swap

有條件轉移:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnonnull,if_icmpeq,if_icmpene,

if_icmplt,if_icmpgt,if_icmple,if_icmpge,if_acmpeq,if_acmpne,lcmp,fcmpl

fcmpg,dcmpl,dcmpg

復合條件轉移:tableswitch,lookupswitch

無條件轉移:goto,goto_w,jsr,jsr_w,ret

調度對象的實便方法:invokevirtual

調用由接口實現的方法:invokeinterface

調用需要特殊處理的實例方法:invokespecial

調用命名類中的靜態方法:invokestatic

方法返回:ireturn,lreturn,freturn,dreturn,areturn,return

異常:athrow

finally關鍵字的實現使用:jsr,jsr_w,ret

 

程序計數器:

記錄的是馬上要執行的代碼對應的字節碼的數字

是程序執行的指針(地址),也即將來要執行的指令代碼

 

動態鏈接:

變量,當執行時需要找到。比如

Map<String, String> map = new HashMap<>();

Map 接口,運行時找HashMap實現,做一個鏈接(動態)

自己寫的接口,執行時去找具體實現。

 

 本地方法棧的理解

 

 

 

執行引擎運行本地方法

會調用被本地方法接口,本地方法入本地方法棧,類似ava棧,也有棧針,調用C語言所實現的dll(cpp)庫,類似java的jar包

 

方法區(線程共享):類的所有字段和方法字節碼,以及一些特殊方法如構造函數,接口代碼也在此定義。

簡單說,所有定義的方法的信息都保存在該區域,靜態變量+常量+類信息(構造方法/接口定義)+運行時常量池都存在方法區中,

雖然Java虛擬機規范把方法區描述為堆的一個邏輯部分,但是它卻有一個別名叫做 Non-Heap(非堆),目的應該是與 Java 堆區分開來。

 

 實例詳解java棧

 

 

棧+堆+方法區的交互關系
HotSpot是使用指針的方式來訪問對象
Java堆中會存放訪問類元數據的地址
reference存儲的就直接是對象的地址

 

 

 

對象類型數據是calss的末班數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM