您的位置:首页 > 其它

浅谈-栈上分配和逃逸分析

2019-10-18 16:55 190 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/C_Xiang_Falcon/article/details/102628569

浅谈-栈上分配和逃逸分析

  • 前体分析
  • 结论
  • 前体

    让我们先来看一段代码

    String s = "a" + "b"

    请问这代码产生了几个对象?
    有的人可能会说3个
    有的人可能会说1个

    这里先不说答案,我们先回顾下什么是对象,对象放在哪里?
    一般情况下,我们把放在堆里面的称之为对象
    也就意味着对象只能放在堆里面

    其实并不是这样,对象其实并不是只能放在堆里面
    它也能放在栈里面

    这里就要讲到第一个概念:

    栈上分配

    public void test(){
    User user = new User();
    
    user....
    }

    正常情况下
    当User对象使用完后,并且之后一段时间内都不再被用到时
    对象就会在堆中等待被gc回收
    但并不是马上被回收,而是等待一个空间的时间
    而gc并不能由我们控制,所以gc的自动回收机制很不是很好

    那么这里就有一个疑问?
    既然这个对象用完后,就不再被使用
    为何要放到堆里面等待被回收呢,何不放在栈里面用完就被弹出去不是很好嘛!

    等对象一旦用完,就马上被释放掉 这就是栈上分配的原理

    那肯定又有人说既然这个机制这么好,我们都把对象放在栈里不是更好吗?!
    其实不见得
    这里就要引入第二个概念

    逃逸分析

    逃逸分析的原理:
    就是分析这个对象的引用有没有逃出栈的范围

    情景一

    public void test(){
    User user = new User();
    
    user....
    
    return user;
    }

    当user使用后,不能马上被回收掉
    如果被回收掉了
    这是 test 的返回结果要被其他方法进行使用,就会报错
    这是对象就绝对不能放在栈内存中,只能放在堆里面

    情景二

    public void test(User user){
    
    user....
    }

    上述情况中的user来自更大范围域中,
    它的作用域远远大于test
    不能在 test 方法结束后,就被回收掉

    逃逸分析在分析对象时,会考虑
    对象引用要是放在更大的范围中被引用,就绝对不能把对象放在栈里面
    但发现对象逃不是栈的范围,就能被放入栈里面

    所以对象不仅可以放在堆中,也能放在栈中

    前体分析

    所以回到我们最早的案例

    String s = "a" + "b"
    println(s)
    

    答案肯定是

    ab

    那么到底产生多少对象,我们可以通过字节码进行查看


    看到 a 了吗?
    看到 b 了吗?
    我们只能看到 ab

    结论

    公式中只产生了一个对象

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: