加入收藏 | 设为首页 | 会员中心 | 我要投稿 吉安站长网 (https://www.0796zz.com.cn/)- 科技、图像处理、媒体智能、办公协同、操作系统!
当前位置: 首页 > 站长资讯 > 评论 > 正文

打造超级互联城市的好处

发布时间:2021-02-17 11:36:54 所属栏目:评论 来源:互联网
导读:用句柄访问方式的最大好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是很普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要修改。 直接指针 reference中存储的直接就是对象地址,此时对象的布局中就必须考虑

用句柄访问方式的最大好处就是reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是很普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要修改。

直接指针

reference中存储的直接就是对象地址,此时对象的布局中就必须考虑如何放置对象类型数据的指针。

HotSpot虚拟机采用的就是这种方式。

 

体是方法区中的运行时常量池,因为class文件中有一个常量池,用于存放编译期生成的各种字面量和符号引用,这部分信息在类加载后进入方法区的运行时常量池中存放)。

如果有读者可以给出明确的结论,还请不吝赐教!

句柄式

在Java堆中划分出一块内存用作句柄池,reference中存储对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。

 

JVM数据区 私有/共享 创建时机 生命周期 垃圾收集 内存溢出 程序计数器 线程私有 线程启动时 与线程相同 无 无 虚拟机栈 线程私有 线程启动时 与线程相同 无 StackOverflowError OutOfMemoryError 本地方法栈 线程私有 线程启动时 与线程相同 无 StackOverflowError OutOfMemoryError Java堆 线程共享 JVM启动时 与进程相同 主要区域 OutOfMemoryError: Java heap space 方法区 线程共享 JVM启动时 与进程相同 较少出现 OutOfMemoryError: PermGen space 对象初探秘

对象的创建

在Java中,从语言层面上来看,创建对象通常只是一个 new 关键字而已,而在虚拟机中,对象(这里讨论的对象仅限于普通对象,不包括数组和Class对象)的创建又是怎样一个过程呢?

虚拟机遇到一条 new 指令时:

执行类加载检查

  • 检查指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载、解析和初始化过。
  • 若没有,则执行相应的类加载过程。

为新生对象分配内存

指针碰撞

假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把指针向着空闲内存那边移动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”。

空闲列表

如果Java堆中的内存并不是规整的,已使用内存和空闲内存相互交错,那就没办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记录哪些内存块是可用的,在分配的时候从列表中找出一块足够大的空间划分给对象实例,并更新列表上的记录,这种分配方式称为“空闲列表”。

如何选择分配方式

选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否带有 压缩整理 功能决定。因此,在使用Serial、ParNew等待Compact过程的收集器时,系统采用的分配算法是指针碰撞,而使用CMS这种基于Mark-Sweep算法的收集器时,通常采用空闲列表。

对象的内存布局

在HotSpot虚拟机中,对象在内存中存储的布局可以分为 3 块区域:对象头(Header)、实例数据(Instance Data)、和对齐填充(Padding)。

对象头

对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志等,官方称这些数据为 “Mark Word” 。

对象头的另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过该指针来确定这个对象是哪个类的实例。但并非所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说,查找对象的元数据信息并不一定要经过对象本身。另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通对象的元数据确定该对象的大小,但是从数组的元数据中却无法确定数组的大小。

实例数据

实例数据是对象真正存储的有效信息,也是在程序代码中定义的各种类型的字段内容。无论是从父类继承下来的,还是子类中定义的,都需要记录。

对齐填充

对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM要求对象起始地址必须是8字节的整数倍,话句话说,就是对象大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数,因此,当对象的实例数据部分没有对齐时,就需要通过对齐填充来补全。

对象的访问定位

Java程序需要通过栈(具体是虚拟机栈中的局部变量表)上的reference数据来操作堆上的具体对象。而reference如何定位、访问堆中对象的具体位置,则取决于不同的虚拟机实现。目前主流的访问方式有使用 句柄 和 直接指针 两种。

问题:毫无疑问,局部变量中的reference存放在栈中,那么成员变量中的reference又是存放在哪里?

笔者也是看到这里时感到疑惑,上网查证了很多,但是说法不一,有的认为在栈中(一概而论:对象在堆,引用在栈),有的认为在堆中


 

(编辑:吉安站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读