对象创建:
1、Java语言层面:new关键字
2、
1)虚拟机遇到一条new指令
2)能否在常量池中定位到该符号引用,并且判断是否已被加载,解析和初始化过,如果已经加载解析初始化就进入第4),否则进入3)
3)执行类的加载过程
4)类加载检查完成后,虚拟机为新生对象分配内存,对象所需内存空间的大小在类加载完成后便可完全确定,分配的过程等同于将一块确定大小的内存从java对中划分出来。
i)对内存分配方法
ii)如果堆内存是规整的,“指针碰撞”,所有用过的内存放到一边,空闲的内存放到另外一边,中间放着一个指针作为分界点的指示器,分配内存就是仅仅把指针项空闲的一边挪动于对象大小相等的距离
iii)如果不规整,需要维护一个列表,表明哪些内存时可用的。“空闲列表”
j)对象的创建爱你是一个频繁的操作,正在给对象A分配内存,对象B有同事使用原来的指针来分配内存
jj)对分配内存空间的动作进行同步处理,虚拟机采用cas配上失败充实的方式保证更新操作的原子性
jjj)吧内存分配动作按照线程不同划分到不同的空间之中,每个线程在java堆中预先分配一小块内存,成为本地线程分配缓冲
内存分配完成,将分配到的内存控件初始化为0,进行必要的设置,该对象的各种信息,初始化
对象内存布局
对象在内存中存储的布局可以分为3块区域:对象头,示例数据,对齐填充
对象头:
1)存储对象自身的运行时数据:如哈希码,gc分带年龄,锁状态标识,线程持有的所,偏向线程ID,偏向时间戳,mark word64bit
2)类型指针:对象指向它类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个累的实例,并不是所有的虚拟机的实现都必须在对象数据保留类型指针,超找对象元数据信息并不一定要经过底下那个本身,如果对象是一个java数组,需要在对象头中有一块用于记录数组长度的数据。
实例数据:
对象真正存储的有效信息,程序代码中所定义额各种类型字段内容,是真正有意义的数据。
对齐填充:没有特别的含义,仅仅起到占位符的作用
对象的访问定位,通过栈上面的对象引用访问堆上的具体的数据
垃圾回收的时候,引用存储的是指针信息,很稳定,垃圾回收移动对象只改变句柄中示例数据的指针,引用本身不需要改变
速度快,节省指针定位开销
JAVA内存溢出来源,不断创建对象会导致对内存溢出
虚拟机栈和本地方法栈溢出(递归)
方法区和运行时常量池溢出
本机直接内存溢出