java空检查消除会导致错误代码吗?

sqserrrh  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(248)

最近,我在这里读到了关于jvm优化的文章,非常棒,
但我有一个优化问题,即空检查消除(或不常见的陷阱)
求和空校验消除 if (obj == null) ... 希望是最好的,而如果遇到分段错误,它会重新编译代码,这一次包括被忽略的部分 if (obj == null) ... .
我的问题是,鉴于:

bool foo(MyClass obj)
{
   if(obj == null)
      return false;
   m_someVar++;
   obj.doSomething(m_someVar);
}

因为取消了空检查,并且只在 m_someVar++ .
foo会执行吗 m_someVar++ 一个额外的时间c将为空?
编辑:
对于这种优化的实现,是否有更深入的解释来源,它解释了这种优化如何保持代码的语义相同?
谢谢

0md85ypi

0md85ypi1#

有许多可能避免这个问题:延迟或撤消增量已经在评论中提到。jvm有一大堆技巧,其中一些适用于:
什么时候 obj.doSomething(m_someVar) 是非虚拟方法调用(a) private 或者 final 方法或从不重写的方法),则可能需要显式的null检查(),因为没有segv,但必须在调用之前抛出npe。我假设这个方法不是内联的,否则这个分析应该在内联之后应用。
什么时候 obj.doSomething(m_someVar) 是一个虚拟方法调用,那么您必须执行“方法分派”,例如 obj.getClass().getPointerToMethod("doSomething(int)") 以确定要调用的具体方法。我写了“像这样的东西”,因为这样做是非常耗时的,并得到尽可能多的优化。这个分派可以移动到增量的上方,它本身会抛出一个npe,如果 obj 碰巧是 null .
如果你运气好的话,派遣人员可能会 if (obj.getClass() != MyClass.class) uncommon_trap(); ,这是最简单的情况(称为“单态调用站点”),但即使这样也涉及到解引用 obj 你又一次得到了npe null .
)空检查可能看起来像 obj.getClass() 在汇编程序中,它是从相对于 obj 指针。什么时候 obj == null 然后出现一个未Map的页面。

nxowjjhe

nxowjjhe2#

它认为您误解了空检查消除实际上是什么。
实际上,它是关于消除(例如)在示例上调用方法时隐式的空检查。
在您的示例中,显式 if(obj == null) 不会被淘汰。这将(正如您所观察到的)改变程序的行为。消除空检查将是不正确的优化。
但是,在 HERE 在以下方面:

bool foo(MyClass obj)
{
   if(obj == null)
      return false;
   m_someVar++;
   obj.doSomething(m_someVar);  // HERE
}

因为jit编译器应该能够推断出 obj 在代码到达该点时始终为非空(不过,这是另一种空检查优化。)
对于这个优化的实现是否有更深入的解释。。。
我不这么认为。至少,没有什么是确定的(除非计算jit编译器源代码中可能出现的注解!)
未指定jit优化器行为。只要不违反jls中定义的java语义,它基本上可以做任何事情。
... 这解释了这种优化是如何保持代码语义相同的?
正如我所解释的,您所阅读的乐观空检查消除优化不适用于您的示例(这会使代码按照jls的要求表现不正确。)

相关问题