5

This question is provoked by this post. When a simple program like the following is run

public class Sample
{
    public static void main(String[] args)
    {
    }
}

with options -versbose:class, it lists a bunch of classes before loading this class

[Opened C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.lang.Object from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.io.Serializable from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.lang.Comparable from C:\jdk1.6.0_14\jre\lib\rt.jar]
.
.
.
.
.
.
[Loaded java.security.cert.Certificate from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded Sample from file:/D:/tmp/]
[Loaded java.lang.Shutdown from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\jdk1.6.0_14\jre\lib\rt.jar]

My questions is,

my program never needed classes like java.util.Collection, Set List and so on. Then why is Bootstrap classloader is loading them. Is this how JVM specs mandates or how Bootstrap classloader decides which classes to load ?

EDIT:

Another aspect:

Even if you try to run a non existent class, the program ends with ClassNotFoundException but not without loading all the classes mentioned earlier. So the classes are loaded merely on invoking the JVM ! So JVM loads a set of classes by default but, what governs this behavior?

Community
  • 1
  • 1
Santosh
  • 17,667
  • 4
  • 54
  • 79

3 Answers3

4

Class is the part of java.lang package and so the bootstrap class loader picks it up for loading, but Class itself requires some dependent framework classes like List or Set, so they are also loaded.

If you will see the code for Class in JDK you will find following imports

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;

Class source internally uses Collections, so it needs to be loaded.

Narendra Pathai
  • 41,187
  • 18
  • 82
  • 120
  • But the same set of classes are loaded even if you try to run a non existent class ! The crux is, these classes are loaded by simply invoking the JVM. – Santosh Dec 27 '13 at 07:46
  • Yes they will be because the java.lang package classes are automatically loaded by bootstrap classloader, and so are all the dependent classes. No matter you type non existent or existent class name. – Narendra Pathai Dec 27 '13 at 07:53
  • Also that is the reason we dont require to import java.lang imports in our source as they are pre loaded. – Narendra Pathai Dec 27 '13 at 07:54
  • 1
    But going by that logic, even the classes from `Collection` and `IO` should not be required to be imported ! – Santosh Dec 27 '13 at 07:57
  • True, but Java people cannot keep track of which classes from other packages are loaded and give default imports for them. As some may be removed and some may be added in future. Then it will become implementation dependent. – Narendra Pathai Dec 27 '13 at 07:59
  • _Java people cannot keep track of which classes..._ well, that will be done by the Bootstrap classloader (and not java people) and thats what my question is. What governs is default loading of classes. – Santosh Dec 27 '13 at 13:07
  • 1
    The class loading has nothing to do it w/ imports, as matter of fact imports are *not* translated to the bytecode at all. Classloading happens when a classRef in the constant pool is dereferenced. That being said: classloading is dynamic -always-, when something is necessary it gets loaded. – bestsss Feb 06 '16 at 07:12
3

There seems to be some misunderstanding what the bootstrap classloader is:

  • it solves the chicken/egg problem: to have a classloader instance you need -a lot- of classes, including object/classs/collections/io/nio, etc
  • a.k.a. VM's built-in classloader
  • it loads all java. classes, i.e. classes starting with java. cannot be loaded by anything else (this is part of the security model)
  • actually, bootstap classloader loads all classes provided by the JRE (for example anything from rt.jar), although if the package doesn't start w/ java. it's possible to have it loaded by an application classloader
  • object.getClass().getClassLoader() returns null as usually the bootstrap classloader is in the native/C code (part of the JVM), i.e. it's not a java class (as it cannot be loaded by itself, see chicken/egg above)
  • it's not a direct parent of any other classloader, ClassLoader.getParent() won't return it.
  • there is no formal direct way to invoke methods on it (as it doesn't exist as java class),

Now to answer the direct question: "what governs this behavior?" - When the first time an attempt is made to load a class via 'Class.forName', normally the current class' classloader asks its own parent to do so. Bootstrap classloader is considered parent of the system classloader (that loads the main class). If the current class has been already loaded by the bootstrap classloader it uses the VM to resole the class needed loading.

Last - classes in java are always loaded dynamically when they are needed, every time there is an attempt to invoke a method - it takes a fully qualified classname from the constant pool that has to be resolved. That behavior is independent from the class' classloader. So when the very 1st class is materialized by the JVM, the ball starts rolling.

bestsss
  • 11,796
  • 3
  • 53
  • 63
2

JRE probably does lazy loading, i.e. a class is loaded only when it's needed.

However, before your main class is accessed, JRE is already executing a lot of other java codes, notably, sun.misc.Launcher. That's why a lot of classes are loaded before your class.


Generally speaking, it's within JRE's discretion to load whatever classes it likes to, whenever.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.1.2

An implementation may resolve symbolic references from a class or interface that is being linked very early, even to the point of resolving all symbolic references from the classes and interfaces that are further referenced, recursively.

An implementation may instead choose to resolve a symbolic reference only when it is actively used; consistent use of this strategy for all symbolic references would represent the "laziest" form of resolution.

Note that initialization of classes happens at strictly specified moments; there's no "eager" initialization -- http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1

Community
  • 1
  • 1
ZhongYu
  • 19,446
  • 5
  • 33
  • 61