运行时数据区域

java会在运行时分配管理的内存

程序计数器

当前线程所执行的字节码行号指示器

通过改变程序计数器的值来选取下一条需要执行的字节码指令

java 每个线程都需要一个独立的程序计数器

唯一一个没有oom的区域

虚拟机栈

线程私有 生命周期与线程相同

方法执行时创建一个栈帧 方法调用到完成的过程就是栈帧从虚拟机栈中入栈到出栈的过程

栈帧是方法运行的基础数据结构

栈内存讲的是虚拟机栈 对应的局部变量表

局部变量表所需的内存空间在编译期分配

栈可以存放 基本数据类型 boolean byte chat short int float long double 对象引用 reference 并不是对象本身

如果线程请求的栈深度大于虚拟机允许的深度 StackOverflowError

虚拟机可以动态扩展 当扩展无法申请到最够内存时 OutOfMenoryError

本地方法栈

虚拟机栈执行java方法 本地方法栈执行虚拟机用到的Native方法 可以合并

堆是所有线程共享的内存区域 在虚拟机启动是创建 唯一目的是存放对象实例

堆可以处于逻辑上连续,物理上不连续的内存空间中。

可以固定大小 也可以扩展 堆溢出oom

方法区

方法区线程共享区域 用与存储已被虚拟机加载的类信息 常量 静态变量 编辑器编译后的代码

垃圾收集行为在这个区域比较少见 内存回收主要是针对常量池的回收和对类型的卸载

运行时常量池

运行时常量池是方法区的一部分 Class文件中除了版本、字段、方法、接口、描述等信息外 还有一项信息为常量池 用与存放编译期生成的各种字面量和符号引用 在类加载后存放到常量池

翻译出来的直接引用也放在运行时常量池中

直接内存

不是虚拟机运行时数据的一部分

java程序执行过程

init.svg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Demo{

private static final String DEMO="STRING";

public void demo1(String str){

String s=str+1;

System.out.printf(DEMO+"~"+s);
}

public static void main(String[] args) {
Demo demo=new Demo();

demo.demo1("aaaa");
}

}

javap -c -l Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class Demo {
//自动生成无参构造方法
public Demo();
Code:
0: aload_0 //加载this放入栈中
1: invokespecial #1 执行父类Object init方法 // Method java/lang/Object."<init>":()V
4: return 返回空
LineNumberTable:
line 1: 0

public void demo1(java.lang.String);
Code:
0: aload_1 //var1 压入栈中
1: invokedynamic #2, 0 // 我理解为简化var1+"1"操作 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
6: astore_2 //给局部变量var2赋值
7: getstatic #3 //取System.out引用 // Field java/lang/System.out:Ljava/io/PrintStream;
10: aload_2 // "STRING~"压入栈中
11: invokedynamic #4, 0 同上简化 "STRING~"+var2操作 // InvokeDynamic #1:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
16: iconst_0 //上步骤结果压入栈中
17: anewarray #5 //接受栈顶的元素 // class java/lang/Object
20: invokevirtual #6 //执行printf方法 // Method java/io/PrintStream.printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
23: pop //弹出
24: return //返回
LineNumberTable:
line 6: 0
line 8: 7
line 10: 24

public static void main(java.lang.String[]);
Code:
0: new #7 //新建类Demo() // class Demo
3: dup //复制一份引用 并把引用放入栈中
4: invokespecial #8 //出栈执行init方法 // Method "<init>":()V
7: astore_1 //创建局部变量
8: aload_1 //加载局部变量var1
9: ldc #9 //常量aaaa入栈 // String aaaa
11: invokevirtual #10 //执行demo1方法 // Method demo1:(Ljava/lang/String;)V
14: return 返回
LineNumberTable:
line 13: 0
line 14: 8
line 15: 14
}