內存結構圖
-
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可以顯示。
本地方法棧
實例分析
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