我在这里看到了很多关于比较并试图回答哪个更快的线程:newInstance
还是new operator
。
从源代码来看,newInstance
应该会慢得多,因为它要进行很多安全检查,并使用反射。我决定先测量一下 jdk-8,在这里使用 jmh
。
@BenchmarkMode(value = { Mode.AverageTime, Mode.SingleShotTime })
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@State(Scope.Benchmark)
public class TestNewObject {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder().include(TestNewObject.class.getSimpleName()).build();
new Runner(opt).run();
}
@Fork(1)
@Benchmark
public Something newOperator() {
return new Something();
}
@SuppressWarnings("deprecation")
@Fork(1)
@Benchmark
public Something newInstance() throws InstantiationException, IllegalAccessException {
return Something.class.newInstance();
}
static class Something {
}
}
我认为这里没有太大的惊喜(JIT进行了许多优化,使得这种差异不是那么大):
Benchmark Mode Cnt Score Error Units
TestNewObject.newInstance avgt 5 7.762 ± 0.745 ns/op
TestNewObject.newOperator avgt 5 4.714 ± 1.480 ns/op
TestNewObject.newInstance ss 5 10666.200 ± 4261.855 ns/op
TestNewObject.newOperator ss 5 1522.800 ± 2558.524 ns/op
在热代码方面的差异大约为 2x ,对于单次运行时间更加糟糕。
现在我切换到jdk-9(如果有影响,则为版本157)并运行相同的代码。 结果如下:
Benchmark Mode Cnt Score Error Units
TestNewObject.newInstance avgt 5 314.307 ± 55.054 ns/op
TestNewObject.newOperator avgt 5 4.602 ± 1.084 ns/op
TestNewObject.newInstance ss 5 10798.400 ± 5090.458 ns/op
TestNewObject.newOperator ss 5 3269.800 ± 4545.827 ns/op
这是热代码的惊人50倍差异。我正在使用最新的jmh版本(1.19.SNAPSHOT)。
在测试中添加了另一种方法后:
@Fork(1)
@Benchmark
public Something newInstanceJDK9() throws Exception {
return Something.class.getDeclaredConstructor().newInstance();
}
这里是jdk-9总体结果:
TestNewObject.newInstance avgt 5 308.342 ± 107.563 ns/op
TestNewObject.newInstanceJDK9 avgt 5 50.659 ± 7.964 ns/op
TestNewObject.newOperator avgt 5 4.554 ± 0.616 ns/op
有人可以解释一下为什么会有如此大的差异吗?
Class.newInstance()
在Java 9中已被弃用。推荐使用的替代方法是clazz.getDeclaredConstructor().newInstance()
,其性能值得关注... - HolgerSomething
中的非public
(默认访问)构造函数。 - Holger