1. 运行时的数据区域
- 程序计数器
- 为了线程切换后恢复正常执行顺序
- 各个线程间互不影响
- Java虚拟机栈/栈内存
- 栈帧(即操作系统概念中的堆栈?):线程私有,存储局部变量表、操作数栈、动态链接、方法出口等信息
- 局部变量表:存放编译期可知的基本数据类型、对象引用、returnAdress
- 会抛出两种异常:请求栈深度大于所允许的深度、没有足够内存
- 本地方法栈:与虚拟栈类似
- Java堆/垃圾堆
- 是Java虚拟机所管理的内存中最大的
- 被所有线程共享,在启动是创建
- 存放对象实例
- 是垃圾收集器管理的主要区域
- 方法区/非堆
- 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译的代码等
- 运行时的常量池
- 方法区的一部分
- 存放编译期生成的各种字面量和符号引用
- 动态性
- 直接内存:与JVM无关,与NIO有关
2. 虚拟机对象
- 对象的创建
- 检查常量池中是否有这个类的符号引用以及是否被加载,解析、初始化
- 分配内存,虚拟机会维护一个内存列表以知道有哪些内存可用
- 虚拟机设置对象信息,存放在对象头中
- 执行
String a = "100";
String b = "100";
String c = new String("100");
String d = new String("100");
System.out.println(a == b);//true
System.out.println(c == b);//false
这是因为虚拟机在创建b的时候会想去常量池看一下有没有同意为“100”的对象,如果发现了,会将b指向这个对象的引用;而创建c、d的时候,是强制要求分配不同的新内存的,所以不是同一个对象。
- 对象的内存布局
- 对象头:包含两部分,一部分存储对象自身运行时的数据(如哈希码、GC年龄分代)、类型指针(确定对象属于哪个类)
- 实例数据:有效信息
- 对齐填充:占位符
3. 对象的访问定位
- 句柄
- Java堆中分出一块句柄池
- Java栈本地变量表中的reference指向句柄地址、句柄包含指向实例数据和类型数据的指针
- 优点:稳定
- 直接指针
- reference指向堆中的指针,指针和实例数据存在一起,指针指向类型数据
- 快