IT追梦者

Programming
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JDK编译器针对final变量的优化

Posted on 2011-10-29 11:11  星龙冰  阅读(700)  评论(0编辑  收藏  举报

使用的是oracle jdk7具体版本是: (build 1.7.0_01-b08)

1.方法作用于的final变量:

源码:

public void methodScopeFinal(){
final int age = 22;
final String firstName = "xu";
int nextAge = age+1;
String name = firstName+"guoping";

 

javap -c反编译得到的jvm指令, 可以看出jvm指令中没有包含对两个final变量(方法作用于中的final成为变量是合适的,因为很多时候需要根据不同的传入参数赋予不同的值)的定义,只有对age+1和firstName+"guoping"的最后结果赋值。

  public void methodScopeFinal();
    Code:
       0: bipush        23
       2: istore_3
       3: ldc           #2                  // String xuguoping
       5: astore        4
       7: return

 

 ------------------------------------------------------------------------------------------------------------------------------------------------

 作为对比看下去掉final变量后的指令:

 public void methodScopeFinal(){

int age = 22;
String firstName = "xu";
int nextAge = age+1;
String name = firstName+"guoping";
}

 没有使用final后的指令要多出很多,包括对age和firstName两个变量的定义和赋值以及后面的加法指令和字符串连接运算指令。

  public void methodScopeFinal();
    Code:
       0: bipush        22
       2: istore_1
       3: ldc           #2                  // String xu
       5: astore_2
       6: iload_1
       7: iconst_1
       8: iadd
       9: istore_3
      10: new           #3                  // class java/lang/StringBuilder
      13: dup
      14: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      17: aload_2
      18: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: ldc           #6                  // String guoping
      23: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      26: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      29: astore        4
      31: return

 

=====================================================================================

final变量定义类: 

public class FinalClassVariableTest

{
public final int age = 22;
public final int anotherAge = getAnotherAge();
public final String firstName = "xu";
public int getAnotherAge(){
return 5;
}

 

 final变量使用类:FinalClassVariableTest 

 public void testClassFinal(){

FinalClassVariable fcVariable = new FinalClassVariable();
int age = fcVariable.age;
int anotherAge = fcVariable.anotherAge;
String name = fcVariable.firstName;
}

 

FinalClassVariableTest 上述
方法的指令可以看出对FinalClassVariable 对象中final int和string在指令中不是通过变量去引用而是直接保存对应的常量值:22和"xu",

 

因此应该注意:如果修改了primitive和string类型的final变量值,不仅要编译单个类最好要把整个工程都全部编译。否则会导致引用到final变量的地方还是修改以前的常量值。 

public static final情形编译器做相同的处理。 

上面method对应的jvm指令: 

  public void testClassFinal();
    Code:
       0: new           #2                  // class FinalClassVariable
       3: dup
       4: invokespecial #3                  // Method FinalClassVariable."<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #4                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
      12: pop
      13: bipush        22
      15: istore_2
      16: aload_1
      17: getfield      #5                  // Field FinalClassVariable.anotherAge:I
      20: istore_3
      21: aload_1
      22: invokevirtual #4                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
      25: pop
      26: ldc           #6                  // String xu
      28: astore        4
      30: return