Question

I am still trying to learn the java class file format and i understand that constant variables values are stored under the ConstantValue attribute, however i don't understand where the non constant field values are stored in the class file. Such as

public Robot robot = new Robot();

I looked through oracles class file specification and i couldn't find any attributes like this.

Était-ce utile?

La solution

The only attribute for storing initial values is the ConstantValue. However, this is only used for static variables. In Java compiled code, it's only used for static final variables, though it can be used for any static variable in handwritten bytecode. And of course, the value has to be constant.

For the example you posted, you have what is known in Java as an initializer. These have no equivalent in the classfile. Instead, the Java compiler will paste this code after every superclass constructor call returns. Note that this means that if you can view them before this point, such as by calling a virtual method in the superclass constructor, they will not have been initialized yet.

Here's an example.

public class initializers {

    static final float f = 4;
    static final int i = int.class.hashCode();
    static int i2 = 4;

    public final Object x = null;
    public Object x2 = null;


    public initializers() {}
    public initializers(int x) {this();}
    public initializers(float x) {}
}

Compiling and dissembling the class results in

.version 49 0
.class super public initializers
.super java/lang/Object

.field static final f F = 4.0F
.field static final i I
.field static i2 I
.field public final x Ljava/lang/Object;
.field public x2 Ljava/lang/Object;

.method public <init> : ()V
    .limit stack 2
    .limit locals 1
    aload_0
    invokespecial java/lang/Object <init> ()V
    aload_0
    aconst_null
    putfield initializers x Ljava/lang/Object;
    aload_0
    aconst_null
    putfield initializers x2 Ljava/lang/Object;
    return
.end method

.method public <init> : (I)V
    .limit stack 1
    .limit locals 2
    aload_0
    invokespecial initializers <init> ()V
    return
.end method

.method public <init> : (F)V
    .limit stack 2
    .limit locals 2
    aload_0
    invokespecial java/lang/Object <init> ()V
    aload_0
    aconst_null
    putfield initializers x Ljava/lang/Object;
    aload_0
    aconst_null
    putfield initializers x2 Ljava/lang/Object;
    return
.end method

.method static <clinit> : ()V
    .limit stack 1
    .limit locals 0
    getstatic java/lang/Integer TYPE Ljava/lang/Class;
    invokevirtual java/lang/Object hashCode ()I
    putstatic initializers i I
    iconst_4
    putstatic initializers i2 I
    return
.end method

As you can see, f is the only one that used a ConstantValue attribute. i did not because it wasn't a constant expression, while i2 did not because it's not final. The code to initialize i and i2 was placed in the static initializer (the 'class constructor'). The code to initialize x and x2 was pasted after both superclass constructor calls, but not in the second constructor, which just calls a constructor in the same class.

Autres conseils

There is no constant in the code you pasted. There is just a variable (which will be allocated on stack at runtime).

If you are interested in what the bytecode for a class which has a non constant field looks like, you can try this article.


The variable robot is initialized at runtime. Say, robot is in class Foo:

class Foo {
    public Robot robot = new Robot();
    Foo() {
    }
}

Now Java compiler will translate new Foo() to a sequence of instructions executing the following steps:

  • Allocate space for new object Foo on the heap. This includes space for field robot.
  • Jump to initializer instructions of class Foo
    • The Foo initializer allocates space for new instance of Robot
    • Call constructor of the parent of Foo
    • Call initializer of Robot
  • ...

So what is in the bytecode are

  • instructions for allocation and initialization of Foo
  • instructions for allocation and initialization of Robot

The conclusion is there is no space for field robot in the bytecode in the class file. There are allocation instructions which are executed at runtime and create the space for the field on the heap.


Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top