内存模型
线程独占:栈、本地方法栈、程序计数器
线程共享、堆、方法区
- 虚拟机栈:【方法栈】线程私有,线程执行时会创建一个栈帧,用于存储局部变量表,操作栈,动态链接,方法出口等;调用时入栈,返回时出栈。
- 本地方法栈:与栈类似,用于保存执行方法信息;【执行Java方法使用的是栈,执行Native方法使用的是本地方法栈】
- 程序计数器:线程私有,用于保存当前线程执行字节码位置;仅服务于Java方法,Native方法执行时程序计数器为空;
- 堆:拥有最大的内存,用户存储对象实例,当没有空间时会抛出OOM异常。
- 方法区:【非堆栈区】用于存储虚拟机加载的类信息、常量、静态变量、即时编译后优化的代码。应用【1.7的永久代、1.8的元空间】
堆栈区别
堆分配物理地址不连续【慢】,栈是连续的【快】
堆 | 栈 | |
---|---|---|
物理地址 | 不连续【慢】 | 连续【快】 |
分配内存时间 | 运行时 | 编译时 |
存放内容 | 实例、数组【关联数据存储】 | 局部变量、操作数栈、返回结果【关联程序方法执行】 |
可见度 | 应用程序共享 | 线程私有 |
静态变量存在方法区;静态对象存在堆中;
创建对象
方法:
调用构造函数:new关键字、Class的newInstance方法、Constructor类的newInstance方法
没有调用构造函数:clone方法 、clone方法
对象分配内存
内存规整时‘指针碰撞’、不规整时‘空闲列表’;【内存是否规整由GC是否存在压缩整理功能决定】
对象访问
句柄:指向指针的指针,对象改变时引用本身不用修改,只改变句柄中的实例数据指针。【稳定】
直接指针:指向对象,即对象在内存中的起始地址,引用存储的是对象地址。【快速】【HotSpot中应用】