我去!秋招了还不了解JVM的逃逸分析

当初在面试时,当面试官问道jvm的对象分配在哪里时,我十分自信的回答道:“分配在堆中”。盲目自信。
当然也不是说这种回答是错误的。其实对象还可以分配在栈内存当中,接下来就说一下对象是如何分配在栈内存以及为什么分配到栈中。
如何判断一个对象是不是应该分配到栈内存当中呢。那就不得不说一下逃逸分析了。
逃逸分析不是一种优化机制,而是一种判断某一段代码是不是可以被优化的一种判断方法。逃逸分析大体上分为两种。一是方法逃逸。二是线程逃逸。
方法逃逸又分为三种:
1.全局赋值逃逸,这种逃逸就是一个方法中的对象赋值给了一个全局变量。

	public class Reg {
		 public static Object obj;
		/**
		* 对象逃逸出方法
		*/
		public void teset(){
			obj = new Object();
			System.out.println(obj);
		}
	}

2.方法返回逃逸,一个方法将方法体中创建的对象做了返回。

	 public Object teset(){
		Object obj = new Object();
		System.out.println(obj);
		return obj;
	}

3.实例引用逃逸,一个方法体中的对象作为形参被别的方法引用。

/**
     * 对象没有逃逸出方法
     */
    public void teset(){
        Object obj = new Object();
        System.out.println(obj);
        test1(obj);
    }
    public void test1(Object obj){
        System.out.println(obj.toString());
    }

线程逃逸:
1.当一个对象赋值给了静态变量,就是逃逸出了线程。

public class Reg {
		 public static Object obj;
		/**
		* 对象逃逸出线程
		*/
		public void teset(){
			obj = new Object();
			System.out.println(obj);
		}
	}

上面说了逃逸分析的几种类型,那么下面说一下逃逸分析完了之后做什么。
当逃逸分析发现某一个对象没有逃逸出方法时,JVM就会对代码进行优化。如何优化?
1.栈上分配:
JIT(即时编译器)将某个对象分配到栈内存当中。当对象分配到栈内存当中时就不需要进行垃圾回收。因为垃圾回收主要是针对堆内存的,栈内存中的对象会随着栈帧的弹出进行销毁。
2.标量替换
标量:一个不可再分的变量,如八大基本数据类型以及reference。
当一个对象是不可被外部方法访问时,并且这个对象是可以被分解的,那么程序运行时不一定会创建这个对象,而改为创建它的若干个被这个方法使用到的成员变量来代替,JIT将一个聚合量替换成多个标量,而标量一般也是存储在栈内存当中的,这也是现在代码优化的主要方法。

public class Reg {
    public void getStudent(){
        Student student = new Student(18,"窝嫩叠");
        System.out.println("age:"+student.age+",name:"+student.name);
    }
}

class Student{
    public int age;
    public String name;

    public Student(int age,String name){
        this.age = age;
        this.name = name;
    }
}
/**
标量替换之后
*/
public void getStudent(){
        int age = 18;
        String name = "窝嫩叠";
        System.out.println("age:"+age+",name:"+name);
    }

3.锁消除
众所周知,锁是一个十分消耗内存的机制。当逃逸分析时,分析出这个对象无法被其他线程访问,就会将这个对象的锁消除掉。

public void f() {
    Object hollis = new Object();
    synchronized(hollis) {
        System.out.println(hollis);
    }
}
/**
消除锁之后
*/
public void f() {
    Object hollis = new Object();
        System.out.println(hollis);
}

逃逸分析是默认开启的,当然并不是说逃逸分析没有问题,逃逸分析肯定也是有时间和空间消耗的,当逃逸分析完之后发现没有没逃逸的对象,就会出现得不偿失的问题。
更新补充:JIT即时编译器在java17中因为没有被广泛使用被删除了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值