Application scenarios of custom class loaders
-
Encryption: If you don’t want your code to be decompiled. (After the class is encrypted, it cannot be loaded by ClassLoader. In this case, you need to define a custom ClassLoader to decrypt the class before loading it.)
-
Load code from nonstandard sources: If your bytecode is stored in a database or even in the cloud, you need to customize a classloader to load classes from a specified source.
Parents delegate
- So let’s take a look
ClassLoader
Class is the defaultloadClass
Method implementation
protected synchronized Class<? > loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { 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 } if (c == null) {// if still not found, Then invoke findClass in order to find the class c = findClass(name); ResolveClass (c); resolveClass(c); } return c; }Copy the code
The parent delegate model works as follows: (1) The class loader queries whether the class has been loaded from the loaded class, and returns it directly if it has been loaded. C = parent.loadClass(name, false). The parent class will use the same strategy to check whether the class is included in the loaded class. If not, the parent class will delegate to the parent class, and so on until the class is loaded. (3) If the startup class loader fails to load (for example, the class cannot be found in $JAVA_HOME/jre/lib), the extension class loader will be used to try to load the class. If the failure continues, the AppClassLoader will be used to load the class. Continued failure throws an exception ClassNotFoundException, which is then loaded by calling the findClass() method of the current loader.
Advantages of parental delegation: (1) Avoid having your own classes dynamically replace Java’s core classes, such as String. (2) It avoids double loading of classes, because the WAY the JVM distinguishes classes is not just based on class names; the same class file loaded by different classloaders produces two different classes.
Topic: Custom class loaders
If the load fails, the findClass method of the current loader will be loaded. Therefore, our custom classLoader only needs to inherit the classLoader and override the findClass method.
- Prepare a
class
The file is compiled and stored in the root directory of drive D
public class People { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }}Copy the code
- Custom class loaders
MyClassLoader
, inheritanceClassLoader
coverfindClass
Methods (wheredefineClass
The binary stream () method converts a file of binary stream bytes into onejava.lang.Class
)
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; public class MyClassLoader extends ClassLoader { public MyClassLoader(){} public MyClassLoader(ClassLoader parent) { super(parent); } protected Class<? > findClass(String name) throws ClassNotFoundException { File file = new File("D:/People.class"); try{ byte[] bytes = getClassBytes(file); // the defineClass method converts a binary stream of bytes into a java.lang.Class Class<? > c = this.defineClass(name, bytes, 0, bytes.length); return c; } catch (Exception e) { e.printStackTrace(); } return super.findClass(name); } private byte[] getClassBytes(File File) throws Exception {// To read. Class bytes, FileInputStream fis = new FileInputStream(file); FileChannel fc = fis.getChannel(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); WritableByteChannel wbc = Channels.newChannel(baos); ByteBuffer by = ByteBuffer.allocate(1024); while (true){ int i = fc.read(by); if (i == 0 || i == -1) break; by.flip(); wbc.write(by); by.clear(); } fis.close(); return baos.toByteArray(); }}Copy the code
- Test it in the main function
MyClassLoader mcl = new MyClassLoader(); Class<? > clazz = Class.forName("People", true, mcl); Object obj = clazz.newInstance(); System.out.println(obj); Println (obj.getClass().getClassLoader())); // Print out our custom classloader system.out.println (obj.getClass().getClassloader ());Copy the code
Refer to the link: www.cnblogs.com/gdpuzxs/p/7… Blog.csdn.net/seu_calvin/…