2015-05-10 2 views
6

Анализируя байт-код этого простого класса, я пришел к выводу, что компилятор не сохраняет информацию о локальной переменной final. Это кажется странным, хотя, поскольку я считаю, что компилятор HotSpot действительно может использовать эту информацию для оптимизации.Модификатор переменной 'final', потерянный в Bytecode?

Код:

public static void main(String[] args) 
{ 
    final int i = 10; 
    System.out.println(i); 
} 

Bytecode:

public static void main(java.lang.String[]); 
descriptor: ([Ljava/lang/String;)V 
flags: ACC_PUBLIC, ACC_STATIC 
Code: 
    stack=2, locals=2, args_size=1 
    0: bipush  10 
    2: istore_1  
    3: getstatic  #16     // Field java/lang/System.out:Ljava/io/PrintStream; 
    6: bipush  10 
    8: invokevirtual #22     // Method java/io/PrintStream.println:(I)V 
    11: return   
    LineNumberTable: 
    line 7: 0 
    line 8: 3 
    line 9: 11 
    LocalVariableTable: 
    Start Length Slot Name Signature 
     0  12  0 args [Ljava/lang/String; 
     3  9  1  i I 

Есть ли конкретная причина не сохранить флаги доступа к локальной переменной, кроме экономить дисковое пространство? Потому что для меня кажется, что final является относительно нетривиальным свойством переменной.

+4

точки доступа JITs преобразования байт-кода в представлении SSA внутри, что делает AIUI finalness лишними в любом случае. И есть другие фикции в java-land, которые не являются реальными на уровне байт-кода, например. generics – the8472

+0

Это имеет смысл для дженериков, так как они нарушили бы совместимость, но 'final' был там с самого начала. – Clashsoft

+0

проверенные исключения были бы еще одним примером. – the8472

ответ

7

Модификатор final отсутствует в байтовом коде, но компилятор уже использует эту информацию для некоторой оптимизации. Хотя ваш пример не показывает его, компилятор может встроить значение переменной final в представление метода байт-кода метода, что приведет к повышению производительности. Что-то вроде ниже, может показать разницу:

public int addFinal() { 
    final int i = 10; 
    final int j = 10; 
    return i + j; 
} 

public int addNonFinal() { 
    int i = 10; 
    int j = 10; 
    return i + j; 
} 

Сформированный байткодом соответственно для каждого метода:

// addFinal 
bipush 10 
istore_1 
bipush 10 
istore_2 
bipush 20 
ireturn 


// addNonFinal 
bipush 10 
istore_1 
bipush 10 
istore_2 
iload_1 
iload_2 
iadd 
ireturn 
Смежные вопросы