Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When classes are loaded?

Well, I've got such a code:

public class Main {
    public static void main(String[] args) {
        Test t; //1
        Integer i = new Integer(1); //2
        t = new Test(); //3
        System.out.println(Test4.a); //4
    }
}

class Test {
    private int a = 10;
    private Test2 t2; //5

    List<Test2> list = new ArrayList<Test2>() {
        {
            for (int i = 0; i < a; i++) {
                add(new Test2()); //6
            }
        }
    };
}

class Test2 extends Test3{
}

class Test3 {
}

class Test4 {
    public static final int a = 4;
}

I don't know how (fully or partially) and when classes are loaded. So:

  1. Test t; - it is not an active usage, but the reference t must be a definite type of. Was Test class loaded (maybe partially, then how many stages - loading\linking\initializing - it passed) or nothing happened?
  2. Integer i = new Integer(1); - was Integer loaded when JVM starts or on this line?
  3. t = new Test(); - an active usage. Was it loaded fully from the beginning or from some point (see 1)
  4. System.out.println(Test4.a); - was Test4 loaded or not?
  5. Were Test2 and Test3 loaded or not? If yes then when?
like image 966
Tim Marcusenko Avatar asked Oct 20 '15 18:10

Tim Marcusenko


1 Answers

When classes are loaded is covered by the JLS, Section 12.4.1.

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.

  • T is a class and a static method declared by T is invoked.

  • A static field declared by T is assigned.

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

  • T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

(snip)

A class or interface will not be initialized under any other circumstance.

Chapter 5 talks about loading, linking, and initializing classes.

The Java Virtual Machine dynamically loads, links and initializes classes and interfaces. Loading is the process of finding the binary representation of a class or interface type with a particular name and creating a class or interface from that binary representation. Linking is the process of taking a class or interface and combining it into the run-time state of the Java Virtual Machine so that it can be executed. Initialization of a class or interface consists of executing the class or interface initialization method (§2.9).

Your questions:

  1. Declaring a variable doesn't load the class. But loading happens before linking, and linking happens before initialization. So, when a class is loaded, it is also then linked and initialized.
  2. The Integer class is loaded by the JVM (along with lots of other language foundation classes) before your code runs.
  3. Now the Test class is loaded, because a new instance is created.
  4. Test4 was not loaded, because only a constant variable was used, which conflicts with the 4th rule above.
  5. Test3 and Test2 were loaded after Test was loaded, because Test2 objects were created in Test's instance initializer, which also caused Test3 (the superclass) to be loaded.

This is confirmed when running your code with the JVM option -verbose:class.

like image 114
rgettman Avatar answered Oct 05 '22 04:10

rgettman