Vraag Verschillen in Java bytecode geproduceerd door Oracle's en Eclipse-compilers


Ons project doet wat Java-bytecode-instrumentatie. En we struikelden over een vreemd gedrag. Veronderstel het volgende codefragment:

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

Oracle's javac compileert het bovenstaande in de volgende bytecode:

   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

en Eclipse's compiler in:

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

Zoals je ziet, produceert Oracle-compiler "dup" na "nieuw", terwijl Eclipse dat niet doet. Dat is helemaal correct in dit gebruik, omdat een nieuw aangemaakt geheel getal helemaal niet wordt gebruikt, dus geen "dup" is vereist.

Mijn vragen zijn:

  1. Is er enig overzicht van verschillen tussen verschillende compilers? Een artikel / blogbericht?
  2. Kan ik veilig concluderen dat als er geen "dup" is tussen "nieuw" en "invokespecial", het object dan niet wordt gebruikt na de initialisatie?

12
2018-02-09 08:05


oorsprong


antwoorden:


  1. Kan ik veilig concluderen dat als er geen "dup" is tussen "nieuw" en "invokespecial", het object dan niet wordt gebruikt na de initialisatie?

Ik weet niet zeker wat je bedoelt precies, maar een verwijzing naar het gemaakte object kan ergens door de constructor worden opgeslagen. Daarom gebruikt de aanroepende methode mogelijk niet het object na de initialisatie, maar het object is mogelijk nog steeds bereikbaar en is daarom mogelijk niet verzamelbaar.


3
2018-02-09 08:37



Als er een is dup tussen nieuwe en invokespecial dan het object is gewoonlijk gebruikt na de compilatie. Veldinitialisatie is bijvoorbeeld meestal een reeks van nieuwe, dup, invokespecial & putfield. In uw voorbeeld is de laatste instructie echter knal die de objectref van de stapel opschoont - dit is hoe je kunt aannemen dat dit object niet wordt gebruikt.


6
2018-02-09 08:19



Passing deze referentie zal dit patroon een beetje doorbreken

  public class Bump {

    Test t;

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

En dan zou je kunnen gebruiken deze om het resultaat terug op te slaan :)

  public class Test {

    Bump b;

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

Veel plezier :)


1
2018-02-09 08:57