做java编译器或JIT优化无参数静态方法

时间:2016-08-10 08:59:41

标签: java static-methods jit

我对java编译器并不精明,但想知道java是否进行了这样的优化。问题在于:

class A {

private final static Map<String, String> fruitIds = new HashMap<String, String>();
static {

        fruitIds.put("Orange", "1");
        fruitIds.put("Apple", "2");
        fruitIds.put("banana", "4");    
}
    public static Set<Integer> getSortedFruitSet() {
        Iterator<String> iterator = fruitIds.values().iterator();
        Set<Integer> returnSet = new TreeSet<Integer>();
        while (iterator.hasNext()) {
            returnSet.add(Integer.valueOf(iterator.next()));
        }
        return returnSet;
    }
}

我知道我可以在这里使用Enums,但即便如此,我可能会遇到同样的问题。每当我调用getSortedFruitSet时,它可能会创建新的TreeSet并填充它,这似乎是不必要的。我可以创建这个TreeSet的另一个静态实例,但有另一种方法来优化它吗?编译器或运行时是否对这种静态方法进行了任何优化?优化此类方法调用甚至是否有意义?

1 个答案:

答案 0 :(得分:0)

java编译器没有这样的优化

当我们用javap -c查看你的getSortedFruitSet()方法时,我们可以看到这段代码的编译版本。

    public static java.util.Set<java.lang.Integer> getSortedFruitSet();
descriptor: ()Ljava/util/Set;
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=2, locals=2, args_size=0
     0: getstatic     #2                  // Field fruitIds:Ljava/util/Map;
     3: invokeinterface #3,  1            // InterfaceMethod java/util/Map.values:()Ljava/util/Collection;
     8: invokeinterface #4,  1            // InterfaceMethod java/util/Collection.iterator:()Ljava/util/Iterator;
    13: astore_0
    14: new           #5                  // class java/util/TreeSet
    17: dup
    18: invokespecial #6                  // Method java/util/TreeSet."<init>":()V
    21: astore_1
    22: aload_0
    23: invokeinterface #7,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
    28: ifeq          53
    31: aload_1
    32: aload_0
    33: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
    38: checkcast     #9                  // class java/lang/String
    41: invokestatic  #10                 // Method java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
    44: invokeinterface #11,  2           // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
    49: pop
    50: goto          22
    53: aload_1
    54: areturn
  LineNumberTable:
    line 13: 0
    line 14: 14
    line 15: 22
    line 16: 31
    line 18: 53
  StackMapTable: number_of_entries = 2
    frame_type = 253 /* append */
      offset_delta = 22
      locals = [ class java/util/Iterator, class java/util/Set ]
    frame_type = 30 /* same */
Signature: #36

您可以看到,TreeSet始终存在newinvokespecial。 (这将创建一个新的TreeSet对象,当您查看字节码时,创建将变为两个步骤。一步new和一个invokespecial调用构造函数。

JIT编译器可以(可能)执行此操作

JIT可以在这里进行优化,但它会在经常执行的方法上执行此操作。要对此进行测试,您需要多次调用该方法并查看JIT生成的汇编代码。 我现在无法验证,但可能会回到答案,所以稍后 - 如果没有其他人同时这样做的话。

很抱歉只回答部分问题。 Java编译器(从java到字节码)一般只做很少的优化:-)