13

Our project does some Java bytecode instrumentation. And we stumbled upon some strange behavior. Suppose the following code snippet:

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

Oracle's javac compiles the above into the following 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

and Eclipse's compiler into:

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

As you can see, Oracle compiler produces "dup" after "new", whereas Eclipse doesn't. Which is totally correct in this use case, as newly created Integer instance is not used at all, so no "dup" is required.

My questions are:

  1. Is there some overview of differences between different compilers? An article/blog post?
  2. Can I safely conclude, that if there is no "dup" between "new" and "invokespecial" then object is not used after initialization?
2
  • 4
    What is your goal with instrumenting the bytecode? Does this difference cause a problem for you? Note that there is no guarantee about what bytecode exactly a Java compiler will produce. It's entirely possible that in a future version Oracle's javac will produce something different than what you see now - so it's not a good idea to write a program that heavily relies on the exact bytecode produced by the compiler. Commented Feb 9, 2012 at 8:19
  • Do you use different JDK for Eclipse? Commented Feb 9, 2012 at 8:19

3 Answers 3

6

If there's a dup between new and invokespecial then the object is usually used after the compilation. For instance, field initialization is usually a sequence of new, dup, invokespecial & putfield. However, in your example the last instruction is pop which cleans the objectref from the stack - this is how you can assume that this object isn't used.

Sign up to request clarification or add additional context in comments.

1 Comment

As pointed out by A.H., the pop only means that it isn't used by the caller. The object itself could give away references to itself in the ctor.
3
  1. Can I safely conclude, that if there is no "dup" between "new" and "invokespecial" then object is not used after initialization?

I'm not sure what you mean exactly, but a reference to the created object might be stored somewhere by the constructor. Therefore the calling method might not use the object after initialization but the object might still be reachable and might be not garbage collectable therefore.

Comments

1

Passing this reference will break this pattern a bit

  public class Bump {

    Test t;

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

And then one could use this for storing the result back :)

  public class Test {

    Bump b;

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

Have fun :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.