1.对象的创建过程:
1.new 类名
2.根据new的参数在常量池中定位一个类的符号的引用。
3.如果没找到这个符号的引用,说明类还没有被加载。则进行类的加载,解析和初始化
4.虚拟机为对象分配内存(位于堆中)。
5.将分配的内存初始化为零(不包括对象头),即抽象属性初始化为null,基本数据类型初始化为0.
、 6.调用对象的<init>方法
2.给对象分配内存的方式:
1.指针碰撞。这种方式前提是堆内存规整的并不是杂乱的,比如,将堆内存分为两块,一块是未使用的,一块是已经使用的。堆内存中未使用和已使用的交错存放则是不规整得 。
2.空闲列表。这种方式适用于堆内存不规整的。原理:虚拟机必须维护一张列表,这张列表记录堆中哪些内存块可用,哪些不可用。当分配内存中,就从这表中找出一块可用的内存
区域给新对象。再更新这张表。
内存的分配方式是有java中的堆是否规整来决定。而堆的规整是由垃圾回收策略来决定的。如果垃圾回收的过程中如果堆内存的 压缩整理,则应该使用指针碰撞
方式,反之则使用空闲列表。
3.在遇到高并发的情况下,给对象分配内存还会带来线程安全性问题。比如,一个线程进来给对象分配内存,在高并发的情况下,另外又有一个线程进来了,第一个线程还没来的及更新内存分配。而另外一个
线程刚好又申请了这块内存。这就导致了线程不安全问题。
解决方式:
1.线程同步。一个线程进来加一把锁,知道这个线程释放这把锁后,其他线程才能进来。这种方式也不失为一个解决办法。但是这种方式效率慢。
2.本地线程分配缓冲(TLAB)。做法就是为每一个线程分配一块单独的内存区域。这样就解决了线程不安全问题。而且效率大大提高。如果单独的内存区域满了后,我们还可以
继续利用线程同步再分配一块单独的内存区域给每一个线程。