The Java default class loader is used in a typical scenario, but sometimes you have to implement your own ClassLoader for some purpose, for example, to achieve the isolation of class libraries, for example, in order to achieve the hot-deploy reload feature. You need to define the class loader yourself, and each ClassLoader loads its own class library resources to achieve the resource isolation effect. The parent delegation mechanism can be used to load the resources, or the parent delegation mechanism can be broken.
First, the use of parental delegation mechanism to customize the ClassLoader is simple, simply inherit the ClassLoader class and override the Findclass method. Here's an example:
① first defines a class to be loaded test, it is very simple, just in the build function output by which class loader loaded.
publicclass Test { publicTest(){ System.out.println(this.getClass().getClassLoader().toString()); }}
② defines a Testclassloader class to inherit ClassLoader, overriding the Findclass method, the thing to do is to read the Test.class byte stream and pass in the DefineClass method of the parent class. The test.class can then be loaded with the custom accumulator Testclassloader, and the "Testloader" will be output after the load is completed.
Public class testclassloader extends ClassLoader { PrivateString name; Public Testclassloader(ClassLoader parent, String name) {Super(parent); This. name = name; }@Override PublicStringtoString() {return This. Name; }@Override PublicClass<?>Findclass(String name) {InputStream is =NULL;byte[] data =NULL; Bytearrayoutputstream BAOs =NewBytearrayoutputstream ();Try{is =NewFileInputStream (NewFile ("D:/test.class"));intc =0; while(-1! = (c = is.read ())) {baos.write (c); } data = Baos.tobytearray (); }Catch(Exception e) {E.printstacktrace (); }finally{Try{Is.close (); Baos.close (); }Catch(IOException e) {E.printstacktrace (); } }return This. defineclass (name, data,0, data.length); } Public Static void Main(string[] args) {Testclassloader Loader =NewTestclassloader (TestClassLoader.class.getClassLoader (),"Testloader"); Class Clazz;Try{clazz = Loader.loadclass ("Test.classloader.Test"); Object object = Clazz.newinstance (); }Catch(Exception e) {E.printstacktrace (); } }}
Second, breaking the parental delegation mechanism is not only to inherit the ClassLoader class, but also to rewrite the LoadClass and Findclass methods, the following example:
① defines the test class.
publicclass Test { publicTest(){ System.out.println(this.getClass().getClassLoader().toString()); }}
② redefined a Testclassloadern class that inherits ClassLoader, which is similar to the previous Testclassloader class, but overrides the Findclass method in addition to overriding the LoadClass method. The default LoadClass method is to implement the logic of the parental delegation mechanism, which is to let the parent class loader load first, and when it fails to load, it is loaded by itself. Here, in order to break the parental delegation mechanism, the LoadClass method must be overridden, that is, the System class loader is first tried to load and the load failure is loaded by itself. It does not give precedence to the parent class loader, which breaks the parental delegation mechanism.
Public class testclassloadern extends ClassLoader { PrivateString name; Public Testclassloadern(ClassLoader parent, String name) {Super(parent); This. name = name; }@Override PublicStringtoString() {return This. Name; }@Override PublicClass<?>LoadClass(String name)throwsclassnotfoundexception {class<?> Clazz =NULL; ClassLoader system = Getsystemclassloader ();Try{clazz = System.loadclass (name); }Catch(Exception e) {//Ignore}if(Clazz! =NULL)returnClazz; Clazz = Findclass (name);returnClazz; }@Override PublicClass<?>Findclass(String name) {InputStream is =NULL;byte[] data =NULL; Bytearrayoutputstream BAOs =NewBytearrayoutputstream ();Try{is =NewFileInputStream (NewFile ("D:/test.class"));intc =0; while(-1! = (c = is.read ())) {baos.write (c); } data = Baos.tobytearray (); }Catch(Exception e) {E.printstacktrace (); }finally{Try{Is.close (); Baos.close (); }Catch(IOException e) {E.printstacktrace (); } }return This. defineclass (name, data,0, data.length); } Public Static void Main(string[] args) {Testclassloadern Loader =NewTestclassloadern (TestClassLoaderN.class.getClassLoader (),"Testloadern"); Class Clazz;Try{clazz = Loader.loadclass ("Test.classloader.Test"); Object object = Clazz.newinstance (); }Catch(Exception e) {E.printstacktrace (); } }}
class loader parental delegation and breaking parental delegation