Java class Loader is a cliché of the problem, most of the Java engineers are also on the knowledge point recite, recently in the source of the time to find some details of the local understanding or relatively vague, just write an article comb.
About the Java class loader knowledge, a search on the Internet a large, I have read a lot of documents, blogs. Although a lot of information, but still hope that through this article as far as possible to write some of their own understanding, their own things. If you just repeat what others have written, you lose the meaning of writing.
Class loader structure
Name Explanation:
- The root class loader, also known as the Boot class loader, starts the ClassLoader. Because it does not belong to the Java class Library, here does not say its corresponding class name, many people like to call Bootstrapclassloader. This article is called the root class loader.
Load path: <java_home>\lib
- Extension class loader, corresponding to the Java class named Extclassloader, which is an inner class of sun.misc.Launcher.
Load path: <java_home>\lib\ext
- Apply the ClassLoader, corresponding to the Java class named Appclassloader, which is an inner class of sun.misc.Launcher.
Load path: User Directory
The load path can be printed in this way System.out.println ("Boot:" +system.getproperty ("Sun.boot.class.path")); SYSTEM.OUT.PRINTLN ("Ext:" +system.getproperty ("Java.ext.dirs")); System.out.println ("app:" +system.getproperty ("Java.class.path"));
Key notes:
- The root ClassLoader can be understood as a conceptual thing for ordinary Java engineers because we cannot get to the root ClassLoader through Java code, which is at the JVM level.
- In addition to the root ClassLoader, the other two extension class loaders and application ClassLoader are initialized through the class Sun.misc.Launcher, while the Launcher class is loaded by the root class loader.
Look at the launcher initialize the source code:
public Launcher() { Launcher.ExtClassLoader var1; try { //初始化扩展类加载器,注意这里构造函数没有入参,即无法获取根类加载器 var1 = Launcher.ExtClassLoader.getExtClassLoader(); } catch (IOException var10) { throw new InternalError("Could not create extension class loader", var10); } try { //初始化应用类加载器,注意这里的入参就是扩展类加载器 this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); } catch (IOException var9) { throw new InternalError("Could not create application class loader", var9); } //设置上下文类加载器,这个后面会详细说 Thread.currentThread().setContextClassLoader(this.loader); //删除了一些安全方面的代码 //...}
Parental delegation Model
The parent delegation model is when we call the class loader's LoadClass method to load the class, and the ClassLoader first requests that it be loaded by its parents classloader, recursively. If all the parent ClassLoader fails to load, the current ClassLoader is loading itself.
Logic is very simple, through the ClassLoader class of source code to analyze.
Protected class<?> loadclass (String name, Boolean resolve) throws ClassNotFoundException {//Class load operation The first thing to do is to lock, avoid concurrent loading synchronized (Getclassloadinglock (name)) {///first determine if the specified class has been loaded class<?> C = Findloadedclass (name); if (c = = null) {Long T0 = System.nanotime (); try {if (parent! = NULL) {//If the current class is not loaded and the parent ClassLoader is not NULL, request the parent ClassLoader to load the operation c = Parent.loadclass (name, false); } else {///If the current class is not loaded and the parent ClassLoader is null, request the root ClassLoader for load operation C = Findbootstrapclassornull ( name); }} catch (ClassNotFoundException e) {} if (c = = null) { Long T1 = System.nanotime (); If the parent loader fails to load, it is loaded by the current class loader, c = findclass (name); Perform some statistical operations SUN.MISC.PERFCOUNTER.GEtparentdelegationtime (). Addtime (T1-T0); Sun.misc.PerfCounter.getFindClassTime (). Addelapsedtimefrom (t1); Sun.misc.PerfCounter.getFindClasses (). increment (); }}//Initialize the class if (resolve) {resolveclass (c); } return C; } }
The implementation logic of parental delegation model is still very simple and clear.
Here are a few details to explain:
- The ClassLoader class is an abstract class, but it does not contain any abstract methods.
- If you want to implement your own ClassLoader without destroying the parent delegation model, simply inherit the ClassLoader class and override the Findclass method.
- If you want to implement your own class loader and break the parental delegation model, you need to inherit the ClassLoader class and override the Loadclass,findclass method.
The confusing system ClassLoader
When you have the above knowledge, you will find that there is a method in the ClassLoader class is Getsystemclassloader, System ClassLoader, what is this?
The system ClassLoader is a confusing concept, and I used to think that it was the application of the class loader alias, just like starting the ClassLoader and the root ClassLoader. In fact, by default, the System class loader we get through Classloader.getsystemclassloader () is also really the application ClassLoader .
A lot of information in the class loader structure when the Application class loader is said to be the System class loader, in fact, we can judge by the class name two is not one thing.
The System class loader can be customized by System.setproperty ("Java.system.class.loader", XXX class name).
The system ClassLoader is not a completely new loader, it is just a concept, essentially the four class loaders mentioned above (the user-defined ClassLoader), as to the reason for this concept and the use of the scene, still need to continue to study.
The context class loader that is ignored
The loading paths for each classloader are discussed above. In view of the design of the parent delegation model, the subclass loader retains a reference to the superclass loader, meaning that when a class loaded by the child ClassLoader needs access to a class loaded by the parent ClassLoader, there is no doubt that it can be accessed. But considering a scenario, would there be a case where the class loaded by the parent ClassLoader would need access to the class loaded by the subclass loader ? If so, how to fix it (the parent ClassLoader does not have a reference to the subclass loader)?
This is the context class loader that we are talking about that is often overlooked.
Classic case:
JDBC is a standard interface for Java-based access to a database, which is contained in the Java base Class library, meaning it is loaded by the root ClassLoader. At the same time, each database vendor will implement this interface to enable Java engineers to access their own database, and this part of the implementation of the class library is required by the Java Engineer in the project as a third-party dependency introduced in use, that is, this part of the implementation of the class library is loaded by the Application class loader.
First, Java gets the code for the MySQL connection:
Load driver Class.forName ("Com.mysql.jdbc.Driver");//Connect database Connection conn = drivermanager.getconnection (URL, user, password);
Here the DriverManager class belongs to the Java base Class library, which is loaded by the root ClassLoader. We can get a connection to the database through it, it is obvious that it was successfully connected to the database through the Com.mysql.jdbc.Driver driver, which also said that the database driver (introduced as a third-party class library) was loaded by the application ClassLoader. This scenario is typical of classes loaded by the parent classloader that need access to classes loaded by the ClassLoader.
How does Java implement this kind of reverse access? Directly look at the source code of DriverManager class:
The method of establishing database connection parameters all the way to the end. private static Connection getconnection (String url, java.util.Properties info, class< ?> caller) throws SQLException {//Gets the class loader of the caller ClassLoader CALLERCL = caller! = null? caller.getclassload ER (): null; Synchronized (Drivermanager.class) {///If NULL, the context class loader is used//This is the focus, when will the ClassLoader be null? The class loaded by the root ClassLoader, of course. if (CALLERCL = = null) {CALLERCL = Thread.CurrentThread (). Getcontextclassloader (); } } //... Omit for (Driverinfo adriver:registereddrivers) {//Use the context class loader to load the driver if (isdriverallowed (adriver. Driver, CALLERCL) {try {//If the load succeeds, the connection is Connection con = adriver.dr Iver.connect (URL, info); //... } catch (SQLException ex) {if (reason = = null) {reason = ex; } } } //... } }
Key notes:
Why can the context ClassLoader be loaded into the database driver? Back to the beginning of the Launcher initialization class loader source code, we found that the original so-called Context class loader is essentially application class loader, there is no enlightened feeling? the context ClassLoader is just a concept to solve the reverse access of classes, not a completely new class loader, which is essentially the application ClassLoader .
Basically I understand that Java ClassLoader is so much knowledge, if there is no mention or the wrong place, welcome to communicate.
Java Learning Exchange QQ Group: 523047986 prohibit small talk, non-happy do not enter!
Read the Java class loader in an article