A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© 不二晨 金牌黑马   /  2018-11-19 17:17  /  881 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

创建:

创建一个Java对象的语句十分简单,无非是用一条new语句,然后调用类的构造器。但是一个对象是怎样在虚拟机内部被创建的呢?

当虚拟机遇到一条new指令时都做了什么?

1.首先检测这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个类是否被加载,解析,初始化。如果未加载则先执行加载过程;

2.为新生对象分配内存(从堆区划分一块内存);

3.虚拟机将分配的内存空间初始化为0;(保证了各个类型的默认值)

4.虚拟机对对象进行必要的设置;

5.执行<init>方法(构造方法);



为新生对象分配内存的方法:

指针碰撞:前提:堆内存绝对规整。原理:所有用过的内存在一边,未用过的内存在另一边,中间有一个指针作为分界。当划分区域时,移动指针。(非线程安全,解决办法为增加一小块本地线程分配缓冲区)
空闲列表:前提:堆内存不规整。原理:维护一个列表,在上面记录那些内存可用,那些内存已使用。当需要分配内存时在表中找到一块足够大的内存,进行划分并更新表。


对象的内存结构:

对象的内存结构分为对象头,实例数据,对其填充三块区域。

对象头:Mark Word(自身的运行时数据)+类型指针;

            Mark Word:哈希码,GC分代年龄,锁状态标识,线程持有的锁,偏向线程ID,偏向时间戳等。长度与虚拟机的字长保持一致。

            类型指针:指向其类元数据的指针。用来确定是哪一个类的对象。但并不是所有的虚拟机实现都必须在对象数据上保留类型指针。

实例数据:真正存储有效信息(字段内容);

填充对其:不是必然存在。仅起到占位符的作用。



对象的访问:Java程序通过栈上reference数据来操作堆上的具体对象。

访问方式有句柄和直接指针两种。

句柄方式:句柄细分为对象示例数据的指针和对象类型数据的指针。实现为在堆内存中划分出一块内存作为句柄池,句柄池存放句柄。访问时栈中reference访问句柄池,再间接访问到各自的具体地址。                  优点:句柄地址固定,对象的移动不会影响栈中reference。

直接指针:reference直接存储对象地址。                    优点:快。



引用分类:

强引用:最常见的引用,如object obj=new object()。强引用存在便不会被GC回收
软引用:描述一些有用但不是必需的对象。在系统将要发生内存溢出之前,将这些对象列入回收范围进行第二次回收。
弱引用:描述非必需的对象,被弱引用的对象只能存活到下一次垃圾回收之前。
虚引用(幽灵引用):最弱的一种引用,这个引用不对对象的生存时间造成任何影响,也无法通过虚引用获取一个对象。唯一作用便是系统回收之前会其对象会收到一个通知。

---------------------
【转载】
作者:zuo_h_dr
原文:https://blog.csdn.net/zuo_h_dr/article/details/83961693


4 个回复

倒序浏览
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马