2012-02-09 29 views
12

Nasz projekt wykonuje niektóre oprzyrządowanie kodu bajtowego Java. I natknęliśmy się na dziwne zachowanie. Załóżmy, że następujący fragment kodu:Różnice w bajtach kodu Java opracowane przez kompilatory Oracle i Eclipse:

public void a() { 
    new Integer(2); 
    } 

javac Oracle kompiluje powyższe pod następującym kodu bajtowego:

0: new #2; //class java/lang/Integer 
    3: dup 
    4: iconst_2 
    5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V 
    8: pop 
    9: return 

i kompilatora w Eclipse:

0: new #15; //class java/lang/Integer 
    3: iconst_2 
    4: invokespecial #17; //Method java/lang/Integer."<init>":(I)V 
    7: return 

Jak widać, Oracle kompilator produkuje "dup" po "nowym", podczas gdy Eclipse nie. Które jest całkowicie poprawne w tym przypadku użycia, ponieważ nowo utworzona instancja Integer nie jest w ogóle używana, więc nie jest wymagane "dup".

Moje pytania są następujące:

  1. Czy jest jakiś opis różnic pomiędzy różnymi kompilatory? Artykuł/post na blogu?
  2. Czy mogę bezpiecznie wywnioskować, że jeśli nie ma "dup" między "nowy" i "invokespecial", to obiekt nie jest używany po inicjalizacji?
+4

Jaki jest Twój cel w zakresie oprzyrządowania kodu bajtowego? Czy ta różnica powoduje u Ciebie problem? Zauważ, że nie ma gwarancji co do tego, jaki kod bajtowy będzie produkował dokładnie kompilator Java.Jest całkiem możliwe, że w przyszłej wersji Oracle 'javac' będzie produkować coś innego niż to, co widzisz teraz - więc nie jest dobrym pomysłem napisanie programu, który w dużym stopniu opiera się na dokładnym kodzie bajtowym generowanym przez kompilator. – Jesper

+0

Czy używasz różnych JDK dla Eclipse? – Nishant

Odpowiedz

3
  1. mogę śmiało stwierdzić, że jeśli nie ma „dup” między „nową” i „invokespecial” wtedy obiekt nie jest używany po inicjalizacji?

Nie jestem pewien co masz na myśli dokładnie, ale odniesienie do utworzonego obiektu mogą być przechowywane gdzieś przez konstruktora. Dlatego metoda wywołująca może nie używać obiektu po inicjalizacji, ale obiekt może być w dalszym ciągu dostępny i dlatego nie można go nazwać śmieciami.

6

Jeśli istnieje dup między nowy i invokespecial następnie przedmiotem zwykle stosowany po kompilacji. Na przykład, inicjujący pole jest zazwyczaj sekwencją nowego, DUP, invokespecial & putfield. Jednak w twoim przykładzie ostatnia instrukcja to pop, która oczyszcza obiekt ze stosu - tak możesz założyć, że ten obiekt nie jest używany.

+0

Jak zauważył A.H., pop oznacza tylko, że nie jest używany przez rozmówcę. Sam obiekt mógł zdradzić odniesienia do siebie w ctor. – Antimony

1

Przechodząc ten odniesienia złamie ten wzór trochę

public class Bump { 

    Test t; 

    public Bump() { 
     new Test(this); 
    } 
    public void setT(Test t) { 
     this.t = t; 
    } 
    } 

A potem jeden przydałby ten do przechowywania wynik z powrotem :)

public class Test { 

    Bump b; 

    public Test(Bump b) { 
     this.b = b; 
     b.setT(this); 
    } 
    } 

Miłej zabawy :)