兴起聊Java(二)

思考一下,Java的引用变量存储于栈中,对象存储于堆中。程序是怎么通过引用变量获取到真实的对象呢?

引用数据类型几乎都有指针。指向堆内存某个对象。指针是C语言中的概念,在C中指针能做更多的事情。但是在java中只能记录一个类似对象地址的数据。

	重点:

	      在Java中: 在栈中为指针分配空间时,这块空间存的不是对象的真实物理地址,而更像一个随机标识符,它能通过它找到对象。具体这个指针存的是什么(我猜是某块内存的编号)。

	可以说java中的指针是一种受限指针。

既然说到堆和栈,不如聊聊JVM的内存结构。

我接着利用上篇文章建立的一个对象student对象来举例。

Student student = new Student();

提出问题,例如,当利用student引用变量去调用一个goSchool()方法时,究竟引发了多少操作?

首先要明白一个问题,student是存储于栈中的变量表中的,它仅仅是一个变量而已,它本身是不具备goSchool()这个方法的。

在此之前还要明白一个问题,JVM是一种虚拟机,它能够执行字节码文件,也就是说我要执行一个goSchool()方法,我就必须要得到该方法的指令码!

但是字节码文件中在类装载的过程中是被加载进元空间的。

好了,到这里已经出现了三种概念, 栈(student)、堆(new Student())、元空间(Student.class)。

student.goSchool()

简单来讲,这个调用方法的动作就几步。

1、栈中变量通过指针确定 new Student()这个对象的位置。

2、堆中的对象又通过头指针确定Student.class的位置,经过动态链接的操作将字面量(符号引用)转为直接引用。

3、执行引擎执行获取到字节码二进制命令,方法执行完毕后通过方法出口将结果返回。

说到这里,还可以深入说说堆、栈这两个的数据结构。只说Java的话,可以接着聊聊Java对象。

刚刚提到了Java对象的头指针,那么就来聊聊一个普通Java对象的创建过程吧。

在HotSpot虚拟机中,也就是我们的常用虚拟机。

对象组成分为3个区域:对象头、实例数据、对齐填充。

 (对象头包括分带年龄)

例如:实例对象Object obj = new Object();

markword

	占8个字节。

class pointer 类型指针

占4个字节

类型指针,也就是指向此对象的类元数据(.class字节码文件)的指针,也就是通过这个指针来知道这个对象是哪个类的实例,但不是所有的虚拟机实现都是通过这个来查找类的元数据的。

instance data

		按数据类型的字节大小来算(没有就为0)

padding

	假如是64位虚拟机,padding现在就是4个字节。

总结: 对象的内存大小必须能被8整除,如何不能用padding填充。

	markword + instancedata = 12 ; padding = 4; 结果=16;

也就是说,一个最最最简单的普通对象大小最起码就是16字节。用padding填充的内存空间也被叫做损失空间。

简述一个对象的创建过程:

Object obj = new Object();

1、当一个对象一旦被实例化,类加载器开始运作。

2、首先为类文件分配内存,第一步初始化变量为0或者null;

3、执行类的构造方法,将符号引用转为直接引用,这时堆中的类变量才会转为对应的真实值。

ps:所有方法执行完毕后便会销毁。构造方法也不例外。 最后会将该类的字节码文件存入元空间,这个上面已经说过。

最后将栈顶引用型数值 obj 存入第二个本地变量,存入主线程栈中的局部变量表中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值