一、对象的创建

1、虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

2、虚拟机将为新生对象分配内存

  • 指针碰撞:Java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离
  • 空闲列表:Java堆中的内存并不是规整的,已使用的内存和空闲的内存相互交错,虚拟机就必须维护一个列表,记录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。

3、虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)

4、虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头(Object Header)之中

5、执行<init>方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

二、对象的内存布局

1、对象头(Header)
  • Mark Word:存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。

这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit,官方称它为“Mark Word”。

  • 类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
个类的实例
2、实例数据(Instance Data):对象真正存储的有效信息,
在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
 
3、对齐填充(Padding):不是必须存在的,仅仅是为了字节对齐。

三、对象的访问定位

java程序需要通过栈上的reference数据来操作堆上的具体对象。

句柄访问:

Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。
好处:reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要修改。

直接指针:

Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址。
好处:速度更快,它节省了一次指针定位的时间开销,由于对象的访问在Java中非常频繁,因此这类开销积少成多后也是一项非常可观的执行成本。

java面试-对象的创建、内存布局、访问定位的更多相关文章

  1. Java虚拟机-对象的创建和访问

    一.对象的创建: 创建对象在java上面是很简单的,使用new关键字就可以了,但是其实在虚拟机中,java对象的创建是一个复杂的过程. 当java虚拟机遇到一个new的指令的时候,对象创建的程序正式启 ...

  2. JVM 专题十二:运行时数据区(七)对象的实例化内存布局与访问定位

    1. 对象的实例化 1.1 创建对象的方式 new 最常见的方式 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 Class的newInstance() ...

  3. JVM运行时数据区--纵向补充--对象的实例化内存布局与访问定位

    对象的实例化 创建对象的方式 1.new:最常见的方式(本质是构造器) 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 2.Class的newInsta ...

  4. 【Java】对象的创建过程

    一.对象的创建过程 1.首次创建对象时或该类静态方法/静态域首次被访问时,JAVA解释器查找该类的路径,定位该类的class文件 2.载入该类的class文件,有关静态初始化的所有动作执行,但是只执行 ...

  5. java中对象的创建过程

    public class Test1 { public static void main(String[] args) { new B(); System.out.println("---- ...

  6. 深入理解java虚拟机---对象的创建过程(八)

    1.对象的创建过程 由于类的加载是一个很复杂的过程,所以这里暂时略过,后面会详细讲解,默认为是已加载过的类.着重强调对象的创建过程. 注意: 最后一步的init方法是代码块和构造方法. 以上是总图,下 ...

  7. Java中 对象的创建于调用

    Main方法是程序的主入口,想要用某个方法必须在main方法中调用 创建对象: 类名 对象名 = new 类名(); 使用对象访问类中的成员: 对象名.成员变量: 对象名.成员方法(); 成员变量的默 ...

  8. Java多线程——对象及变量的并发访问

    Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...

  9. Java匿名对象导致的内存泄漏

    这几天与在某群与群友讨论了Runnable匿名对象导致内存泄漏的相关问题,特此记录一下. 示例代码如下: package com.memleak.memleakdemo; public class L ...

随机推荐

  1. JavaScript中判断对象是否属于Array类型的4种方法及其背后的原理与局限性

    前言 毫无疑问,Array.isArray是现如今JavaScript中判断对象是否属于Array类型的首选,但是我认为了解本文其余的方法及其背后的原理与局限性也是很有必要的,因为在JavaScrip ...

  2. JS广度优先遍历

    自己用JS实现了 广度优先遍历 第一种用了数组的高阶函数,看起来有些复杂.然后思索着从可读性上优化了一下,孰优孰劣以后分析. var list = [{ id: "ab", chi ...

  3. 小记一下递归通过id寻找一条链路的数据

    Array.prototype.remove = function(val) { var index = this.indexOf(val); if (index > -1) { this.sp ...

  4. nginx反向代理理解

    实际开发中,会有不同的环境: - 开发环境:自己的电脑- 测试环境:提供给测试人员使用的环境- 预发布环境:数据是和生成环境的数据一致,运行最新的项目代码进去测试- 生产环境:项目最终发布上线的环境 ...

  5. JVM线上故障初步简易排查

    线上故障主要包括cpu 磁盘 内存 网络等问题 依次排查 1.cpu 1) 先用ps找到进程pid 2) top -H -p pid 找到cpu占用高的线程 3)printf '%x\n' pid 获 ...

  6. MVCC多版本并发控制器

    在多个事务并发执行的时候,MVCC机制可以协调数据的可见性,事务的隔离级别就是建立在MVCC之上的: MVCC机制通过undo log链和ReadView机制来实现: undo log版本链: 在数据 ...

  7. 中心化-ESB

    服务调用者与服务提供者通过企业服务总线相连接: ESB成为瓶颈:无论在性能上还是成本消耗上,ESB都会导致瓶颈出现.

  8. Android中Context样式分析

    目录 1.样式定义以及使用 1.1.默认样式 1.2.样式定义及使用 1.3.当前样式下attr属性的获取 1.4.属性集合的定义与获取 2.Activity中Theme的初始化流程 2.1.系统调用 ...

  9. C++指针的算术运算 、关系运算

    下面随笔是关于指针的算术运算 .关系运算. 指针类型的算术运算 指针与整数的加减运算 指针++,--运算 指针类型的算术运算 指针p加上或减去n 其意义是指针当前指向位置的前方或后方第n个数据的起始位 ...

  10. iPhone去除input默认样式

    /*<!---->去掉苹果短的样式*/ input[type="button"], input[type="submit"], input[type ...