If you want to use a custom class loader to load the class file, you need to inherit the java.lang.ClassLoader class.
There are several important methods for ClassLoader:
protectedClassLoader(ClassLoaderparent): Creates a new class loader using the specified parent class loader for delegate operations.
protectedfinalClass<?>defineClass(Stringname,byte[]b,intoff,intlen): Convert an array of bytes to an instance of the Class class.
protectedClass<?>findClass(Stringname): Find the class with the specified binary name.
publicClass<?>loadClass(Stringname): Load the class with the specified binary name.
protectedfinalClass<?>findLoadedClass(Stringname): If the Java virtual machine has recorded this loader as a startup loader of a class with a given binary name, the class with that binary name is returned. Otherwise, return null.
publicfinalClassLoadergetParent(): Returns the delegated parent class loader.
protectedfinalvoidresolveClass(Class<?>c): Link to the specified class.
If you want to follow the parent delegation model, then rewrite the findClass(Stringname) method; if you don't want to follow the parent delegation model, then rewrite the loadClass(Stringname) method directly.
Customize class loaders that follow parent delegation model
ParentsDelegateClassLoader.java
package com.zzj.classloader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;/** * Parents delegate class loader and override findClass(name) method* * @author Administrator * */public class ParentsDelegateClassLoader extends ClassLoader {private static final String EXT = ".class";private String path;public ParentsDelegateClassLoader() {path = this.getResource("").getPath();}public ParentsDelegateClassLoader(String path) {this.path = path;}@Override protected Class<?> findClass(String name) throws ClassNotFoundException {byte[] b = null;try {b = loadClassFile(name);}catch (IOException e) {e.printStackTrace();}return this.defineClass(name, b, 0, b.length);}private byte[] loadClassFile(String name) throws IOException {String classFile = getClassFile(name);System.out.println("The class file will be loaded soon" + classFile);ByteArrayOutputStream out = new ByteArrayOutputStream();InputStream input = new FileInputStream(classFile);int count;byte[] temp = new byte[1024];while ((count = input.read(temp))) > -1) {out.write(temp, 0, count);}out.close();input.close();return out.toByteArray();}private String getClassFile(String name) {String pathName = name.replace(".", File.separator);if (path.endsWith("/") || path.endsWith("//")) {return path + pathName + EXT;}return path + File.separator + pathName + EXT;}}Now there is a class file com/zzj/classloader/User.class under the classpath classpath and F://ClassloaderTest//bin directory. The package name is com.zzj.classloader. Use the class loader ParentsDelegateClassLoader to load the class under F://ClassloaderTest//bin.
package com.zzj.classloader;public class App {private static final String path = "F://ClassloaderTest//bin";private static final String classname = "com.zzj.classloader.User";public static void main(String[] args) throws Exception {ParentsDelegateClassLoader classLoader = new ParentsDelegateClassLoader(path);Class<?> clazz = classLoader.loadClass(classname);System.out.println(clazz);System.out.println(clazz.getClassLoader());}}Output:
class com.zzj.classloader.User sun.misc.Launcher$AppClassLoader@19821f
The loader of the User class is the system class loader AppClassLoader, not the class loader we define ourselves. In fact, it is not the class under F://ClassloaderTest//bin, but the class under classpath. This is the parent delegation model: when the ParentsDelegateClassLoader loader receives the loading request, it will first delegate to the parent class loader. If the parent class loader successfully loads, a Class object will be returned. If the load fails, the class loader that received the load request will be loaded.
Delete the User class under classpath to test run:
The class file will be loaded soon F:/ClassloaderTest/bin/com/zzj/classloader/User.class class com.zzj.classloader.User com.zzj.classloader.ParentsDelegateClassLoader@61de33
At this time, the User class loads as ParentsDelegateClassLoader.
This can be verified from the source code of ClassLoader:
public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); }The overloaded method was called:
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First determine whether the class has been loaded by the current class loader Class c = findLoadedClass(name); if (c == null) { try { if (parent != null) {// If the parent class loader exists, then delegate to the parent class to load c = parent.loadClass(name, false); } else {// If the parent class loads empty, its parent class loader is the boot class loader c = findBootstrapClass0(name); } } catch (ClassNotFoundException e) { // If the parent class loader fails to load, it will load itself and call the findClass method! c = findClass(name); } } if (resolve) { resolveClass(c); } return c; }It can be seen that if you want to destroy the parent delegation model, you can directly rewrite the loadClass(Stringname) method.
Customize class loaders that do not follow parent delegation model
NotParentsDelegateClassLoader.java
package com.zzj.classloader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;/** * Non-parents delegation class loader, override the loadClass(name) method* * @author Administrator * */public class NotParentsDelegateClassLoader extends ClassLoader {private static final String EXT = ".class";private String path;public NotParentsDelegateClassLoader() {path = this.getResource("").getPath();}public NotParentsDelegateClassLoader(String path) {this.path = path;}@Override public Class<?> loadClass(String name) throws ClassNotFoundException {byte[] b = null;try {b = loadClassFile(name);}catch (FileNotFoundException e) {System.err.println("Loader" + this.getClass().getName() + "No class file found" + name + ", delegated to the parent class loader!");// Delegated to the parent class loader return getClass().getClassLoader().loadClass(name);}catch (IOException e) {System.err.println("Loader" + this.getClass().getName() + "Loading class file" + name + "Failed, delegated to the parent class loader!");// Delegated to the parent class loader return getClass().getClassLoader().loadClass(name);}// Check whether the class has been loaded by the current class loader (only check the current class loader, not the parent class loader) Class<?> clazz = findLoadedClass(name);if (clazz != null) {System.out.println("class" + name + "loaded!");return clazz;} else {System.out.println("class" + name + "not loaded yet!");}return this.defineClass(name, b, 0, b.length);}private byte[] loadClassFile(String name) throws IOException, FileNotFoundException {String classFile = getClassFile(name);System.out.println("The class file will be loaded" + classFile);ByteArrayOutputStream out = new ByteArrayOutputStream();InputStream input = new FileInputStream(classFile);int count;byte[] temp = new byte[1024];while ((count = input.read(temp))) > -1) {out.write(temp, 0, count);}out.close();input.close();return out.toByteArray();}private String getClassFile(String name) {String pathName = name.replace(".", File.separator);if (path.endsWith("/") || path.endsWith("//")) {return path + pathName + EXT;}return path + File.separator + pathName + EXT;}}Now there is a class file com/zzj/classloader/User.class under the classpath classpath, with the package name com.zzj.classloader, and the User class is loader NotParentsDelegateClassLoader.
package com.zzj.classloader;public class App2 {private static final String className = "com.zzj.classloader.User";public static void main(String[] args) throws Exception {NotParentsDelegateClassLoader classLoader = new NotParentsDelegateClassLoader();Class<?> clazz = classLoader.loadClass(className);System.out.println(clazz);System.out.println(clazz.getClassLoader());}}Output:
The class file /E:/Myeclipse/zzjtest/WebRoot/WEB-INF/classes/com/zzj/classloader/User.class class com.zzj.classloader.User has not been loaded yet! The class file will be loaded soon/E:/Myeclipse/zzjtest/WebRoot/WEB-INF/classes/java/lang/Object.class class com.zzj.classloader.User com.zzj.classloader.NotParentsDelegateClassLoader@61de33 Loader com.zzj.classloader.NotParentsDelegateClassLoader class file java.lang.Object is not found, and will be delegated to the parent class loader!
At this time, the loader of the User class is NotParentsDelegateClassLoader, which is not delegated to the parent class first. It will only be delegated to the parent class loader if the load fails. This happens to be the opposite of the parent delegation model.
Of course, even if the load fails, it can be specified without delegating to the parent class loader, so that the class loading mechanism of more complex mesh models can be built.
Summarize
The above is all about the code example of Java custom class loader, I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!