Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - When is the 0th local variable not 'this'?

Tags:

java

bytecode

In the local variables of a Java method, when will the 0th local variable not refer to 'this'?

I can think of static methods as a counterexample, are there any others?

UPDATE: I am referring to bytecode

like image 347
user973758 Avatar asked Mar 04 '14 14:03

user973758


Video Answer


2 Answers

The JVM specification section 2.6.1 seems to think that it only depends on whether it's a static (class) method or an instance method:

The Java Virtual Machine uses local variables to pass parameters on method invocation. On class method invocation, any parameters are passed in consecutive local variables starting from local variable 0. On instance method invocation, local variable 0 is always used to pass a reference to the object on which the instance method is being invoked (this in the Java programming language). Any parameters are subsequently passed in consecutive local variables starting from local variable 1.

That's in terms of the initial values of the local variables; see Mike Strobel's answer for an example where it's explicitly changed during the method.

like image 91
Jon Skeet Avatar answered Oct 23 '22 06:10

Jon Skeet


There are two cases I am aware of when local #0 does not refer to this:

  1. In static methods, as documented by @JonSkeet.
  2. In instance methods where local #0 has been overwritten by some value other.

The second case is perfectly valid. Local #0 is only guaranteed to reference this upon entry to an instance method. Within the method, there is nothing inherently "special" about slot #0; it may be (re)written like any other slot (as can those used by formal parameters). Consider the following example in Jasmin format:

.class public HelloWorld
.super java/lang/Object

.method public <init>()V
  .limit stack 2
  aload_0
  invokenonvirtual java/lang/Object/<init>()V
  ldc              "Hello World."
  astore_0
  getstatic        java/lang/System/out Ljava/io/PrintStream;
  aload_0
  invokevirtual    java/io/PrintStream/println(Ljava/lang/String;)V
  return
.end method

.method public static main([Ljava/lang/String;)V
  .limit stack 2
  new HelloWorld
  invokenonvirtual HelloWorld/<init>()V
  return
.end method

In HelloWorld/<init>()V, we overwrite local #0 with a constant string. Thus, the second use of aload_0 loads a value other than a this pointer. It is not unusual for the same local slot to refer to different "conceptual" variables at different points in the code, especially if a class has been run through a bytecode optimizer.

So, in answer to your question: yes, there is at least one other counterexample.

like image 40
Mike Strobel Avatar answered Oct 23 '22 05:10

Mike Strobel