Bản trình bày không hoàn toàn chính xác hoặc bạn không hiểu đúng.
Thực tế, JVM có thể các phương thức không tĩnh nội tuyến, ngay cả với varargs. Hơn nữa, nó có thể loại bỏ phân bổ các mảng Object[]
tương ứng trong một số trường hợp nhất định. Thật không may, nó không làm điều này khi một phương pháp vararg lặp qua mảng bằng cách sử dụng vòng lặp for
.
Tôi đã thực hiện tiêu chuẩn JMH sau để xác minh lý thuyết và chạy nó với GC profiler (-prof gc
).
package bench;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class VarArgs {
@Benchmark
public void inlineNonStatic(Blackhole bh) {
inlineNonStaticVA(bh, "foo", 4, new Object());
}
@Benchmark
public void inlineStatic(Blackhole bh) {
inlineStaticVA(bh, "foo", 4, new Object());
}
@Benchmark
public void loopNonStatic(Blackhole bh) {
loopNonStaticVA(bh, "foo", 4, new Object());
}
@Benchmark
public void loopStatic(Blackhole bh) {
loopStaticVA(bh, "foo", 4, new Object());
}
public void inlineNonStaticVA(Blackhole bh, Object... args) {
if (args.length > 0) bh.consume(args[0]);
if (args.length > 1) bh.consume(args[1]);
if (args.length > 2) bh.consume(args[2]);
if (args.length > 3) bh.consume(args[3]);
}
public static void inlineStaticVA(Blackhole bh, Object... args) {
if (args.length > 0) bh.consume(args[0]);
if (args.length > 1) bh.consume(args[1]);
if (args.length > 2) bh.consume(args[2]);
if (args.length > 3) bh.consume(args[3]);
}
public void loopNonStaticVA(Blackhole bh, Object... args) {
for (Object arg : args) {
bh.consume(arg);
}
}
public static void loopStaticVA(Blackhole bh, Object... args) {
for (Object arg : args) {
bh.consume(arg);
}
}
}
-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining
cho thấy rằng tất cả 4 phiên bản đều được sắp xếp thành công vào người gọi:
@ 28 bench.VarArgs::inlineNonStaticVA (52 bytes) inline (hot)
@ 27 bench.VarArgs::inlineStaticVA (52 bytes) inline (hot)
@ 28 bench.VarArgs::loopNonStaticVA (35 bytes) inline (hot)
@ 27 bench.VarArgs::loopStaticVA (33 bytes) inline (hot)
Kết quả xác nhận rằng không có sự khác biệt về hiệu năng giữa gọi tĩnh so với các phương pháp không tĩnh.
Benchmark Mode Cnt Score Error Units
VarArgs.inlineNonStatic avgt 20 9,606 ± 0,076 ns/op
VarArgs.inlineStatic avgt 20 9,604 ± 0,040 ns/op
VarArgs.loopNonStatic avgt 20 14,188 ± 0,154 ns/op
VarArgs.loopStatic avgt 20 14,147 ± 0,059 ns/op
Tuy nhiên, GC profiler chỉ ra rằng vararg Object[]
mảng được phân bổ cho loop*
phương pháp, nhưng không phải cho inline*
phương pháp.
Benchmark Mode Cnt Score Error Units
VarArgs.inlineNonStatic:·gc.alloc.rate.norm avgt 20 16,000 ± 0,001 B/op
VarArgs.inlineStatic:·gc.alloc.rate.norm avgt 20 16,000 ± 0,001 B/op
VarArgs.loopNonStatic:·gc.alloc.rate.norm avgt 20 48,000 ± 0,001 B/op
VarArgs.loopStatic:·gc.alloc.rate.norm avgt 20 48,000 ± 0,001 B/op
Tôi đoán, điểm ban đầu là các phương pháp tĩnh luôn là đơn hình. Tuy nhiên, JVM cũng có thể phương thức đa hình nội tuyến nếu không có quá nhiều người nhận thực tế trong trang web cuộc gọi cụ thể.
Bạn muốn chắc chắn rằng phương pháp này không bị ghi đè nếu nó không phải là 'tĩnh'? (và nó không phải là 'private' hoặc' final' hoặc là) – Tom
@Tom: JVM * biết * liệu một phương thức có bị ghi đè hay không. Nếu biết mọi lớp được nạp. – Holger