The process of loading a class
The main task of the ClassLoader is to load the class files into the JVM. As the following illustration shows, the process is divided into three steps:
1. Load: Locate the class file to load and load its byte stream into the JVM;
2. Link: Assign the most basic memory structure to the class to be loaded to save its information, such as attributes, methods, and referenced classes. At this stage, the class is still in an unusable state;
(1) Verification: the load of the word stream verification, such as format, security aspects;
(2) Memory allocation: Prepares the memory space for the class to represent its properties, methods, and referenced classes;
(3) Parsing: Loading other classes referenced by the class, such as the parent class, the implemented interface, and so on.
3. Initialization: Assign a value to a class variable.
class Loader hierarchy
the following figure dashed above is a few important class loaders provided by the JDK, as detailed below:
(1) Bootstrap class Loader: When the class that contains the main function is started, load the jar package in the Java_home/lib directory or-xbootclasspath the specified directory;
(2) extention Class Loader: Loads the jar packages under the Java_home/lib/ext directory or-djava.ext.dirs the specified directory.
(3) System class Loader: Loads a class or jar package under CLASSPATH or-djava.class.path specified directory.
What you need to know is:
1. In addition to bootstrap class loader, other ClassLoader are subclasses of the Java.lang.ClassLoader class;
2.Bootstrap class loader is not implemented in Java, if you do not use the Personalization class loader, then Java.lang.String.class.getClassLoader () is Null,extension class The loader parent loader is also null;
3. Several ways to obtain the ClassLoader:
(1) Get Bootstrap class Loader: Trying to get Bootstrap class Loader, the result is necessarily null. You can verify this by using the getClassLoader method of the class object within the Rt.jar package, such as Java.lang.String.class.getClassLoader () to get or get extention class Loader, then call the GetParent method to obtain;
(2) Get extention class Loader: Use the getClassLoader method of the class object in the jar package under the Java_home/lib/ext directory or get system class Loader first. Then it is obtained by its GetParent method;
(3) Get System class Loader: Invoke the getClassLoader method of the class object containing the main function or call Thread.CurrentThread () within the main function. Getcontextclassloader () or call Classloader.getsystemclassloader ();
(4) Get user-defined class Loader: Invoke the getClassLoader method of the class object or call Thread.CurrentThread (). Getcontextclassloader ();
The operation principle of the class loader
1. Principle of Agency
2. The principle of visibility
3. Principle of uniqueness
4. Principle of Agency
The proxy principle refers to a class loader that requests its parent loader agent to load when it loads a class, and the parent loader requests its parent loader agent to load, as shown in the following illustration.
Why use proxy mode? This can be done first by reducing the repetition of loading a class. (Is there any other reason?) )
A place that is easily misunderstood:
It is generally assumed that the proxy order of the ClassLoader is parent one, which is:
1. When loading a class, the class loader first checks to see if it has loaded the class, returns if it is loaded, or the parent loader agent;
2. The parent loader repeats 1 operations until the bootstrap Class Loader;
3. If bootstrap class loader does not load the class, it attempts to load, returns if the load succeeds, and if it fails, throws the ClassNotFoundException, which is loaded by the child loader;
4. The subclass loader attempts to load after catching an exception, returns if successful, and throws classnotfoundexception if it fails until the loaded subclass loader is launched.
This understanding of the Bootstrap class Loader,extention class Loader,system class Loader These loaders is correct, but some personalized loaders are not, for example, the IBM Web Sphere Portal Some of the class loaders implemented by the server are parent last, the child loader first tries to load, and if the load fails, the parent loader is asked to do so because if you expect a version of log4j to be used by all applications, put it in the Was_home library, is loaded when it is started. If an application wants to use a different version of log4j, it is not possible to use parent one because the class within the log4j is already loaded in the parent loader. However, if you use parent last, the ClassLoader that is responsible for loading the application will first load another version of log4j.
The principle of visibility
Each class has a different visibility to the ClassLoader, as shown in the following illustration.
Extension of knowledge, OSGi is the use of this feature, each bundle by a separate classloader loaded, so each class loader can load a version of a class, so the entire system can use multiple versions of a class.
Uniqueness principle
Each class is most loaded in one loader.
Extension Knowledge 1: To be precise, the singleton pattern refers to a single instance of a class in a group of ClassLoader.
Extension Knowledge 2: A class can be loaded by multiple ClassLoader, each class object in its own namespace, comparing the class object or converting the instance to a different namespace, for example:
The Klass class is classloadera loaded, assuming that the class object is Klassa, and is classloaderb loaded, assuming that the class object is KLASSB, then Klassa is not equal to KLASSB. A ClassCastException exception is thrown when an instance of ClassA is cast into a klassb.
Why should I personalize the class loader
The Personalization class loader adds a lot of flexibility to the Java language, and the main uses are:
1. Can be loaded from a variety of places, such as the network, database, or even real-time compiled source files to obtain class files;
2. After personalization, the class loader can load a version of the class file in principle at runtime;
3. After personalization, the class loader can unload some classes dynamically;
4. After personalization, the class loader can decrypt and decompress the class before loading the class.
implicit and explicit loading of classes
implicit loading: When a class is referenced, inherited or instantiated, it is implicitly loaded, and if the load fails, it throws a noclassdeffounderror.
Explicit loading: Use the following method to throw a classnotfoundexception if the load fails.
Cl.loadclass (), CL is an example of a class loader;
Class.forName (), loaded using the class loader for the current class.
Execution of static blocks of classes
If there are the following categories:
Package cn.fengd;
public class Dummy {
static {
System.out.println ("Hi");
}
Build another test class:
Package cn.fengd;
public class Classloadertest {public
static void Main (string[] args) throws Instantiationexception, Exception {
try {
/
* * different ways of loading.
*/
Class C = ClassLoaderTest.class.getClassLoader (). LoadClass ("Cn.fengd.Dummy");
catch (Exception e) {
//TODO auto-generated catch block
e.printstacktrace ();
}
}
}
What is the effect after the operation?
- does not output hi. This shows that the class object has not been initialized after using LoadClass;
- If you add c.newinstance () after the load statement; There is a hi output that initializes the class object when the class is instantiated.
- If a different load statement Class c = class.forname ("Cn.fengd.Dummy", False, Classloader.getsystemclassloader ());
- does not output hi. Because the parameter false indicates that the class object does not need to be initialized;
- If you add c.newinstance () after the load statement; There is a hi output that initializes the class object when the class is instantiated.
If you change to Class.forName ("Cn.fengd.Dummy"), or new Dummy ()?
Will output hi.
Common problem Analysis:
1. Is the specified type or the same type loaded by different classloader?
in Java, a class is identified with its exact matching class name (fully qualified class name), where the exact matching class name includes the package name and the class name. But in the JVM, a class is uniquely identified with its full name and an instance of the loaded class ClassLoader. Classes loaded by different ClassLoader will be placed in different namespaces. We can use two custom ClassLoader to load a custom type (note, do not place the custom type's bytecode in the system path or extension path, otherwise it will be preempted by the System class loader or the extended class loader, and then use the two class instances obtained to Java . lang. Object.Equals (.....) Judgment, there will be unequal results. You can write two custom classloader to load the same custom type, then make a judgment, and you can test the load java.* type and then test the test results.
2. Directly invoke the Class.forName (String name) method in your code, which will trigger the class loader for class loading behavior?
class.forname (String name) uses the class loader that invokes the class to load the class by default. Let's analyze the corresponding JDK's code directly:
Java.lang.Class.java
publicstatic class<?> forname (String className) throws ClassNotFoundException { Return
FORNAME0 (ClassName, True, Classloader.getcallerclassloader ());
}
Java.lang.ClassLoader.java
//Returns the Invoker ' class loader, or null if none.
Static ClassLoader Getcallerclassloader () {
//Gets the type class (caller) of the calling class
caller = Reflection.getcallerclass (3);
This can are null if the VM is requesting it
if (caller = = null) {
returnnull
}
Invokes the local method in Java.lang.Class to get the ClassLoader return Caller.getclassloader0 () that loads the calling class (caller)
;
}
Java.lang.Class.java
//virtual machine local implementation, get the current class loader
native ClassLoader GetClassLoader0 ();
3. When writing the custom class loader, if the parent loader is not set, what is the parent loader?
the System class loader is used by default without specifying a parent class loader. Maybe someone doesn't understand, so let's take a look at the JDK code implementation. As we all know, we write custom ClassLoader directly or indirectly inherit from the Java.lang.ClassLoader abstract class, and the corresponding parameterless default constructor is implemented as follows:
Excerpt from Java.lang.ClassLoader.java
protected ClassLoader () {
SecurityManager security = System.getsecuritymanager ();
if (security!= null) {
security.checkcreateclassloader ();
}
This.parent = Getsystemclassloader ();
initialized = true;
}
Let's take a look at the implementation of the corresponding Getsystemclassloader () method:
Privatestaticsynchronizedvoid Initsystemclassloader () {
//...
Sun.misc.Launcher L = sun.misc.Launcher.getLauncher ();
SCL = L.getclassloader ();
//...
}
We can write a simple test code to test:
System.out.println (Sun.misc.Launcher.getLauncher (). getClassLoader ());
The corresponding output of this machine is as follows:
sun.misc.launcher$appclassloader@197d257
So, we can now believe that when the custom class loader does not specify a parent class loader, the default parent class loader is the System class loader. At the same time, we can draw the following conclusions:
The instant user custom class loader does not specify a parent class loader, so you can also load the following three-place classes:
(1) The class under <java_runtime_home>/lib
(2) < Java_runtime_home >/lib/ext or the class in the specified position by the system variable Java.ext.dir
(3) The class in the current engineering class path or at the specified position by the system variable Java.class.path
4. What is the effect of forcing the parent class loader to NULL when writing a custom class loader? If the custom class loader cannot load the specified class, will it fail to load?
The JVM specification stipulates that if a user-defined ClassLoader enforces the parent class loader to NULL, the Startup class loader is automatically set to the parent class loader of the current user-defined class loader (the problem has been analyzed before). At the same time, we can draw the following conclusions:
The instant user custom class loader does not specify the parent class loader, then it can also be loaded into a class under <java_runtime_home>/lib, but it cannot be loaded at this time <java_runtime_home>/lib/ Ext directory under the class.
Note: The inference of question 3 and question 4 is based on the user-defined ClassLoader itself, which extends the Java.lang.ClassLoader.loadClass (...). The default delegation logic, if the user changes the default delegate logic, the above inference is not necessarily true, as detailed in question 5.
5. When writing a custom class loader, what are the general points of attention?
(1) Generally try not to overwrite the existing loadclass (...). method, the delegation logic in the
This is typically done before JDK 1.2, and it turns out that doing so is most likely to cause the system's default ClassLoader to function. In the JVM specification and JDK documentation (1.2 or later), users are not advised to overwrite LoadClass (...). method, in contrast, explicitly prompts the developer to overwrite the Findclass (...) when developing a custom ClassLoader. Logic. Give an example to verify the problem:
User-defined class loader Wrongclassloader.java (overwrite loadclass logic)
publicclasswrongclassloaderextends ClassLoader {public
Class<?> loadclass (String name) throws ClassNotFoundException {
returnthis.findclass (name);
}
Protected class<?> Findclass (String name) throws ClassNotFoundException {
//Assume that this is a specific directory outside of the project d:/ Library down load class
specific implementation code omitted
}
}
We already know from the previous analysis that the user-defined class loader (Wrongclassloader) defaults
The class loader is a system class loader, but now the conclusion of the 4 kinds of problems is not tenable. Everyone can Jane
Single test, now <java_runtime_home>/lib, < java_runtime_home >/lib/ext and work
The classes on the path classpath are not loaded.
Question 5 test code one
Publicclass wrongclassloadertest {
publicstaticvoid main (string[] args) {
try {
Wrongclassloader loader = New Wrongclassloader ();
Class classloaded = Loader.loadclass ("Beans.") Account ");
System.out.println (Classloaded.getname ());
System.out.println (Classloaded.getclassloader ());
} catch (Exception e) {
e.printstacktrace ();}}}
(Note: D: "Classes" beans "account.class physical existence)
Output results:
JAVA.IO.FILENOTFOUNDEXCEPTION:D: "Classes" java "Lang" Object.class (the system cannot find the path specified.) At Java.io.FileInputStream.open (Native method) at Java.io.fileinputstream.<init> (fileinputstream.java:106) A T Wrongclassloader.findclass (wrongclassloader.java:40) at Wrongclassloader.loadclass (WrongClassLoader.java:29) at Java.lang.ClassLoader.loadClassInternal (classloader.java:319) at Java.lang.ClassLoader.defineClass1 (Native method ) at Java.lang.ClassLoader.defineClass (classloader.java:620) at Java.lang.ClassLoader.defineClass (Classloader.java :) at Wrongclassloader.findclass (wrongclassloader.java:43) at Wrongclassloader.loadclass (WrongClassLoader.java () at Wrongclassloadertest.main (wrongclassloadertest.java:27) Exception in thread "main" Java.lang.noclassdeffounderror:java/lang/object at Java.lang.ClassLoader.defineClass1 (Native method) at Java.lang.ClassLoader.defineClass (classloader.java:620) at Java.lang.ClassLoader.defineClass (Classloader.java :) at WRONGCLAssloader.findclass (wrongclassloader.java:43) at Wrongclassloader.loadclass (wrongclassloader.java:29) at
Wrongclassloadertest.main (wrongclassloadertest.java:27)
This means that the java.lang.Object of the type to be loaded is not loaded. Here enumerated due to the overwrite loadclass (... The logical errors caused are obviously simpler, and the actual logic errors may be much more complicated.
Question 5 test Two
User-defined class loader Wrongclassloader.java (loadclass logic not overridden)
publicclasswrongclassloaderextends ClassLoader {
Protected class<?> Findclass (String name) throws ClassNotFoundException {
//Assume that this is a specific directory outside of the project d:/ Library down load class
specific implementation code omitted
}
}
After you have modified the custom class loader code Wrongclassloader.java, run the test code, and the output is as follows:
Beans. Account
Wrongclassloader@1c78e57
This shows that beans. Account load succeeded and was loaded by the custom class loader Wrongclassloader.
The reason for this analysis, I think there is no need to explain, we should be able to analyze the out.
(2) correctly set the parent class loader
Through the analysis of questions 4 and 5 above, we should have understood that this is the most important point for customizing user Class Loaders, but is often overlooked or easily brought. With the previous JDK code analysis as the basis, I think now everyone can cite examples.
(3) To ensure the logical correctness of Findclass (String) method
Try to understand in advance the load task that the ClassLoader of the class loader is about to complete, ensuring that the corresponding bytecode content is obtained to the maximum extent possible.
6. How to determine at run time the System class loader can load which path under the class?
one can call Classloader.getsystemclassloader () directly or otherwise get to the System class loader (the System class loader and the extended class loader itself are derived from URLClassLoader), The Geturls () method in the call URLClassLoader can be obtained;
Second, you can view the entry information on the current classpath directly by getting the system Properties Java.class.path system.getproperty ("Java.class.path")
7. How do I determine the classes under which the standard Extension class loader can load at run time?
one of the methods:
try {
url[] Exturls = ((URLClassLoader) Classloader.getsystemclassloader (). GetParent ()). Geturls ();
for (int i = 0; i < exturls.length i++) {
System.out.println (exturls[i]);
}
catch (Exception e) {//...}
The corresponding output of this machine is as follows:
File:/d:/demo/jdk1.5.0_09/jre/lib/ext/dnsns.jar
File:/d:/demo/jdk1.5.0_09/jre/lib/ext/localedata.jar
File:/d:/demo/jdk1.5.0_09/jre/lib/ext/sunjce_provider.jar
file:/d:/demo/jdk1.5.0_09/jre/lib/ext/ Sunpkcs11.jar