Java中内存区域与对象的概念和作用
这篇文章主要讲解了“Java中内存区域与对象的概念和作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中内存区域与对象的概念和作用”吧!
1、Java虚拟机包含以下几个运行时数据区域:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区。
2、程序计数器
1)在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等都需要依赖计数器来完成;
2)为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,因此是线程独立的;
3)如果正在执行一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,,这个计数器的值则为空;
4)此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
3、Java虚拟机栈
1)线程私有,生命周期与线程相同;
2)描述的是Java方法执行的内存模型:每个方法执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程;
3)两种异常:*Error和OutOfMemoryError。
4、本地方法栈
1)与虚拟机栈作用相似,区别是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈为虚拟机使用到的Native方法服务;
2)两种异常:*Error和OutOfMemoryError。
5、Java堆
1)所有线程共享,存放对象实例和数组;
2)Java堆是垃圾收集器管理的主要区域;
3)Java堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可;
4)如果没有内存完成实例分配,并且堆也无法扩展时,将抛出OutOfMemoryError异常。
6、方法区
1)所有线程共享,存放被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;
2)JDK1.8仍然保留方法区的概念,只不过实现方式不同,取消永久代,方法存放于元空间(Metaspace),元空间仍然与堆不相连,但与堆共享物理内存,逻辑上可认为在堆中;
3)无法满足内存分配需求时,将抛出OutOfMemoryError异常。
7、使用new创建对象的过程
1)类加载检查。首先检查这个指令的参数是否能在常量池中定位到一个符号引用,并检查这个符号引用代表的类是否已经被加载、解析和初始化,如果没有,则必须执行类加载过程;
2)分配内存。两种分配方式:指针碰撞和空闲列表。指针碰撞要求Java堆内存是绝对规整的,空闲列表允许Java堆不规整。采用那种方法取决于采用的垃圾收集器。
3)考虑并发问题。两种方案:一种是CAS+失败重试保证原子性,另一种是本地线程分配缓冲(TLAB),事先给每个线程分配一小块内存,分配完了才需要同步锁定。
4)初始化零值。保证对象的实例字段在Java代码中不赋初值就可以直接使用。
5)设置对象信息。例如对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象头中。
6)执行<init>方法。
8、对象的内存布局
1)3块区域:对象头、实例数据、对齐填充;
2)对象头:包含两部分信息,一部分用于存储自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向锁线程ID、偏向时间戳等,另一部分是类型指针,指向它的类元数据的指针。
3)实例数据:是一个对象真正存储的有效信息。
4)对齐填充:并不是必然存在的,由于HotpotVM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,因此没有对齐的部分需要通过填充来补全。
9、对象的访问定位:主流的访问方式有使用句柄和直接指针两种,HotSpt采用的第二种方式访问对象。
感谢各位的阅读,以上就是“Java中内存区域与对象的概念和作用”的内容了,经过本文的学习后,相信大家对Java中内存区域与对象的概念和作用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!