本文将简单介绍下java内存区域,借此加深对java虚拟机的理解;
希望对入门者有一定的引导作用,同时也作为记录帮助自己记忆,若有错误,希望大牛指点一二;
简述
java虚拟机所管理的内存包括这几个运行时数据区:程序计数器、java虚拟机栈、本地方法栈、java堆、方法区、直接内存;
参考图片(来自《深入理解java虚拟机》,推荐阅读):
程序计数器
- 当前线程所执行的字节码的行号指示器,根据这里的值来选取下一条需要执行的字节码指令;
- 每个线程都有一个程序计数器,各线程互不影响;
java虚拟机栈
- 线程私有的,线程间互不干扰,生命周期与线程相同;
- 描述java方法执行的内存模型,每个方法再执行时会建立一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息;每个方法调用至完成就对应一个栈帧(栈帧是方法运行时的基础数据结构)再虚拟机栈中入栈到出栈的过程;
- 其中局部变量表存放了编译器可知的各种基本数据类型;
- 这个区域存在两种异常状况:StackOverflowError(线程请求的栈深度大于虚拟机允许深度)和OutOfMemoryError(扩展时无法申请足够内存);
本地方法栈
- 与虚拟机栈作用相似, 为虚拟机使用的Native方法服务;
- 也会抛出StackOverflowError和OutOfMemoryError;
java堆
- java虚拟机管理内存中最大的一块, 是所有线程共享的一块内存区域;
- 用来存放对象实例;
- 是垃圾收集器管理的主要区域,又称为”GC堆”;
- 可分为新生代和老年代,再细分为Eden空间 From Survivor和To Survivor空间 ;
- 堆无法扩展时会抛出OutOfMemoryError异常;
方法区
- 各个线程共享的内存区域;
- 存储虚拟机加载的类信息、常量、静态变量、编译后的代码等;
- 内存不满足时抛出OutOfMemoryError异常;
直接内存
- 内存不够会抛出OutOfMemoryError异常;
- 不是虚拟机运行时数据区的一部分;
对象创建
- 虚拟机遇到new指令,检查参数是否能在常量池中定位到类的符号引用,若没有,先执行类加载过程(该过程会在后续文章进行分享);
- 类加载检查完,在java堆中为对象分配内存(受不同收集器影响);
- 虚拟机对对象进行一些设置:是哪个类的实例,如何查找类元数据信息,对象哈希码,对象的GC分代年龄等;
- 执行init进行初始化;
对象的访问定位
- 需要通过栈上的reference数据来操作栈上的对象;
- 两种访问方式:
- 句柄:java堆种一块内存作为句柄池,reference保存对象的句柄地址,句柄再保存对象实例数据和类型数据的具体地址信息;
- 直接指针:java堆对象放置访问类型数据,reference种存储对象地址;
以上是对java虚拟机涉及内存以及对象创建、对象访问定位流程的简单介绍,后续会继续进行相关基础和进阶知识的学习整理分享,欢迎一起讨论交流~