java内存区域和对象的产生

一直被java中内存组成弄的头晕眼花,这里总结下都有哪些,先上图片

程序计数器

小块内存,线程执行字节码的信号指示器,以此获取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复都要依赖他,并且每一个线程都会有自己的程序计数器,这块区域线程私有;线程执行java方法时,记录正在执行的虚拟机字节码指令地址,执行native方法,计数器值为空

虚拟机栈

java方法执行的内存模型,每个方法在指定的时候会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口,每一个方法从调用直至执行完成的过程对应一个栈帧在与你及中入栈到出栈的过程。

局部变量表存储编译器可知的基本数据类型(int,char,byte....),对象引用类型(reference,执行对象起止地址的引用指针)和return Address。其中64位长度long和double类型占用两个局部变量空间,其他数据类型占一个。并且局部变量表所需要的内存在编译期间就完成了分配

局部变量空间:

本地方法栈

和虚拟机栈作用相同,不同的是本地方法栈主要对本地方法提供服务,也就是native方法。

线程共享的一块区域,虚拟机启动时创建,存放对象实例。

方法区

存储已被虚拟机加载的类信息,常量,静态变量。

运行时常量池

编译后的class文件除了有类的版本,字段,方法,接口信息外,还好有一项信息---常量池,这部分内容在加载后就会进入到方法区的运行时常量池存放,在项目运行期间也可以产生新的常量放到池里面

一个对象的产生

虚拟机遇到new命令,检查指令中参数是都能在常量池中定位到类的符号引用【符号引用不是在堆中吗?】,检查符号是否被加载,解析或初始化,然后开始加载类。

加载全过程为加载,验证,准备,解析和初始化5个阶段。

1)加载,1-1,通过类的全限定名获取类的二进制字节流(这个阶段没有指定从哪里获取,怎么获取,多以可以进行一些处理);1-2,把字节流代表的静态存储结构转化为方法区的运行时数据结构;1-3,内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口。

2)验证,连接阶段第一步,确保文件中字节流包含该信息符合当前虚拟机要求
3)准备,正式为类变量分配内存并设置类变量初始值阶段,变量使用内存在方法区中分配,这个时候分配的内存只包括类变量(static修饰的),没有实例变量。并且这时候只是为变量赋值为0,真正的复制在初始化时才会执行
4)解析,常量池中符号引用替换为直接引用,
5)初始化,最后一步,开始执行字节码,并初始化,为变量赋值

// 第一版,只是单纯的把知识点记一下,明天进行详细修改

posted @ 2019-03-15 17:29  以苦做舟  阅读(169)  评论(0编辑  收藏  举报