在代码层面,我们通过new关键字创建一个对象:

Object obj=new Object();

而虚拟机中,创建一个对象,则经过了许多环节,JVM的内存结构可以通过另一篇文章了解:一个“Hello World”理解JVM运行时数据区 ,本文主要基于JVM的内存结构,聊聊对象在JVM中是怎么创建的:

  1. 虚拟机遇到new指令,首先检查new的参数是否能在方法区中的常量池中定位到一个类的符号引用,并且检查这个类是否已被加载、解析和初始化过,如果没有,则先执行类加载机制;(先check是否需要load class,确保类已加载)
  2. 接着,虚拟机将为对象在堆(Java Heap)中分配一块内存,对象所需内存的大小在类加载(Class Load)完成后已经可以确定。分配的方式主要有2种:指针碰撞(Bump the Pointer)和空闲列表(Free List)
  3. 分配完内存,虚拟机会对这些空间初始化为零值,这步操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使用。
  4. 接着初始化对象头;对象头的信息包括:类的元数据信息、哈希码、GC分代年龄、是否启用偏向锁等
  5. 调用<init>方法

关键字词典:

指针碰撞:假设Java堆中的内存是规整的,所有已分配的内存都在一边,空闲的内存在另一边,指针的位置在两者中间;当需要分配内存时,只需要将指针向空闲内存区域移动与对象大小相同的距离,这种分配方式叫做“指针碰撞”;Serial、ParNew等带Campact过程的收集器采用的就是指针碰撞;

空闲列表:假设Java堆中的内存是不规整的,这些空闲的内存由一个表在维护,当需要分配内存给一个对象时,就会在这张表中查找一个足够的空闲空间出来分配给该对象,并更新记录。基于Mark-Sweep的CMS收集器就是使用空闲列表;

TLAB:内存的分配涉及了并发时线程安全的问题,因此每个线程在Java堆中会预先分配一小块内存作为该线程的“本地缓冲区”(Thread Local Allocation Buffer),那个线程需要分配内存直接在该线程的TLAB上分配,只有TLAB用完需要分配新的TLAB时,才需要同步锁定内存。是否启用TLAB,可以通过-XX:+/-UseTLAB参数设定;第2、第3步都是在TLAB内完成。

最新文章

  1. 第50课 关于对话框(About)
  2. [No000082]Convert和Parse的区别/Convert.ToInt32()与int.Parse()的区别
  3. 在Xcode 6 beta里编译Cocos2d-x iOS项目时失败
  4. 套题 codeforces 360
  5. ubantu安装sogou输入法
  6. Js树型控件Dtree使用
  7. jquery1.11 操作checkbox:全选、取消全选、获取选择元素、获取取消选择元素(总结)
  8. download plugin update site for offline installation
  9. iOS UITextField 响应键盘的return 事件
  10. SQL学习指南第三篇
  11. .class 缓存
  12. GitHub &amp; OAuth 2.0 &amp; JWT
  13. Spring MVC的核心控制器DispatcherServlet的作用
  14. JSP显示页面和数据库乱码
  15. Python一键安装全部依赖包
  16. Openresty(Lua+Nginx)实践
  17. apache配置,禁止指定后缀访问
  18. ScrollView:ScrollView can host only one direct child异常
  19. PAT 甲级 1077 Kuchiguse
  20. Java方法重写与super关键字

热门文章

  1. vue-cli3.0 Typescript 项目集成环信WebIM 群组聊天
  2. 为什么StringBuilder是线程不安全的?StringBuffer是线程安全的?
  3. switch对输入的运算符的判断
  4. 重学js之JavaScript 面向对象的程序设计(创建对象)
  5. Day 9 用户管理
  6. 48 (OC)* 适配iPad和iPhone、以及横竖屏适配。
  7. Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析
  8. Mach-O在内存中符号表地址、字符串表地址的计算
  9. FIT文件CRC校验
  10. java8 base64使用