对象发布与逃逸-this逃逸

作者: 兰塔项 | 来源:发表于2017-09-16 22:20 被阅读274次

    what is this escape?

    在《Java Concurrency in Practice》一书的第三章提到了对象的发布与逃逸。作者举了this指针逃逸的例子。所谓的“this逃逸”,指的是在构造函数返回之前,其他线程就已经取得了该对象的引用。此时,对象尚未完成实例化,还是残缺的,取得对象引用的线程使用残缺的对象可能引发令人遗憾的错误。作者举的例子,不太容易理解,下面对该例子做适当扩展来理解“this逃逸”。

    show me the code

    我在com.gongjun.study.concurrency包下建了下面的三个类:

    public class ThisEscape {
    
        private final int num;
    
        public ThisEscape(EventSource source) {
            source.registerListener(new EventListener() {
                public void onEvent(Object o) {
                    doSomething(o);
                }
            });
            num = 42;
        }
    
        private void doSomething(Object o) {
            if (num != 42) {
                System.out.println("Race condition detected at " + new Date());
            }
        }
    }
    
    public class EventSource {
    
        public void registerListener(EventListener listener) {}
    
    }
    
    public interface EventListener {
    
        public void onEvent(Object o);
    }
    

    analysis the code

    1.手动编译源代码,生成class文件

    javac EventSource.java EventListener.java ThisEscape.java
    
    image.png

    我们看到对ThisEscape中的内部匿名类EventListener生成了对应的class文件ThisEscape$1.class

    2.查看ThisEscape的字节码

    javap -verbose ThisEscape.class
    
    image.png

    在ThisEscape的构造器中,new了一个匿名类ThisEscape$1,并将自己作为入参,即为我们所说的this引用。

    3.查看匿名类ThisEscape$1的字节码

    javap -verbose ThisEscape\$1.class
    
    image.png

    从字节码中,我们看到匿名类确实持有了外部类的引用。

    由此,我们可以看出确实发生了对象(this)的逃逸,EventSource中的registerListener完全有可能在异步线程中执行,某种情况下ThisEscape还没完全构造完全,而在EventListener的匿名类中通过持有this引用,调用ThisEscape的doSomething方法,会出现不满足预期的结果。

    reference

    How Does "this" Escape?
    深入JAVA002_对象的发布和逃逸 --this解惑

    相关文章

      网友评论

        本文标题:对象发布与逃逸-this逃逸

        本文链接:https://www.haomeiwen.com/subject/naiusxtx.html