2013-06-02 2 views
4

Как часть одного из моих школьных проектов мне нужно копать в java байт-код. Я начал писать простые программы и использовать утилиту javap для просмотра сгенерированного байт-кода. У меня есть один из вопросов относительно *ipush инструкций.java bytecode - no ipush инструкция

Когда я осматриваю байткод этого кода:

public class Main{ 
    public static void main(String []args){ 
    int a; 
    a=5; 
    a=a+32765; 
    } 
} 

я получаю

public class Main 
    SourceFile: "Main.java" 
    minor version: 0 
    major version: 51 
    flags: ACC_PUBLIC, ACC_SUPER 
Constant pool: 
    #1 = Methodref   #3.#12   // java/lang/Object."<init>":()V 
    #2 = Class    #13   // Main 
    #3 = Class    #14   // java/lang/Object 
    #4 = Utf8    <init> 
    #5 = Utf8    ()V 
    #6 = Utf8    Code 
    #7 = Utf8    LineNumberTable 
    #8 = Utf8    main 
    #9 = Utf8    ([Ljava/lang/String;)V 
    #10 = Utf8    SourceFile 
    #11 = Utf8    Main.java 
    #12 = NameAndType  #4:#5   // "<init>":()V 
    #13 = Utf8    Main 
    #14 = Utf8    java/lang/Object 
{ 
    public Main(); 
flags: ACC_PUBLIC 
Code: 
    stack=1, locals=1, args_size=1 
    0: aload_0  
    1: invokespecial #1     // Method java/lang/Object."<init>":()V 
    4: return   
    LineNumberTable: 
    line 1: 0 

    public static void main(java.lang.String[]); 
flags: ACC_PUBLIC, ACC_STATIC 
Code: 
    stack=2, locals=2, args_size=1 
    0: iconst_5  
    1: istore_1  
    2: iload_1  
    3: sipush  32765 
    6: iadd   
    7: istore_1  
    8: return   
    LineNumberTable: 
    line 4: 0 
    line 5: 2 
    line 6: 8 
} 

и когда я поменять 32765 на 32769, который не находится в диапазоне коротких Я получаю

public class Main 
    SourceFile: "Main.java" 
    minor version: 0 
    major version: 51 
    flags: ACC_PUBLIC, ACC_SUPER 
Constant pool: 
    #1 = Methodref   #4.#13   // java/lang/Object."<init>":()V 
    #2 = Integer   32769 
    #3 = Class    #14   // Main 
    #4 = Class    #15   // java/lang/Object 
    #5 = Utf8    <init> 
    #6 = Utf8    ()V 
    #7 = Utf8    Code 
    #8 = Utf8    LineNumberTable 
    #9 = Utf8    main 
    #10 = Utf8    ([Ljava/lang/String;)V 
    #11 = Utf8    SourceFile 
    #12 = Utf8    Main.java 
    #13 = NameAndType  #5:#6   // "<init>":()V 
    #14 = Utf8    Main 
    #15 = Utf8    java/lang/Object 
{ 
    public Main(); 
flags: ACC_PUBLIC 
Code: 
    stack=1, locals=1, args_size=1 
    0: aload_0  
    1: invokespecial #1     // Method java/lang/Object."<init>":()V 
    4: return   
    LineNumberTable: 
    line 1: 0 

    public static void main(java.lang.String[]); 
flags: ACC_PUBLIC, ACC_STATIC 
Code: 
    stack=2, locals=2, args_size=1 
    0: iconst_5  
    1: istore_1  
    2: iload_1  
    3: ldc   #2     // int 32769 
    5: iadd   
    6: istore_1  
    7: return   
    LineNumberTable: 
    line 4: 0 
    line 5: 2 
    line 6: 7 
} 

так что теперь число хранится в постоянном пуле. Я знаю, что нет инструкции ipush, которую я мог бы использовать для толкания целочисленной константы в стек, но мне интересно, почему такой инструкции нет?

+1

Это связано с общими ограничениями на размер инструкций байткода. Int не вписывается в одну инструкцию. –

+1

@ Марко это неправда. Существуют произвольные длинные инструкции (стоп-сигнал, поисковый переключатель). Настоящая причина заключается в том, что если вам нужно указать весь int, вы можете также вставить его в постоянный пул. – Antimony

ответ

3

Основываясь на простой конструкции CISC, они пытались сделать каждую инструкцию как можно короче (в байтах). Инструкции, которые используют 32-битные или 64-битные константы, проще/короче ссылаться на постоянную таблицу.