内存结构图
-
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