暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

秒懂运行时数据区

长夜难眠 2020-08-10
380

点击蓝字

关注dd


作用


JVM在执行JAVA程序时会把它管理的内存区域划分为若干个不同的数据区域,统称为运行时数据区。而对其进行划分主要是便于不同类型数据的管理。


分布


运行时数据区可划分为程序计数器、Java虚拟机栈、本地方法栈、方法区、和堆。其中又可分类为线程私有和线程共享的。


程序计数器 


程序计数器拥有较小的内存空间,而且是线程私有的,存储线程当前执行指令的地址。


Java虚拟机栈 


Java虚拟机栈是线程私有的,存储局部变量表、操作数栈、动态链接以及方法出口等。


本地方法栈


本地方法栈与虚拟机栈所发挥的作用是非常相似的。


其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务。而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。


方法区 


方法区是线程共享的,存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。


方法区属于堆的一部分,具体实现由JDK决定 ,在JDK7的实现是永久代, JDK8的实现是元空间。


Java堆 


最大的一块内存空间,在虚拟机启动时创建。


Java堆是线程共享的,存储着对象实例、数组。


Java堆划分为新生代、老年代,这两部分内存的比例为1:2。


新生代又可划分为Eden、Servivor0、Servivor1区,比例为8:1:1。


关于对象


对象存储在堆内存中。


创建对象的方式


创建对象的方式有几种:通过new关键字的方式。


通过调用Class的newInstance()方法。


Construstor的newInstance()方法(推荐)。


使用反序列化、使用clone()方法。


使用第三方库Objenesis等。


创建对象的步骤


判断对象是否加载、链接、初始化。


分配内存:规整内存,进行指针碰撞。不规整内存,虚拟机维护空闲列表。


处理并发安全问题:采用cas失败重试策略保证原子性-给每个线程分配一块TLAB空间。


初始化分配到的空间:所有属性设置默认值。


设置对象头。


执行init方法。


对象的内存布局


对象头:运行时元数据(hashCode、GC分代年龄、锁状态标志位、线程持有的锁、偏向线程id、偏向时间戳)、类型指针(指向类元数据instanceKlass,确定该对象所属的类型)、如果是数组,还要记录数组长度。


实例数据:存储程序代码中定义的各种类型的字段,相同宽度的字段总是被分配在一起,父类定义的变量会出现在子类之前。


对齐填充:不是必须的,仅仅起到占位符的作用。


局部变量表


局部变量表存放了编译期可知的各种Java虚拟机基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型)和returnAddress类型(指向了一条字节码指令的地址。


数据类型在局部变量表中的存储空间以局部变量槽(Slot)来表示,其中64位长度的long和double类型的数据会占用两个变量槽,其余的数据类型只占用一个。


异常


StackOverFlowError:Java虚拟机栈、本地方法栈。


OutOfMemoryError:堆、Java虚拟机栈、本地方法栈、方法区。



喜欢本篇内容请给dd点个在看


文章转载自长夜难眠,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论