对象的创建到死亡
Posted xiaosuye
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对象的创建到死亡相关的知识,希望对你有一定的参考价值。
JVM下的内存分布:
1.程序计数器:每一个线程都有一个程序计数器,执行java方法时,计数器存放着正在执行的虚拟机字节码指令的地址,执行Native方法时,计数器为空。
2.栈:线程私有,生命周期与线程的生命周期相同,内存空间在编译期完成分配,运行时不会改变。
3.堆:堆是被所有线程共享的一块内存,在虚拟机启动时创建,堆可以在物理上不连续,只要在逻辑上连续即可。
4.方法区:被所有线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码。JDK1.7后,字符串常量池移除方法区。
5.本地栈:为Nativa方法服务。
6.运行时常量池:每一个Class文件中带有一个运行时常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类的加载后进入方法区的运行时常量池中存放。
虚拟机中对象创建的过程(限于普通Java对象):
1.首先在常量池中找到要创建对象的类的引用,并且检查这个类是否已经被加载、解析和初始化。
2.这个类没有被加载,必须执行相应的类加载过程。
3.类加载通过后,虚拟机为对象分配内存。内存分配方式为指针碰撞或者空闲列表。
4.内存分配完成后,虚拟机将内存空间初始化为“零值”。
5.虚拟机对对象进行设置。(例如:这个对象属于哪个类,对象的哈希码等。这些信息在对象头之中。)
6.将对象按照代码进行初始化。
指针碰撞:在内存绝对规整的情况下,指针分界着用过的内存和空闲内存,指针向空闲内存移动对象大小的空间,被称为指针碰撞。
空闲列表:在内存不规整的抢矿下,虚拟界维护一个列表,记录着那些内存可用的,在列表中找出够大的空间存放对象,被称为空闲列表。
对象的内存布局
对象在内存中的布局可以分为三块区域:对象头、实例数据、对齐填充。
对象头包含两部分:1.存储对象之神的运行是数据,如哈希码等。2.类型指针,虚拟机通过这个指针来确定这个对象是哪个类的实力。
实例数据:代码中定义的各种字段。
对齐填充:保证对象的大小是8字节的倍数。
对象的访问定位
通过栈上的reference数据来操作栈上的具体对象,访问方式有使用句柄和直接指针两种。
使用句柄:堆中会划分一块句柄池,reference中存储的是对象的句柄地址,句柄池中的句柄中包含了对象的示例数据和类型数据的地址信息。
直接访问:reference中存放的是对象实例数据的地址,在实例数据中有对象类型数据的地址。
各自的优点:
句柄优点为:在对象移动的时候,只会该病句柄池中的句柄,不会改变reference数据本身。
直接访问优点:速度快。
怎样判定对象是否已经“死亡”?
1.引用计数法:给对象添加一个引用计数器,每当有一个地方引用这个对象时,计数器的值+1,否则计算器的值-1,任何时候,计数器的值为0,对象死亡。
缺点:很难解决对象之间互相引用的问题。
2.可达性分析算法:设置一个起始点,从起始点开始向下搜索,搜索路径被称为引用链,当一个对象到起始点之间没有一条完整的引用链时,对象死亡。
可以作为起始点的对象为:
栈中引用的对象、方法区中的静态对象、方法区中的常量对象、本地栈中的对象。
引用的分类:
强引用:代码中存在的引用,引用在垃圾回收器不会回收引用的对象。
软引用:还有用但非必要的对象,在放生内存溢出异常之前,垃圾回收器将这些对象进行第二次回收。
弱引用:也是还有用但非必要的对象,但是比软引用还要弱,垃圾啊及回收期工作时,就会对这些对象进行回收
虚引用:最弱的一中引用,无法通过虚引用老火的一个实例,对象被回收时会有系统通知。
以上是关于对象的创建到死亡的主要内容,如果未能解决你的问题,请参考以下文章