对象创建过程
创建对象的几种方式
1. new关键字 Object obj = new Object();
2. 反射
3.克隆
4.反序列化
创建对象的过程
1.创建过程
(1)检查是否加载过
虚拟机解析new指令,首先检查常量池是否有类的符号引用,并且检查是否已经加载解析和初始化,没有就执行类加载过程
2.多线程下分配空间时安全性问题
TLAB: 为每一个线程预先分配一块内存,JVM在给线程中的对象分配内存时,首先在TLAB分配,当对象大于TLAB中的剩余内存或TLAB的内存已用尽时,再采用CAS进行内存分配。
CAS: CAS 是乐观锁的一种实现方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。
 
3.对象的内存布局

对象都是在堆中么?(逃逸)
逃逸的基本行为是分析对象的动态作用域,分析指针动态范围的方法称之为逃逸分析 当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他过程或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。
1.方法逃逸
//方法逃逸 public Dog testEscape(){ Dog dog = new Dog(); return dog; }
//未发生方法逃逸 public void testEscape(){ Dog dog = new Dog(); dog.run(); }
2.线程逃逸
//线程逃逸 public static void testEscape(){ Dog dog = new Dog("小黑"); new Thread(new Runnable() { @Override public void run() { dog.run(); } }).start(); }

3.栈上分配
在一般应用中,不会逃逸的局部对象占比很大,如果使用栈上分配,那大量对象会随着方法结束而自动销毁,垃圾回收系统压力就小很多。
4.同步消除
线程同步本身比较耗时,如果确定一个变量不会逃逸出线程,无法被其它线程访问到,那这个变量的读写就不会存在竞争,对这个变量的同步措施可以清除。
5.标量替换。
  (1)标量就是不可分割的量,java中基本数据类型,reference类型都是标量。相对的一个数据可以继续分解,它就是聚合量(aggregate)。
                 (2)如果把一个对象拆散,将其成员变量恢复到基本类型来访问就叫做标量替换。
 (3) 如果逃逸分析证明一个对象不会被外部访问,并且这个对象可以被拆散的话,那么程序真正执行的时候将可能不创建这个对象,而改为直接在>栈上创建若干个成员变量。
6.相关JVM参数
         -XX:+DoEscapeAnalysis 开启逃逸分析
          -XX:+PrintEscapeAnalysis 开启逃逸分析后,可通过此参数查看分析结果。
          -XX:+EliminateAllocations 开启标量替换
          -XX:+EliminateLocks 开启同步消除
          -XX:+PrintEliminateAllocations 开启标量替换后,查看标量替换情况
7.总结
如果项目中的大部分方法中的对象都不会逃逸,那么可以开启逃逸分析、开启标量替换、开启同步擦除。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号