Java ClassLoader Incomplete analysis

Source: Internet
Author: User
Tags throw exception

Although we have read about the books of the JVM, they are all understood at the conceptual level. Today specially spent a day to study the next class loader, feel is not so unfamiliar, but also just the tip of the iceberg, simply do not completely analyze it. The content is a bit long and can be accessed quickly using the catalog.

Class Loader

The three types of class loaders that are predefined by the JVM are simply a cliché. When the JVM launches a project, it uses the following three types of ClassLoader by default:
1. Boot (Bootstrap) class loader : Responsible for loading the <Java_Home>/lib following core class library or -Xbootclasspath option for the specified jar package. The loading process is implemented by the native method, and the program cannot get directly to the ClassLoader and cannot perform any operations on it.
2. extension (Extension) class loader : Implemented by the extension ClassLoader sun.misc.Launcher.ExtClassLoader . The class library that is responsible for loading <Java_Home>/lib/ext or specifying the location by system variables -Djava.ext.dir . The program can access and use the Extension class loader.
3. System class Loader : The system ClassLoader is sun.misc.Launcher.AppClassLoader implemented, and in some places it is called SystemClassLoader . is responsible for loading the -classpath -Djava.class.path class library under the directory referred to by the system classpath or variable. The program can access and use the System class loader.

Parent-Child delegation class-loading mechanism ClassLoader

Parent-child relationship of three kinds of loaders

Note that the father and son here are not inherited, they are ClassLoader implementations of abstract classes, and therefore all contain a ClassLoader parent member variable that points to its parent loader. The delegated relationship here can also be used as an agent .

Parent Delegated source Code implementation

Then let's take a look at the code, which loadClass is the ClassLoader core method of class loading in an abstract class.

protectedClass<?>LoadClass(String name,BooleanResolvethrowsclassnotfoundexception {synchronized(Getclassloadinglock (name)) {//Jobenga is loaded before, the cache is taken directly, the native method is implementedClass C = findloadedclass (name);if(c = =NULL) {Try{The parent loader is first delegated to load                    if(Parent! =NULL) {//Note here recursive callc = Parent.loadclass (name,false); }Else{//bootstrap is inaccessible, so the parent of ext must be null                    //At this time directly with the native method call startup class load load, if not found, throw exceptionc = findbootstrapclassornull (name); }                }Catch(ClassNotFoundException e) {//ClassNotFoundException not processed, only as exit recursion}if(c = =NULL) {//If the parent loader fails to load then look within the scope of this ClassLoader                    ///Findclass The class file is found, the DefineClass method is called to import the bytecode into the method area, and the results are cachedc = findclass (name); }            }//Whether parsing, default false            if(resolve)            {Resolveclass (c); }returnC }    }

It can be seen that the nature of the so-called parental assignment is the two-sentence recursive code:

ifnull) {    false);}

The load succeeds in getting the class object C, the failure throws the exception and the previous method catches and ignores with catch, and then the current class loader findClass() operation, so repeated.

Note
1. For security reasons, the bootstrap startup ClassLoader only loads classes that begin with the package named Java, javax, Sun , and so on
2. Class loading will enter the link stage , which contains validation, preparation, parsing, resolve parameters determine whether to perform the parsing phase, the JVM specification does not strictly specify the execution time of the stage
3. Because the lookup cache is used first findLoadedClass() , the same class will only be loaded once

User-defined class loader

When you write your own class implementation ClassLoader , it is the user-defined class loader. When instantiating a custom ClassLoader, the system ClassLoader () is adopted by defaultwithout specifying the parent ClassLoader (without passing the parent ClassLoader to the constructor). The corresponding parameterless default constructor is implemented as follows:

protectedClassLoader() {    this(checkCreateClassLoader(), getSystemClassLoader());}

It will call the parameter constructor and getSystemClassLoader() pass in the System class loader as the parent. So the user-defined class loader can also get the class object loaded by the 3 ClassLoader in a parent-delegated way.

When implementing a custom class loader, you should not override loadClass() it unless you do not need a parental delegation mechanism. The logic to override is the findClass() way the class is loaded.

The class object obtained using the custom class loader gets the instance through Newinstance () to compare whether two class objects with the same class fully qualified name are the same, depending on whether the same classloader loaded them , that is, calling defineClass() Instead of the class loader that was previously delegated.

Analysis of common methods java.lang.ClassMethods of the Object Class<?> forName(……)

This is a common way to load a class manually, Class with two overloads in the class:

    • public static Class<?> forName(String className)
    • public static Class<?> forName(String name, boolean initialize,
      ClassLoader loader)

There may be a question here, which class loader is used by default to load the first method? Let's take a look at the implementation:

publicstaticforName(String className)            throws ClassNotFoundException {    // 使用native方法获取调用类的Class对象    Class<?> caller = Reflection.getCallerClass();    returntrue, ClassLoader.getClassLoader(caller), caller);}

Where getClassLoader(caller) you set up the class loader you are using, continue to see its implementation:

static ClassLoader getClassLoader(Class<?> caller) {     ifnull) {         returnnull;     }     return caller.getClassLoader0(); }}

The official note for this code is the class loader that returns caller, which means that the native method getClassLoader0() returns the caller's ClassLoader. That is, assuming that the Class A is executed forName(String className) , then the ClassLoader used is to load the classloader of a.

Tips
forName0()The essence is still ClassLoader called loadClass() to load the class.

ClassLoader getClassLoader()

This method is used to get the class loader that loads a class object, but it is obtained through an instance or class object:

    • (new A()).getClass().getClassLoader()
    • A.class.getClassLoader()
A variety of methods for obtaining class information

After a class object is reflected, the class information is obtained through the following methods:

Field[] getDeclaredFields() Class[] getDeclaredClasses() Method[] getDeclaredMethods() 等等

For details, please refer to Javadoc or view source code

java.lang.ClassLoaderMethods of the Object ClassLoader getParent()

Get parent ClassLoader

Class loadClass(String)

Explicitly call this method for class loading, passing in the class fully qualified name

URL getResource(String)

Gets the resource locator with the given name. The resource can be any data, and the name must be separated by a "/" path name. The actual invocation findResource() method, the method is not implemented, requires subclass inheritance implementation.

InputStream getResourceAsStream(String)

Gets the InputStream input stream that can read the resource, which is actually called after getting to the URL using the above method url.openStream() InputStream.

ClassLoader getSystemClassLoader()

This is a static method that ClassLoader.getSystemClassLoader() can be obtained through the system ClassLoader Appclassloader, regardless of the calling class. The implementation is described in the last section.

URLClassLoader Overview

ClassLoaderis just an abstract class, many methods are empty need to implement themselves, such as findClass() , and findResource() so on. Java provides java.net.URLClassLoader this implementation class for use with a variety of application scenarios.

First of all, the AppClassLoader ExtClassLoader URLClassLoader subclass mentioned before, the custom class loader recommends inheriting it directly.

Look at the description in Javadoc:

The ClassLoader is used to load classes and resources from a set of URL paths (pointing to a jar package or directory). The Convention uses URLs that end with '/' to represent directories. If it does not end with that character, the URL is considered to point to a jar file.

constructor function

URLClassLoaderAccept an array of URLs as parameters, which will load the required classes under these provided paths, and the corresponding primary constructors have

    • public URLClassLoader(URL[] urls)
    • URLClassLoader(URL[] urls, ClassLoader parent)
getURLs()Method

Use URL[] getURLs() the method to get the URL path, reference code:

public static void main(String[] args) {    URL[] urls = ((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs();    for (URL: urls) {        System.out.println(url);    }}// file:/D:/Workbench/Test/bin/
Load mode

In, findClass() it uses classes URLClassPath in the class Loader to load class files and resources. The class URLClassPath defines the implementation of two Loader classes, respectively FileLoader JarLoader , and classes, which are used to load classes and resources in the directory, as the name implies, and the latter is the classes and resources loaded in the jar package. Loaderclass is already implemented by default getResource() , which is to load the jar package from the network URL address and then use JarLoader to complete subsequent loads, while the two implementation classes simply override the method.

You may want to ask how URLClassPath is the choice to use the right one Loader ? The answer is--it depends on the URL format. Take a look at the core code that has been cut down below, easy to understand.

PrivateLoaderGetloader(FinalUrl url) {String s = url.getfile ();//At the end of "/", if the URL protocol is "file" then use Fileloader to load the local file    //Otherwise load the network URL using the default loader    if(s! =NULL&& S.endswith ("/"))    {if("File". Equals (Url.getprotocol ()))return NewFileloader (URL);Else            return NewLoader (URL); }Else{//Non-"/" End uses Jarloader        return NewJarloader (URL, Jarhandler, lmap); }}
getSystemClassLoader()Implementation of the method

getSystemClassLoader()The traced source can be found to be essentially sun.misc.Launcher retrieving its member variables through an instance loader . So loader when did this assignment go to the value? Let's take a look at its constructor (the irrelevant content is truncated):

   Public Launcher() {Extclassloader extclassloader;Try{//Create and Initialize extension class loader ExtclassloaderExtclassloader = Extclassloader.getextclassloader (); }Catch(IOException IOException) {Throw NewInternalerror ("Could not create extension class loader"); }Try{//Create and initialize the system ClassLoader Appclassloader and assign to loaderLoader = Appclassloader.getappclassloader (Extclassloader); }Catch(IOException Ioexception1) {Throw NewInternalerror ("Could not create application class loader"); }//The thread context ClassLoader is set to Appclassloader by default      //related information see another blog postThread.CurrentThread (). Setcontextclassloader (loader); }

You can see Launcher that the initialization was created ExtClassLoader and the AppClassLoader thread context class loader is set AppClassLoader to the default settings . Although I did not see the source of the JVM, I speculated that the JVM might have created Launcher the extensions and the system ClassLoader by creating an instance, and the launch (Bootstrap) class loader was created by calling the local method.

Obviously, the getSystemClassLoader() return of the loader is AppClassLoader correct, here we also found the thread context class loader assignment, specifically about the thread context class loader learning please refer to another blog post.

Summarize

There are not many scenarios where you can write your own classloader, but the above analysis of the ClassLoader will at least give you an idea of the underlying implementation mechanism of the JVM and how you are familiar with the implementation of reflection. My personal style is to know the reason why, in my understanding of the scope of knowledge I am interested to study. Before always spend a whole period of time to chew on the difficulty after the ignored, after work to develop this often note the habit, his summary after the comb is indeed better than to look at other people's article to come deeper and more thorough, hope to keep!

Java ClassLoader Incomplete analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.