发布于2021-06-12 14:03 阅读(699) 评论(0) 点赞(24) 收藏(3)
Java 虚拟机在执行Java程序的过程中会把它所管理的内存划分为 5 个区域,如图
用于储存结构信息的地方,包括常量池、静态常量、构造函数等。(运行时常量池)
对象实例(几乎所有),数组。这块是 GC 的主要区域。
java 栈总是和线程关联在一起,每当创一个线程时,JVM 就会为这个线程创建一个对应的 java 栈,在这个栈中,又会包含多个栈帧,每运行一个方法就建一个栈帧,用于存储局部变量表、操作数栈、动态连接(多态)、返回地址等。每一个方法从调用直至执行完成的过程,就对应一栈帧在 java 栈中入栈到出栈的过程。(为什么 JVM 要使用栈?非常符合Java中方法间的调用)
无限递归会导致栈溢出,一般的方法调用很难出现。
指向当前线程正在执行的字节码指令的地址(用于保存当前线程执行的内存地址)。由于 JVM 程序是多线程执行的(线程轮流切换),所以为了保证线程切换回来后,还能恢复到原先状态,就需要一个独立计数器,记录之前中断的地方,可见程序计数器也是线程私有的。
保存的是 native 方法的信息,只不过是为 JVM 使用到 native 方法服务的。虚拟机规范无强制规定,各版本虚拟机自由实现。
每当线程被创建的时候,JVM 就需要为其在内存中分配虚拟机和本地方法栈记录调用方法的内容,分配程序计数器记录指令执行的位置,这样的内存消耗就是创建线程的内存代价。
先执行相应的类加载过程。
- 指针碰撞:如果java堆中内存是绝对规整的,用过内存与空闲内存各放一边,中间放着一个指针作为分界点的指示器,那指针向空间那边挪动一段与对象大小相等的距离为分配内存,这种分配方式称为“指针碰撞”。
- 空闲列表:如果java堆中内存不是规整的,使用的内存和空闲的内存相互交错,虚拟机就必须维护一个列表,记录哪些内存块是可以用的,在分配内存的时候找到一块空间划分给对象实例,并更新列表记录,这种方式称为“空闲列表”。
分配内存涉及到并发安全问题:
多个线程同时对一块内存进行分配。这里解决有2种方案
CAS 机制:虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性;
分配缓冲:把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在 Java 堆中预先分配一小块私有内存,也就是本地线程分配缓冲。
CAS 操作需要输入两个数值,一个酒店旧值 A(期望操作前的值)和一个新值B,在操作期间会先比较旧值有没有变化,如果没有变化,才换成新值,否则不进行交换。
(注意不是构造方法)内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(如int值为0,boolean值为false等)。这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型锁对应的零值。
虚拟机对对象进行必要的设置,例如这个对象是哪个实例、如何才能找到类的元数据信息、对象的哈希吗、对象的GC 分代年龄等信息。这些信息存放在对象的对象头之中。
在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角看,对象创建才刚刚开始,所有的字段都还为零值。所以,一般来说,执行 new 指令之后会接着把对象按照程序员的医院意愿进行初始化,这样一个真正可用的对象才算完全产生处理。
在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头、实例数据、对齐填充。
原文链接:https://blog.csdn.net/qq_36865892/article/details/117786031
作者:想要飞翔的天使
链接:http://www.javaheidong.com/blog/article/222159/028bbafa4eaa59e78a1f/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!