Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The classes loaded by Bootstrap Classloader

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?

like image 876
Santosh Avatar asked Dec 27 '13 07:12

Santosh


3 Answers

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.

like image 50
Narendra Pathai Avatar answered Oct 20 '22 10:10

Narendra Pathai


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.

like image 40
bestsss Avatar answered Oct 20 '22 10:10

bestsss


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

like image 42
ZhongYu Avatar answered Oct 20 '22 08:10

ZhongYu