[JVM-6] classloader

definition

As mentioned loading stage allows designers to a controlled height of the module, as the source of the class files can be varied, code generation, reflection generated either from the network and the like. Therefore, the class loader as the processing of these documents is particularly important.

But the class loader function Not only that, it also has an important feature is the fully qualified name of a class and uniquely identify a class. Popular, say two classes are the same, not only for its fully qualified name as its corresponding class loader must also be the same, in order to explain the two classes are equal.

Because of the functional role of class loader so important that its implementation of the virtual machine specification also very seriously. In the Java virtual machine, its implementation model is the parent delegation model .

model

Parent delegation model

Parents delegated to perform primarily process model diagram shown above, which is divided into boot class loader (Bootstrap Class-loader), to expand the class loader (Extension Class-loader), an application class loader (Application Class-loader).

Wherein initiating class loader is responsible for loading the JRE core libraries, such as rt.jar under JRE directory. But in fact, according to "insider-depth analysis of Java Web technologies," said, start class loader delegation model is not strictly in line with the parents, because the Bootstrap Class-loader does not belong to the class hierarchy levels JVM. Bootstrap Class-loader is not a subclass, Extension Class-loader is not the parent class. But here we do not get to the bottom, just know that on it.

Extension Class-loader is mainly responsible for loading the JRE expand ext directory under the category.

Application Class-loader is mainly responsible for the user class path under the category (Class-path), the class loader is used the most, because the great majority of cases, usually the developer does not implement class loader customized, so the JVM this class will be used to load most of the class.

Implementation process

Parents delegate execution model

The figure is the parent delegate execution model, the time when class begins loading, first check has already been loaded before, if not loaded before, load the parent class method is invoked, if the parent fails to load, throws an exception, calls itself findClass () method to load.

JDK source code in the loading process analysis:

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 { // 无父亲就调用 bootstarp 加载器来加载 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } // 父加载器和 bootstarp 加载器都没有找到指定类,调用当前类的 findClass() 来完成类加载 // 因此,自定义类加载器,就是重写 findClass() 方法 if (c == null) { // If still not found, then invoke findClass in order // 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; } }

From the source code, we can see that in fact meet the regulatory requirements of the  parent delegation model  of. And when we want to customize a class loader time is achieved by rewriting findClass ().

Custom class loader

/**
 * 1. 自定义类加载器通过集成ClassLoader来实现,主要通过重写findClass方法
 * 2. findClass方法首先通过自定义的loadByte()方法将Class文件转换成byte[]字节流
 * 3. 然后通过defineClass()方法将其转换为Class对象
 */
public class SelfClassLoader extends ClassLoader { private String classPath; public SelfClassLoader(String classPath) { this.classPath = classPath; } /** * 通过 difineClass,将一个字节数组转换为Class 对象 * @param name * @return * @throws ClassNotFoundException */ @Override 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(); } } /** * 根据路径将指定的文件读取为byte 流 * @param name * @return * @throws IOException */ private byte[] loadByte(String name) throws IOException { name = name.replaceAll("\\.", "/"); FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class"); int len = fis.available(); byte[] data = new byte[len]; fis.read(data); fis.close(); return data; } }

Another class of implementations custom method loader:

/**
 * 1. 加载指定packageName下的类
 * 2. 用自定义类加载器进行加载,如果加载失败,再交给父加载器进行加载
 */
public class UrlSelfClassloader extends URLClassLoader { private String packageName = ""; public UrlSelfClassloader(URL[] urls, ClassLoader parent) { super(urls, parent); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> aClass = findLoadedClass(name); if (Objects.nonNull(aClass)){ return aClass; } if (!packageName.startsWith(name)){ return super.loadClass(name); }else { return findClass(name); } } }

How to use a custom class loader

public static void main(String args[]) throws Exception { MyClassLoader classLoader = new MyClassLoader(""); Class clazz = classLoader.loadClass(""); Object obj = clazz.newInstance(); Method helloMethod = clazz.getDeclaredMethod("hello", null); helloMethod.invoke(obj, null); }


Guess you like

Origin www.cnblogs.com/Joy-Hu/p/11102547.html