在Oracle JDK 1.7(javac 1.7.0_17)上,仍然使用来实现“ +”运算符
StringBuilder,如
javap-c在类上运行以获取字节码所示(仅在此处显示循环):
public static void plusOperator();Code: 16: iload 4 18: ldc#10 // int 100000000 20: if_icmpge 53 23: new#11 // class java/lang/StringBuilder 26: dup 27: invokespecial #12 // Method java/lang/StringBuilder."<init>":()V 30: aload_0 31: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 34: aload_1 35: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 38: aload_2 39: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 42: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 45: astore 5 47: iinc 4, 1 50: goto 16public static void stringBuilder();Code: 16: iload 4 18: ldc#10 // int 100000000 20: if_icmpge 50 23: new#11 // class java/lang/StringBuilder 26: dup 27: invokespecial #12 // Method java/lang/StringBuilder."<init>":()V 30: aload_0 31: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 34: aload_1 35: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 38: aload_2 39: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 42: astore 5 44: iinc 4, 1 47: goto 16
两者之间的唯一区别是,带有“ +”的版本将循环内的转换
StringBuilder为a
String。
因此,问题就来了:为什么对于相同的代码,您的测试为什么会显示出如此不同的结果?或更完整地说, 这为什么不是有效的微基准 。以下是一些可能的原因:
- 您正在计算挂钟时间。这意味着您实际上正在衡量运行测试时JVM所做的一切。其中包括垃圾回收(这很重要,因为您要创建大量垃圾)。您可以通过获取线程CPU时间来减轻这种情况。
- 您无需验证HotSpot何时或是否在编译方法。这就是为什么您应该在进行任何微基准测试之前进行预热阶段的原因:基本上,先运行
main()
多次,然后再运行实际测试。



