Java-class loading

How does Compile Once, Run Anywhere work?

Insert picture description here

How JVM loads .class files

Java Virtual Machine

Insert picture description here
Class Loader: Load class files into memory according to a specific format.
Runtime Data Area: JVM memory structure model
Execution Engine: Parse commands
Native Interface: Native libraries that integrate different development languages ​​are used by Java

reflection

The Java reflection mechanism is in the running state, for any class, you can know all the properties and methods of this class; for any object, you can call any of its methods and properties] Kinds of methods to dynamically obtain information and dynamically call objects The function is called the reflection mechanism of the java language.

package reflect;

public class Robot {
    
    
    private String name;

    public void sayHi(String helloSentence) {
    
    
        System.out.println(helloSentence + " " + name);
    }

    private String throwHello(String tag) {
    
    
        return "Hello " + tag;
    }


}

package reflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectSample {
    
    
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
    
    
        Class clazz=Class.forName("reflect.Robot");
        Robot robot= (Robot) clazz.newInstance();
        System.out.println("Class name is "+clazz.getName());
        //私有方法调用
        //获取类中声明的方法
        Method getHello=clazz.getDeclaredMethod("throwHello", String.class);
        getHello.setAccessible(true);
        Object str=getHello.invoke(robot,"Tom");
        System.out.println("getHello result is"+str);

        //获取所有公共的方法
        Method sayHi=clazz.getMethod("sayHi", String.class);
        sayHi.invoke(robot,"Welcome");

        //获取声明的属性
        Field name=clazz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(robot,"Alice");
        sayHi.invoke(robot,"Welcome");
    }
}

The process of class from compilation to execution

  • The compiler compiles Robot.java source files into Robot.class bytecode objects
  • ClassLoader converts bytecode into JVM Class objects
  • JVM uses Class object to instantiate Robot object

ClassLoader

ClassLoader plays a very important role in Java. It mainly works in the Class loading stage. Its main function is to obtain Class binary data streams from outside the system. It is the core component of Java. All Classes are loaded by ClassLoader. ClassLoader Responsible for loading the binary data stream in the Class file into the system, and then handing it over to the Java virtual machine for connection, initialization and other operations.

Types of ClassLoader

BootStrapClassLoader: written in C++, loading the core library java.*
ExtClassLoader: written in Java, loading the extended library javax.*
AppClassLoader: written in Java, the directory where the loader is located.
Custom ClassLoader: written in Java, customized loading

Implementation of custom ClassLoader

The key function
findClass
defineClass

Define a class outside the project and compile it into a class file using javac

public class Wali {
    
    
	static{
    
    
		System.out.println("Hello, Wali!");
	}
}

Custom class loader

package customclassloader;

import java.io.*;

//自定义类加载器
public class MyClassLoader extends ClassLoader {
    
    
    private String path;
    private String classLoaderName;

    public MyClassLoader(String path, String classLoaderName) {
    
    
        this.path = path;
        this.classLoaderName = classLoaderName;
    }

    //用于寻找类文件
    @Override
    public Class findClass(String name) {
    
    
        byte[] b = loadClassData(name);
        return defineClass(name, b, 0, b.length);
    }

    //用于加载类文件
    private byte[] loadClassData(String name) {
    
    
        name = path + name + ".class";
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
    
    
            in = new FileInputStream(new File(name));
            out = new ByteArrayOutputStream();
            int i = 0;
            while ((i = in.read()) != -1) {
    
    
                out.write(i);
            }

        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                out.close();
                in.close();
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
        return  out.toByteArray();
    }
}

Write test class

package customclassloader;

public class ClassLoaderChecker {
    
    
    public static void main(String[] args) throws Exception {
    
    
        MyClassLoader m=new MyClassLoader("D:\\MyData\\","myClassLoader");
        Class c=m.loadClass("Wali");
        System.out.println(c.getClassLoader());
        c.newInstance();//触发静态代码块
    }
}

Parent delegation mechanism of class loader

Insert picture description here

  1. Check whether the class is loaded from bottom to top
  2. Try to load the class from top to bottom

Why use the parent delegation mechanism to load classes

  • Avoid loading multiple copies of the same bytecode

How the class is loaded

  • Implicit loading: new
  • Explicit loading: loadClass, forName

The difference between loadClass and forName

  • The class obtained by Class.forName has been initialized
  • The class obtained by Classloder.loadClass is not yet linked.

Guess you like

Origin blog.csdn.net/yasuofenglei/article/details/104218137