1:Java虚拟机内存模型主要分为5大区域,其中共有区域(线程非安全)为:Java堆、方法区,线程私有(线程安全)为:Java虚拟机栈、本地方法栈、程序计数器。
2:Java堆是用来分配对象内存,几乎所有的对象内存都在Java堆上处理。
方法区是用来存放编译后的常量、静态变量、编译后的代码缓存、类型信息。
Java虚拟机栈,Java虚拟机在调用Java方法的时候,会为每一个方法创建一个栈桢,方法的调用过程其实就是栈桢的入栈到出栈的过程。栈桢包括局部变量表、动态连接、操作数栈、方法出口。局部变量表是栈桢最重要的元素,他用来存储基本数据类型、引用数据类型等。局部变量表的大小单位是局部变量槽,除了64位的double、long占用2个局部变量槽,其他数据类型都是占用一个局部变量槽。
程序计数器是用来记录线程在JVM中运行的内存地址
3:使用new关键字实例化对象的时,Java虚拟机创建对象的过程:
①JVM接受到new关键字指令,首先判断常量池中是否有该类的符号引用,如果没有则执行类加载过程。
②类加载完成后,内存大小已经确定下来,Java虚拟机开始在Java堆上分配内存大小。
内存的分配方式有两种:
指针碰撞、空闲列表。指针碰撞指的是,将Java堆中的内存均匀分布在两边,已使用的内存放一边,未使用的内存放另一边,中间用一个指针来隔断标识。分配内存时,就是将指针从已分配的内存往未分配的内存方向,移动出一块所需要的内存大小。
空闲列表指的是,Java堆的内存分布是不均匀的,已经划分的内存与未划分的内存交错在一起,这时候Java堆需要维护一张列表,来记录堆中可使用内存的大小。分配内存时,从列表中找到一块可以分配的内存大小,并记录更新列表数据。
由于堆是线程共享的,所以堆上使用指针分配内存是线程不安全的,所以解决这种线程非安全有两种方案,一是使用CAS比较重试的规则来自旋分配。二是,使用TLAB(Thread Local Allocation Buffer)来预分配。可以设置-XX:+/-UseTABL参数来设置大小。
④完成内存分配后,将内存空间初始化零值。
⑤设置对象信息:对象实例、hashcode、GC分代年龄等信息。到此构造函数创建完成。
⑥执行Class字节码中的<Init>()。对象创建完成。
网友评论