普通对象的创建(不包括数组和class对象)

  当虚拟机遇到new指令时,会在常量池中检查是否包含这个类的符号引用(全限定名),通过这个确定是否经过类加载的过程,如果true,为该

对象分配内存,对象大小在类加载过程就已经确定。如果false,需要进行类加载。

分配内存

1、分配内存的方式:

  指针碰撞:如果内存是绝对规整的,使用过的在一边,未使用过的在另一边,中间有个指针作为分界点的指示器,为对象分配内存的时候,只需

要向未使用过的一边移动与对象大小相同的距离完成内存分配

  空闲列表:内存非规整的情况下,jvm通过维护一个列表记录哪些内存可用,在分配内存的时候,从列表里面找到一个大于对象大小的内存进行

分配,并且更新列表记录使用哪种内存分配方式取决于使用哪种垃圾收集器:

  Serial、ParNew等带有Compact过程,采用指针碰撞

  类似CMS这种基于Mark-Sweep算法的收集器,采用空闲列表

2、并发环境下分配内存

  如果给对象A分配内存的时候,指针还没来及修改,对象B使用原来的指针来分配内存(类似脏读)

解决方案

  ①.对分配内存的动作进行同步处理--通过CAS+失败重试的方式保证操作的原子性(了解CAS机制可以查看Atomic源码)

  ②.使用本地线程缓冲区TLAB,就是为每个线程在堆中预先分配一小块内存,各个线程分配内存相互不影响(类似ThreadLocal变量概念),只

有在TLAB用完重新分配新的TLAB时,才需要进行同步处理。通过-XX:+/-UseTLAB参数配置是否使用TLAB

  上述分配内存动作完成。

初始化内存

  此时,jvm将分配的内存空间初始化为零值(不包含对象头),如果使用TLAB,在分配TLAB时提前完成这一步

作用:

  为了保证用户没有赋初值的情况下也是可以使用

  然后设置对象头保存的一些信息,例如:这个对象是哪个类的实例,如何找到类的元数据信息、对象的哈希码、GC分代年龄等。
  都完成之后,VM角度来看,一个对象已经产生,但程序的角度,对象创建才刚开始——<init>方法还没执行,所有字段都是零值,初始化过程,

一个真正的对象才完成

对象的内存布局(HotSpot)

1、对象头Header

  ①存储对象本身的运行时数据,如hashcode,GC分代年龄、锁状态标志、线程持有的锁等

  ②类型指针:对象指向本身类元数据的指针,虚拟机就是通过类型指针确定对象是哪个类的实例。但不是所有的对象都保存类型指针,所以查

找类的元数据也不一定通过对象本身

  针对数组,Header还要一个记录数组长度的数据,因此无法通过数组的元数据确定数组大小,但是普通java对象是可以的

2、实例数据Instance Data

  对象真正存储的有效数据,也就是代码定义的各种类型字段,无论是从父类继承的,还是子类本身定义的。相同宽度的字段被分配到一起。满

足这个条件前提下,父类定义到子类前,但是如果CompactFields=true,子类较小的变量也可能插入到父类变量的空隙

3、对齐填充Padding

  不是必然存在的,没有特别的意义,起着占位符的作用,对象起始地址要是8字节的整数倍,就是对象的大小必须是8字节的整数倍,对象头是8

字节的1倍或2倍,当对象实例数据部分没有对齐时,需要对齐填充来补全。

对象的访问定位

  java程序通过栈中的reference操作堆中的具体数据。

定位方式:

  ①.句柄访问(间接):堆中维护一个句柄池,本地变量表中reference存储的就是对象的句柄地址,句柄池包含了对象实例数据(堆)和类型数

据(方法区)各自的地址信息

  ②.直接指针访问:reference中存储的就是对象实例数据,实例数据有指向方法区中的对象类型数据的指针

对比

  句柄访问的优点:reference中保存的只是句柄地址,如果对象GC被移动只需要改变实例数据指针,reference本身不需要改变

  指针访问的优点:速度更快。节省一次指针定位的时间开销,因为对象访问在java很频繁,所以节省的时间开销是很客观的。HotSpot采用指针访问

java虚拟机(三)--HotSpot 对象的更多相关文章

  1. 深入理解Java虚拟机(二)——HotSpot对象创建、内存、访问

    对象的创建 虚拟机遇到一条字节码new指令时,开始对象创建过程. 首先去检查这个指令的参数是否能在常量池定位到一个类的符号引用: 检查这个符号引用代表的类是否已被加载.解析和初始化,如果没有就必须执行 ...

  2. Java虚拟机三:OutOfMemoryError异常分析

    根据Java虚拟机规范,虚拟机内存中除过程序计数器之外的运行时数据区域都会发生OutOfMemoryError(OOM),本文将通过实际例子验证分析各个数据区域OOM的情况.为了更贴近生产,本次所有例 ...

  3. 深入理解java虚拟机(三)-----类加载机制

    类加载机制jvm把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被jvm直接使用的java类型.在java中,类型的加载.连接和初始化都是在程序运行期间完成的 ...

  4. 深入理解Java虚拟机(三)——垃圾回收策略

    所谓垃圾收集器的作用就是回收内存空间中不需要了的内容,需要解决的问题是回收哪些数据,什么时候回收,怎么回收. Java虚拟机的内存分为五个部分:程序计数器.虚拟机栈.本地方法栈.堆和方法区. 其中程序 ...

  5. 深入理解Java虚拟机(四)——HotSpot垃圾收集器详解

    垃圾收集器 新生代收集器 1.Serial收集器 特点: 单线程工作,收集的时候就会停止其他所有工作线程,用户不可知不可控,会使得用户界面出现停顿. 简单高效,是所有收集器中额外内存消耗最少的. 没有 ...

  6. Java虚拟机三 Java堆和栈

    Java堆是和Java应用程序关系最为紧密的内存空间,几乎所有的对象都存放在堆中.并且堆是完全自动化管理的. 根据垃圾回收机制的不同,Java堆有可能有不同的结构.最为常见的一种就是将整个Java堆分 ...

  7. 虚拟机性能监控与故障处理工具(深入理解java虚拟机三)

    JDK自带的工具可以方便的帮助我们处理一些问题,包括查看JVM参数,分析内存变化,查看内存区域,查看线程等信息. 我们熟悉的有java.exe,javac.exe,javap.exe(偶尔用),jps ...

  8. 深入理解Java虚拟机(三)、垃圾收集算法

    1.第一门真正使用内存动态分配和垃圾收集技术的语言:Lisp 2.程序计数器.虚拟机栈.本地方法栈这3个区域随线程而生灭,这几个区域的内存会随着方法结束或线程结束而回收,GC关注的是Java堆和方法区 ...

  9. 基于Java的三种对象持久化方式

    1:序列化技术: 序列化的过程就是将对象写入字节流和从字节流中读取对象.将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,可以通过管道或线程读取,或通过网络连接将对象 ...

随机推荐

  1. 异步FIFO的编程

    对于异步FIFO.最基本的两个方面是地址控制和空.满标志位的产生.首先地址控制分别为读地址和写地址,每次读写时能读写地址应该加1.计数次数为ram深度的2倍.当读写地址相等时则空标志位有效,当读写地址 ...

  2. linux用户进程分析

           经过实验3的介绍.我们须要来点实在的.所以将我们理解的流程用于linux系统的分析.换句话说.通过类比的方式去进行描写叙述与理解linux相关的部分. 本节的内容非常详实.并且也分析 ...

  3. wxpc

  4. 【OI】关于斯特林数的简单理解

    斯特林数分为第一类斯特林数:S1(n,k)和第二类斯特林数:S2(n,k). S1(n,k)代表在n个元素中选出k个环的方案数,S2(n,k)代表在n个元素中选出k个非空集合的方案数, 不同之处在于, ...

  5. projecteuler----&gt;problem=12----Highly divisible triangular number

    title: The sequence of triangle numbers is generated by adding the natural numbers. So the 7th trian ...

  6. YTU 2632: B2 友元光顾

    2632: B2 友元光顾 时间限制: 1 Sec  内存限制: 128 MB 提交: 378  解决: 241 题目描述 定义一个平面上的点类Point,其中设置成员函数distance1求当前对象 ...

  7. Opencv+Zbar二维码识别(二维码校正)

    二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图: 这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~. 这里介绍一种二维码校正方法,通 ...

  8. POJ2686 Traveling by Stagecoach 状态压缩DP

    POJ2686 比较简单的 状态压缩DP 注意DP方程转移时,新的状态必然数值上小于当前状态,故最外层循环为状态从大到小即可. #include <cstdio> #include < ...

  9. VMware 虚拟机下挂载U盘

    1.首先设置虚拟机为连接的可移动U盘 2.首先在虚拟机界面的情况下,插入U盘,U盘格式为fat32的 3.在mnt目录下新建一个文件夹usb 4.运用sudo fdisk -l /dev/sdb 来查 ...

  10. 揭秘Node.js深受欢迎的原因

    揭秘Node.js深受欢迎的原因 http://www.php100.com/html/dujia/2014/1127/7922.html