0

I am trying to check for default value of instance variables (i.e. 0 here) in the generated bytecode. I can see <init>() getting called and if I print myvar instance variable inside constructor then I see getfield called for myvar but then where was this default set first?

Please answer on following:

  1. When is default value being set in myvar? (after compilation or object creation time)
  2. Who(compiler or jvm) is initializing(or let's say setting default value) in the instance variable?
public class FieldInit {

    int myvar;

    public static void main(String[] args) {

        new FieldInit(); // and what would happen if I comment out this
    }
}

I am trying to deassemble bytecode using javap but not able to see the <clinit>() method, I guess here this may be happening. Please let me know if it is possible to see <clinit>() method and if so, how?

2 Answers 2

2

In JVM, an object instantiation is split into two bytecode instructions:

  1. new allocates a new uninitialized object;
  2. invokespecial calls a constructor that initializes the object.

The JVM Specification for the new bytecode says:

Memory for a new instance of that class is allocated from the garbage-collected heap, and the instance variables of the new object are initialized to their default initial values

The JVM sets all instance fields to zeroes when executing new instruction. So, by the time a constructor is invoked, all fields are already set to their default values. You will not find this "zeroing" in the bytecode - it's done implicitly by the JVM during object allocation.

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

2 Comments

please check @apangin "Default Values" section on docs.oracle.com/javase/tutorial/java/nutsandbolts/… It is mentioned: It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. does that not suggest that it is being done prior to running in JVM?
@Prakhar that just means that the tutorial is sloppy. The specification linked in this answer, is the authoritative document. Besides that, you already noticed yourself that there are no related bytecode instructions generated by the compiler.
0
  1. Your question is not answerable because it's more complicated than you think it is.

fields in java are encoded in a field datastructure and this datastructure includes room for the initial value. However, the only possible initial values in this data structure are numbers and strings.

Let's see it in action! (and note that L is just a java syntax thing to tell java: This number is a long, not an int. 5 is a constant, so is 5L).

class Test {
    public static final long mark = 5L;
}

javac Test.java
javap -v c Test
.....
public static final long mark;
   descriptor: J
   flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
   ConstantValue: long 5l

Hey look there it is, constant value 5L.

But what if it isn't constant?

Ah, that's a problem. You can't encode that here.

So, instead, it's syntax sugar time!

You can write a special method in any class that is run during a class's static initialization. You can also write a special method that is run as a new instance is made. That one is almost entirely the same as a constructor, with only exotic differences. It looks like this:

public class Test {
    static {
        System.out.println("What voodoo magic is this?");
    }

    public static void main(String[] args) {
        System.out.println("In main");
    }
}

Let's see it in action!

javac Test.java
java Test
What voodoo magic is this?
In main

javap -c -v Test
...
static {};
   descriptor: ()V
   flags: (0x0008) ACC_STATIC
   Code:
     stack=2, locals=0, args_size=0
        0: getstatic     #7                  // Field >java/lang/System.out:Ljava/io/PrintStream;
        3: ldc           #21                 // String Voodoo...
        5: invokevirtual #15                 // Method >java/io/PrintStream.println:(Ljava/lang/String;)V
        8: return
     LineNumberTable:
       line 3: 0
       line 4: 8
}

As you can see, that weird static{} thing was compiled to something that looks exactly like a method, bytecode and all, but the name of the method is bizarre, it's just static{}.

Here comes the clue

But what happens if we make that a little more complicated. Let's initialize this field to the current time, instead!

class Test {
    public static final long mark = System.currentTimeMillis();
}

This is just syntax sugar. That explains how this works, because as I told you, at the class file level, you cannot initialize fields with non-constants. Thus, that compiles to the same thing as:

class Test {
    public static final long mark;

    static {
        mark = System.currentTimeMillis();
    }
}

and you can javap to confirm this.

One is called a 'compile time constant'. The other isn't. This shows up in various ways. For example, you can pass a CTC as annotation parameter. Try that: try using static final long MARK = 5L; (you will be able to), then static final long MARK = System.currentTimeMillis(); - that won't be allowed.

So, where is that initial value? If it's a constant value, javap -c -v will show it. If it isn't, it's stuck in the static block.

3 Comments

Thanks @ rzwitserloot. I got your point about constant vs variable initialisation, but I want to know if I am not giving some explicit initialisation value while declaring/ inside constructor/ or in instance initialisation block then when and where it is being to 0?
@Prakhar well, javap -v -c tells the story, doesn't it? Fields that do not have an explicit 'constantvalue' initial value are instead null / 0 '\0' / 0.0 / false. In fact, null is not a valid constant value (for weird reasons). private String x = null; is read by the compiler as just private String x;.
@Prakhar The reason there is no actual = 0; code anywhere in that class file is because if there had been, that would suggest you could simply not have that code, and have a truly uninitialized field. But what does that mean? Presumably: Just claim memory, don't wipe anything out. That would be a security violation, and thus if that was possible, the Class Verifier would reject such classes. That's a ton of complication, for what? The spec correctly simplifies it all by stating explicitly that fields cannot be observed to contain uninitialized bits.

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.