首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >空指针检查的顺序

空指针检查的顺序
EN

Stack Overflow用户
提问于 2017-07-23 06:14:10
回答 2查看 148关注 0票数 1

这些代码来自:

http://hg.openjdk.java.net/code-tools/jcstress/file/tip/tests-custom/src/main/java/org/openjdk/jcstress/tests/volatiles/ReadAfterReadTest.java

代码语言:javascript
复制
public class ReadAfterReadTest {
    private final Holder h1 = new Holder();
    private final Holder h2 = h1;
    private static class Holder {
        int a;
        int trap;
    }
    @Actor
    public void actor1() {
        h1.a = 1;
    }
    @Actor
    public void actor2(II_Result r) {
        Holder h1 = this.h1;
        Holder h2 = this.h2;
        (*****)
        // Spam null-pointer check folding: try to step on NPEs early.
        // Doing this early frees compiler from moving h1.a and h2.a loads
        // around, because it would not have to maintain exception order anymore.
        (*****)
        h1.trap = 0;
        h2.trap = 0;

        // Spam alias analysis: the code effectively reads the same field twice,
        // but compiler does not know (h1 == h2) (i.e. does not check it, as
        // this is not a profitable opt for real code), so it issues two independent
        // loads.
        r.r1 = h1.a;
        r.r2 = h2.a;
    }
}

我不明白作者所说的突出显示(*)注释是什么意思。

EN

回答 2

Stack Overflow用户

发布于 2017-07-24 04:52:56

Java spec要求在轮询它们的字段之前检查h1h2实例是否为空,即使没有显式的NPE检查-这个功能也被称为隐式空指针检查。让我们看一下汇编代码(由JIT生成):

代码语言:javascript
复制
0x00007f1fad2429f2: mov    %rbx,0x18(%rsp)
0x00007f1fad2429f7: mov    (%rsp),%rbx
0x00007f1fad2429fb: mov    0x10(%rsp),%rcx
0x00007f1fad242a00: mov    0x28(%rsp),%r10    ;*aload
0x00007f1fad242a05: mov    0x10(%rbx),%r11d   ;*getfield h1
0x00007f1fad242a09: mov    0xc(%r11),%edx     ;*getfield a
                                              ; implicit exception: dispatches to 0x00007f1fad242b37
0x00007f1fad242a0d: mov    %r12d,0x10(%r11)   ;*putfield trap
0x00007f1fad242a11: mov    0x14(%rbx),%r9d    ;*getfield h2
0x00007f1fad242a15: mov    %r12d,0x10(%r9)    ;*putfield trap
                                              ; implicit exception: dispatches to 0x00007f1fad242b49
0x00007f1fad242a19: mov    %r10,0x28(%rsp)
0x00007f1fad242a1e: mov    %rcx,0x10(%rsp)

其中解除对空指针的引用将导致SEGV信号到进程。VM有SEGV处理程序,它可以处理这个问题,并抛出一个适当的NullPointerException(NPE)。

这可以被认为是一个小的编译器屏障,它可以阻止一些优化,其中异常应该准确地抛出在它发生的地方。这种检查保证了代码的进一步执行不会导致NPE,因此编译器可以移动h1.ah2.a加载,因为它不再需要维护异常顺序。

票数 2
EN

Stack Overflow用户

发布于 2017-07-23 06:42:31

我认为他正在尝试提早生成NullPointerException。也就是说:如果h1h2在这一点上为空,那么分配h1.trap = 0将抛出一个NPE。

接下来的几行解释了为什么这会有帮助:

Doing this early frees compiler from moving h1.a and h2.a loads -我认为它与编译器和JIT所做的一些优化有关。

最简单的方法是编写一个测试类,并为您尝试访问传递的变量值和不访问时的情况生成字节码,并查看差异。

或者您可以联系作者: Aleksey Shipilev (shade) @aleksey shipilev

如果你真的想理解,我认为你需要读一些关于这方面的东西:

https://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/ http://www.javaworld.com/article/2076060/build-ci-sdlc/compiler-optimizations.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45259702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档