我并不十分了解编译器和JIT优化的内部知识,但我通常会尝试使用“常识”来猜测什么可以优化,哪些不能。所以我在写一个简单的单元测试方法今天:如何编写(测试)不会被编译器/ JIT优化的代码?
@Test // [Test] in C#
public void testDefaultConstructor() {
new MyObject();
}
这种方法实际上是我所需要的。它检查默认的构造函数是否存在并且运行时没有异常。
但后来我开始考虑编译器/ JIT优化的影响。编译器/ JIT可以通过完全取消new MyObject();
语句来优化此方法吗?当然,它需要确定调用图对其他对象没有副作用,这是普通构造函数的典型情况,它只简单地初始化对象的内部状态。
我认为只有JIT可以执行这样的优化。这可能意味着它不是我应该担心的事情,因为测试方法只执行一次。我的假设是否正确?
尽管如此,我正在考虑一般的主题。当我想到如何防止这种方法被优化时,我想我可能assertTrue(new MyObject().toString() != null)
,但这非常依赖于toString()
方法的实际实现,即使如此,JIT也可以确定toString()
方法总是返回一个非null字符串(例如,如果实际上调用了Object.toString()
),并因此优化整个分支。所以这种方式是行不通的。
我知道在C#中我可以使用[MethodImpl(MethodImplOptions.NoOptimization)]
,但这不是我真正想要的。我希望找到一种(语言无关)的方式,确保我的代码的某些特定部分能够按照我的预期实际运行,而JIT不会干扰此过程。
此外,是否有任何典型的优化案例,我应该知道创建我的单元测试?
非常感谢!
谢谢。我想知道为什么JIT的行为如此?如果一个对象分配是无用的(在某些情况下实际上可以通过静态分析来确定),为什么JIT不会对它进行优化? – 2009-02-13 22:46:21
虽然我现在可以想到一个角落案例,但我认为这很少见。如果为了确保有足够的内存可用于某些其他对象(甚至确保不会发生分页)而完成对象分配,则优化将使该假定失效。 – 2009-02-13 22:48:24
需要将Java虚拟机(JVM)保持在与根据Java内存模型在JVM中执行程序代码一致的状态。在JIT可以证明代码对可观察程序状态没有影响的情况下,并不需要实际执行任何特定代码或分配内存。 – 2013-05-20 20:18:38