深入了解Java技术(3)Java虚拟机对象探秘

创建对象很多人说Java时面向对象编程,之所以这样说因为程序运行过程中都有对象被创建出来,在代码中通常用new关键字
你知道虚拟机时怎样创建对象?
虚拟机遇到new指令,通过在常量池里检查是否这个指令的参数(类的符号引用)已被加载,解析,初始化,如果没有的话,虚拟机去执行相应的类加载过程,经过上述的检查通过后虚拟机对新生对象分配内存,分配内存的原理就是Java堆中的内存分为用过的和空闲中间有指示器当分界线,当有新的对象,指针挪动一段与对象大小相等的距离,这种方式称为’指针碰撞’,
如果指示器不是在内存之间的话就不会指针碰撞,这样的话虚拟机就需要存一个列表记录哪些内存是可用的,对象实例分配内存时将在列表找到空闲内存划分给他剩下的再记录在空闲列表中,这种方式称为‘空闲列表’
选择哪种分配方式都是Java堆决定
有两种情况,在使用serial和parnew等带compact过程的收集器时是指针碰撞,在使用CMS这种基于MARK-sweep算法的收集器时是空闲列表在对象创建后我们需要关注一个问题,如果对象创建非常频繁的话,仅仅修改一个指针所指向的位置,在并发情况下线程也是不安全的,假如正在给对象A分配内存,指针还没得急改指针,对象B就进来
结果对象A和对象B同时使用了一个对象解决问题有两种方式
一个是对分配内存时进行同步操作,采用CAS配上失败重试方式来保证
另一种分配内存时按照不同线程划分在不同的空间内进行。就是把每个线程事先都分配一小块内存称为‘本地线程分配缓冲’,只有本地线程分配缓冲用完需要分配新的本地线程分配缓冲,需要同步锁定。运行Java虚拟机时可以通过-XX:+/-UseTLAB参数设定 ,如果这样的话保证了对象的实例字段在Java代码中可以不给初始值,直接用,因为对象分配内存完成后都初始化为零值
通过我上面讲的,怎么在虚拟机java堆创建对象分配内存,在程序来说才刚刚开始,init方法没有执行所有字段都为零,在我们开发者角度来说这个对象还没有创建成功,通过new指令执行init方法后这个对象才创建成功

1.详细介绍对象的内存布局
一个对象在内存布局中分为3块局域 对象头,实例数据和对齐填充
对象头:一部分用于存储对象自身的运行数据,比如哈希码,GC分代年龄,锁状态标志,线程持有的锁等等,另一部是类型指针就是对象指向他的类元数据的指针,虚拟机通过这个来确定这个对象是哪个类的对象,再一个不一定所有的虚拟机实现都必须在对象数据上保留类型指针,普通Java对象的元数据信息可以确定Java对象的大小,如果是数组的元数据无法确定数组的大小
实例数据:对象真正存储的有效信息就是代码中所定义的各种类型的字段内容,不管父类继承下来的,还是子类定义的都得记录一下,储存顺序根据虚拟机分配策略和字段在Java源码定义的顺序有影响
对齐填充:不一定存在,有占位符的作用就是对象的大小必须是8字节的整倍数,而对象头部分正好是8字节的倍数,如果对象实例数据部分没有对齐时,需要对齐填充补全
2.详细介绍对象的访问定位
创建对象为了使用对象,Java程序需要通过栈上的reference数据来操作Java堆的对象实例,refere类型只是指向对象的引用,关于引用通过何种方式去定位,访问堆中的对象的具体位置,取决于虚拟机实现而定的,访问方式有两种为句柄和直接指针。
句柄
Java堆中将会划分为一块内存来作为句柄池,reference中储存的就是对象的句柄地址,句柄中包含了对象实例数据与类型数据各自的具体地址信息 。简单说 Java栈中本地变量表通Java堆中的句柄池指入对象实例数据
直接指针
Java栈中本地变量表通Java堆中的对象类型数据的指针指入方法区中的对象类型数据
各有各的优势 使用句柄来访问好处 reference中存储的是最稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改,使用直接指针访问好处:访问速度快,节省了一次指针定位的时间开销,如果对象访问非常频繁,执行成本非常可观

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听不见你的名字

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值