0

Debugging sub-expression

Sub.x

in expression

System.out.println(Sub.x);

in given below code,to understand rule of class initialization in run-time for classes namely., class Sub and class Super in JVM memory space.

package defaultvalues;
import java.util.*;

class Super{
    static int x;
    static{
        System.out.println("Super");
    }
}

class Sub extends Super{
    Date date;
    {//instance initialisation block for date
        Calendar temp = Calendar.getInstance();
        date = temp.getTime();
    }
    static{
        System.out.println("Sub");
    }

    long alarm;
}

class Game{
    static Random rand;
    static{
        rand = new Random();
    }
    static void tossCoin(){
        if(rand.nextBoolean()){
            System.out.println("Heads");
        }else{
            System.out.println("Tails");
        }
    }

}
public class Example {
    public static void main(String[] args) {
        System.out.println(Sub.x); // class Super is loaded. From class Super, static members are
        //initialised and static initialisation blocks are executed before executing expression 'Sub.x'

        Game.tossCoin(); // class Game is loaded. From class Game, static members are initialised
        //and static initialiser blocks are executed before executing expression 'Game.tossCoin()'
        Sub obj = new Sub(); //instance variables are initialised and instance initialisation block 
        //of class A are executed.
        System.out.println(obj.date);
        System.out.println(obj.alarm);
    }

}

After debug, observation is that, class Super gets initialized but class Sub does not get initialised before expression Sub.x gets evaluated. Immediate output after evaluating expression System.out.println(Sub.x); is:

Super
0

So, System.out.println("Sub"); does not execute before expression Sub.x gets evaluated.

With respect to this expression Sub.x evaluation, in source code, I see the expression Sub.x getting evaluated, class Super gets initialized but not class Sub.

My question is:

Does class Sub get loaded & linked but not initialized before evaluating sub-expression Sub.x during run-time?

Note: Working in Eclipse environment

overexchange
  • 15,768
  • 30
  • 152
  • 347
  • Probably. If you compile with -Xlint, does the compiler issue a warning that a variable `x` is being accessed through a sub class? – markspace Jun 16 '15 at 15:58
  • *"Under the hood, Does javac compiler translate expression Sub.x to Super.x before execution?"* You can check that yourself: run `javap -c Example.class` from the console and see. – Tom Jun 16 '15 at 16:15
  • @Tom `javap` shows this: `3: getstatic #22; //Field defaultvalues/Sub.x:I` How do I understand this line? – overexchange Jun 16 '15 at 16:22
  • So, the compiler doesn't replace something there. It load the static variable `Sub.x` of type `I`nteger. – Tom Jun 16 '15 at 16:23
  • @Tom If compiler does not replace expression `Sub.x` with `Super.x`, then, why `class Sub` does not get loaded before sub-expression `Sub.x` gets evaluated? – overexchange Jun 16 '15 at 16:23
  • Just a heads up, the terms `loaded` and `initialized` are different. I believe you are referring to class initialization in this context (?) – vikingsteve Jun 16 '15 at 16:27
  • @vikingsteve yes you are right, am referring to `initialization` – overexchange Jun 16 '15 at 16:29

2 Answers2

3

The behavior you describe is given in an example in the JLS, here

Example 12.4.1-2. Only The Class That Declares static Field Is Initialized

class Super {
    static int taxi = 1729;
}
class Sub extends Super {
    static { System.out.print("Sub "); }
}
class Test {
    public static void main(String[] args) {
        System.out.println(Sub.taxi);
    }
}

This program prints only:

1729

because the class Sub is never initialized; the reference to Sub.taxi is a reference to a field actually declared in class Super and does not trigger initialization of the class Sub.

which matches the list of initialization causes

  • A static field declared by T is used and the field is not a constant variable (§4.12.4).

The field is declared by Super, not Sub.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • For your point: "because the class Sub is never initialized", I understood this point, but how do I verify/confirm if `class Sub` is loaded/linked to JVM instance before sub-expression `Sub.x` gets evaluated? – overexchange Jun 16 '15 at 17:21
  • 1
    @overexchange What specific behavior do you mean by _loaded_? Also, why do you need to confirm it? Seems like a design smell. – Sotirios Delimanolis Jun 16 '15 at 17:26
  • Am talking about these [phases](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html), when I say loaded/linked. As java programmer, I feel, It is important for me to know, whether `class Sub` is loaded in this situation. – overexchange Jun 16 '15 at 17:27
  • @overexchange You can read the rules of loading in the document you linked to, but, again, what difference will it make whether you know if it happens for your class or not? (Unless you're debugging some classloader issue, but there are better ways to do that.) – Sotirios Delimanolis Jun 16 '15 at 17:31
  • @overexchange You can use techniques described [here](http://stackoverflow.com/questions/482633/in-java-is-it-possible-to-know-whether-a-class-has-already-been-loaded) to investigate. – Sotirios Delimanolis Jun 16 '15 at 17:32
  • @overexchange Also, see the [`-verbose:class`](http://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html) VM argument. – Sotirios Delimanolis Jun 16 '15 at 17:43
  • One supplementary, As per your [link](http://stackoverflow.com/questions/482633/in-java-is-it-possible-to-know-whether-a-class-has-already-been-loaded), Is `class ClassLoader` known as bootstrap class loader? – overexchange Jun 16 '15 at 17:54
  • The boostrap class loader is a `ClassLoader` subclass provided by the JRE that starts everything. – Sotirios Delimanolis Jun 16 '15 at 17:56
  • what is the name of that subclass(bootstrap class loader)? – overexchange Jun 16 '15 at 18:11
  • @overexchange It depends on the JRE. It's an implementation detail. I believe you can get a reference to it with `ClassLoader.getSystemClassLoader()`. – Sotirios Delimanolis Jun 16 '15 at 18:14
2

It's because you haven't triggered static class initialization yet.

In the answer to a related question, here, the answer talks about the various ways to trigger class initialization.

If you made a method getX() in class Sub which returns x from it's superclass, it should perform static class initialization for Sub.

Some more reading in JLS-12.4.1.

Note in this case that "A static field declared by T is assigned." does not seem to apply, since x was declared in the superclass.

Community
  • 1
  • 1
vikingsteve
  • 38,481
  • 23
  • 112
  • 156
  • Can I say, `class Sub` gets loaded & linked but not initialized before expression `Sub.x` is evaluated? – overexchange Jun 16 '15 at 16:48
  • Yes, I believe that is true. – vikingsteve Jun 16 '15 at 16:53
  • Can I confirm this by writing java code(to verify load/link) in the above program? – overexchange Jun 16 '15 at 16:57
  • The line `Sub obj = new Sub();` already triggers static class initialization of class `Sub`, but if you want to trigger it earlier, you can for example just add this to Sub class: `static int n;` and then access it somehow, e.g. `System.out.println(Sub.n);`. – vikingsteve Jun 16 '15 at 18:08