This article mainly studies the relevant content of Java dynamic loading of jar and class files, as follows.
Class files loading in JAVA is dynamic. In other words, we will only load when we use it, and if we don't use it, we will not load our class.
JAVA provides us with two dynamic mechanisms. The first is the implicit mechanism. The second is the display mechanism. as follows:
Two methods:
The Class.forName() method has two forms:
public static Class forName(String className)public static Class forName(String className, boolean initialize,ClassLoader loader) Calling the forName() method with only one parameter is equivalent to Class.forName(className, true, loader).
Both methods must be connected to the native method forName0() at the end.
ForName() with three parameters, the last call is: forName0(name, initialize, loader);
Whether you are using new to instantiate a certain class, or using the Class.forName() method with only one parameter, the steps of "loading the class + running static code blocks" are implied inside.
When using the Class.forName() method with three parameters, if the second parameter is false, the class loader will only load the class and will not initialize the static code block. Only when the class is instantiated will the static code block be initialized. The static code block is initialized when the class is instantiated for the first time.
ClassLoader is used to Load Class. When a Class is loaded, all Classes referenced by this Class will also be loaded, and this loading is recursive. That is to say, if A refers to B and B refers to C, then when A is loaded, B will also be loaded, and when B is loaded, C will also be loaded. Recursive so until all required Class loads well.
package com.demo.test;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.MalformedURLException;import java.net.URL;import java.net.URLClassLoader;public class DynamicLoadDemo {enum FileType {JAR, CLASS, OTHER}static class MyClassLoader extends ClassLoader {public synchronized Class<?> loadClass(String name, File file) throws FileNotFoundException {Class<?> cls = findLoadedClass(name);if(cls != null) {return cls;}FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;try {while (true) {len = fis.read(buffer);if (len == -1) {break;}baos.write(buffer, 0, len);}//FileInputStream's flush is an empty operation, because flush is the function of writing things in the cache to the entity (hard disk or network stream). There is no need here so it is empty. //baos.flush();byte[] data = baos.toByteArray();return defineClass(null, data, 0, data.length);}catch (IOException e) {e.printStackTrace();}finally {try {baos.close();}catch (IOException e) {e.printStackTrace();}try {fis.close();}catch (IOException e) {e.printStackTrace();}}return null;}}public static void main(String[] args) {String className = "com.demo.test.HelloWorld";String paths[] = { "HelloWorld.jar", "HelloWorld.class" };for (String path : paths) {String lowerPath = path.toLowerCase();FileType fileType = FileType.OTHER;if (lowerPath.endsWith(".jar") || lowerPath.endsWith(".zip")) {fileType = FileType.JAR;} else if (lowerPath.endsWith(".class")) {fileType = FileType.CLASS;} if (fileType == FileType.OTHER) {return;}File file = new File(path);if (!file.exists()) {return;}try {URL url = file.toURI().toURL();System.out.println(url.toString());Class<?> cls = null;switch (fileType) {case JAR: URLClassLoader classLoader = new URLClassLoader(new URL[] { url }, Thread.currentThread().getContextClassLoader());cls = classLoader.loadClass(className);break;case CLASS: MyClassLoader myClassLoader = new MyClassLoader();cls = myClassLoader.loadClass(className, file);break;default: break;}if (cls == null) {return;}// Instance variable Field field = cls.getDeclaredField("hello");if (!field.isAccessible()) {field.setAccessible(true);}System.out.println(field.get(cls.newInstance()));// Call the static method without parameters Method staticMethod = cls.getDeclaredMethod("sayStaticHello", null); if (!staticMethod.isAccessible()) {staticMethod.setAccessible(true);}// If the return value of the function is void, nullstaticMethod.invoke(cls, null);// Instance Method method with parameters Method = cls.getDeclaredMethod("say", String.class);if (!method.isAccessible()) {method.setAccessible(true);}Object ret = method.invoke(cls.newInstance(), "hello world");System.out.println(ret);}catch (MalformedURLException e) {e.printStackTrace();}catch (ClassNotFoundException e) {e.printStackTrace();}catch (NoSuchMethodException e) {e.printStackTrace();}catch (SecurityException e) {e.printStackTrace();}catch (IllegalAccessException e) {e.printStackTrace();}catch (IllegalArgumentException e) {e.printStackTrace();}catch (InvocationTargetException e) {e.printStackTrace();}catch (InstantiationException e) {e.printStackTrace();}catch (NoSuchFieldException e) {e.printStackTrace();}catch (FileNotFoundException e) {e.printStackTrace();}}}}result:
The above is all the content of this article about the analysis of Java dynamic loading jar and class file instances. 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!