Java custom class loader and parental delegation model

Source: Internet
Author: User

In fact, the parental delegation model is not complicated. Customizing the ClassLoader is not difficult! You can search a lot of results from the Internet and then copy you can use them. However, if you want to customize the ClassLoader every time you have to search someone else's article, and then copy, so obviously not. However, the custom class loader is not often used, it is easy to forget for a long time. I believe you often do not remember very loadClass clearly findClass , defineClass these functions should I rewrite which one? What do they mostly do? This article roughly analyzes the various functions of the flow, the purpose is to let you read after, it is hard to forget! Or, extend your memory time to the custom ClassLoader! Customize whenever you want!

1. Parental delegation Model

There is a lot of information on the internet about parental assignment models. Let me just briefly describe it as a review.

1.1 What is a parental delegation model?

First, you need to know what the ClassLoader is. Simply put, the class loader class loads the file into JVM memory and into the object, based on the specified fully qualified name Class . If you stand on JVM the point of view, there are only two kinds of loaders:

  • Launch class loader ( Bootstrap ClassLoader ): implemented by the C++ language (for HotSpot ), which is responsible for <JAVA_HOME>\lib loading the -Xbootclasspath class library into memory in the path specified by the directory or parameter.

  • Other ClassLoader: Java implemented by the language and inherited from the abstract class ClassLoader . Such as:

    • Extension class loader ( Extension ClassLoader ): Responsible for loading <JAVA_HOME>\lib\ext java.ext.dirs all class libraries in the path specified by the directory or system variable.
    • Application class loader ( Application ClassLoader ). Responsible for loading the classpath specified class library on the user classpath (), we can use this classloader directly. In general, if we do not have custom ClassLoader, the default is to use this loader.

The parent delegation model works by: If a class loader receives a request for a class load, it first does not attempt to load the class itself, but instead delegates the request to the parent class loader to complete. This is true for each classloader, and the ClassNotFoundException child loader attempts to load itself only if the parent loader cannot find the specified class (that is) within its own search scope.


Parent delegation model for Class loader 1.2 Why do I need parental delegation models?

Why do we need parents to delegate the model? Imagine a scenario where there is no parental delegation model:

A hacker customizes a java.lang.String class that String has the same functionality as a system String class, but modifies a function slightly. such as equals functions, this function is often used, if in this function, the hacker added some "virus code". And is joined by a custom class loader JVM . At this point, if there is no parental delegation model, JVM it may be mistaken that the hacker's custom java.lang.String class is the class of the system String , causing the "virus code" to be executed.

With the parental delegation model, the hacker's custom java.lang.String classes will never be loaded into memory. The java.lang.String final custom ClassLoader cannot load the class because the top class loader first loads the system's class java.lang.String .

You might think that I'm forcing a custom class inside a custom ClassLoader java.lang.String , not by calling the parent loader. Really, that's doable. However, JVM when judging whether an object is a type, it returns false if the actual type of the object differs from the class loader of the type to be compared.

To give a simple example:

ClassLoader1, ClassLoader2 all load java.lang.String classes, corresponding to Class1, Class2 objects. Then Class1 the object is not part ClassLoad2 of the object-loaded java.lang.String type.

1.3 How do I implement a parental delegation model?

The principle of parent delegation model is simple and easy to implement. Each time it is loaded by delegating the parent class loader, the parent class loader fails to load and then loads itself. In fact ClassLoader , the class default loadClass method has been written for us, we do not have to write.

2. Custom class Loader 2. 1 Several important functions 2.1.1 LoadClass

loadClassThe default implementation is as follows:

public Class<?> loadClass(String name) throws ClassNotFoundException {        return loadClass(name, false);}

Then look at the loadClass(String name, boolean resolve) function:

Protected class<?> loadclass (String name,Boolean resolve)Throws classnotfoundexception{Synchronized (Getclassloadinglock (name)) {First, check if the class has already been loaded class C = Findloadedclass (name);if (c = =NULL) {Long T0 = System.nanotime ();try {if (Parent! =NULL) {c = parent.loadclass (name,FALSE); }else {c = findbootstrapclassornull (name);}}catch (classnotfoundexception e) {//ClassNotFoundException Thrown if class not found //from the Non-null parent class loader} if (c = = null) {//if still not found, then invoke Findclass in or Der //to find the class. long t1 = System.nanotime (); c = Findclass (name); //This is the defining class loader; record the stats Sun.misc.PerfCounter.getParentDelegationTime (). Addtime (T1-T0); Sun.misc.PerfCounter.getFindClassTime (). Addelapsedtimefrom (t1); Sun.misc.PerfCounter.getFindClasses (). increment (); }} if (Resolve) {resolveclass (c);} return C;}           

As can be seen from the above code, the loadClass(String, boolean) function is the implementation of the parent delegation model! The general process is as follows:

  1. First, check to see if the class with the specified name has already been loaded, and if it is loaded, it will not need to be loaded and returned directly.
  2. If this class has not been loaded, then determine if there is a parent loader, or if there is a parent loader, it is loaded (that is, called) by the parent loader parent.loadClass(name, false); . Or it is called by the ClassLoader bootstrap to load.
  3. If both the parent loader and the bootstrap ClassLoader do not find the specified class, the method of the current ClassLoader is called findClass to complete the class load.

In other words, if you customize the ClassLoader, you must override the findClass Method!

2.1.1 Find Class

findClassThe default implementation is as follows:

protected Class<?> findClass(String name) throws ClassNotFoundException {        throw new ClassNotFoundException(name);}

As you can see, the function of an abstract class ClassLoader findClass defaults to throwing an exception. As we know earlier, loadClass when the parent loader is unable to load the class, it invokes the function in our custom ClassLoader findeClass , so we have to loadClass implement this function to convert a specified class name to an Class object.

This is good if it is a byte array to read a class of the specified name. But how do you convert a byte array to an Class object? It is simple to Java provide a defineClass method by which a byte array can be converted to a class object.

2.1.1 DefineClass

defineClassThe main functions are:

Converts a byte array to an Class object, which is the class final byte array after the file is read. For example, if the class file is encrypted, it needs to be decrypted and passed into the function as a parameter defineClass .

defineClassThe default implementation is as follows:

protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError { return defineClass(name, b, off, len, null);}
2.2 Function Call procedure

The function call procedure mentioned in the previous section is as follows:


Custom Function Call Procedure 2.3 Simple example

First, we define a generic class to load Java : Test.java . Put com.huachao.cl under the package:

package com.huachao.cl;public class Test { public void hello() { System.out.println("恩,是的,我是由 " + getClass().getClassLoader().getClass() + " 加载进来的"); }}

Attention:

If you are creating directly within the current project, Test.java please copy the files and delete them after compiling Test.class Test.java . Because if Test.class stored in the current project, according to the parent delegation model, it is loaded through the ClassLoader sun.misc.Launcher$AppClassLoader . In order for our custom class loader to load, we put the Test.class file into another directory.

In this example, our Test.class file contains the following directories:


class file Directory

The next step is to customize our ClassLoader:

Import Java.io.FileInputStream;Import Java.lang.reflect.Method;PublicClassMain {StaticClassMyclassloaderExtendsClassLoader {Private String ClassPath;PublicMyclassloader(String ClassPath) {This.classpath = ClassPath; }PrivateByte[] Loadbyte (String name)Throws Exception {name = Name.replaceall ("\\.","/"); FileInputStream FIS =New FileInputStream (ClassPath +"/" + name +". Class");int len = fis.available ();byte[] data =NewByte[len]; Fis.read (data); Fis.close ();return data; }Protected class<?> Findclass (String name)Throws ClassNotFoundException {try {byte[] data = loadbyte (name);Return defineclass (name, data,0, data.length); } catch (Exception e) {e.printstacktrace (); throw new classnotfoundexception ();}} }; public static void main (String args[]) throws Exception {myclassloader classLoader = new Myclassloader ( "d:/test"); Class clazz = Classloader.loadclass ( "com.huachao.cl.Test"); Object obj = clazz.newinstance (); Method HelloMethod = Clazz.getdeclaredmethod ( "hello", null); Hellomethod.invoke (obj, null);}         

The results of the final operation are as follows:

class Main$MyClassLoader 加载进来的

Java custom class loader and parental delegation model

Related Article

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.