java类的动态加载
java动态加载的机制:
ClassLoader->SecureClassloader–>URLClassLoader–>AppClassLoader
loadClass–>findClass(重写方法)–>defineClass(从字节码加载类)
初始化的时候会加载静态代码块
实例化的时候会加载构造代码块、无参构造函数
1、URLClassLoader动态加载任意类
测试静态类
package loadClass;
import java.io.IOException;
public class test {
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试动态加载:
package loadClass;
import com.sun.jndi.toolkit.url.UrlUtil;
import serializes.Person;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class loadclass_test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, MalformedURLException {
//file协议加载
//URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {new URL("file:///C:\\temp\\")}); //文件所在目录
//http协议加载
//URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {new URL("http://127.0.0.1:888/")});
//jar协议
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {new URL("jar:file:///C:\\temp\\test.jar!/")});
Class<?> loadClass = urlClassLoader.loadClass("loadClass.test"); //全名:包名+类名
loadClass.newInstance();
}
}
执行完成截图:
2、defineClass 动态加载任意类
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); //获取系统的类加载器(classloader)
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
byte[] path = Files.readAllBytes(Paths.get("C:\\temp\\test.class"));
Class test = (Class)defineClass.invoke(systemClassLoader, "loadClass.test", path, 0, path.length);
test.newInstance();
3、Unsave动态加载任意类:
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
Class c = Unsafe.class;
Field theUnsafe = c.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe)theUnsafe.get(null);
byte[] path = Files.readAllBytes(Paths.get("C:\\temp\\test.class"));
Class<?> test1 = unsafe.defineClass("loadClass.test", path, 0, path.length, systemClassLoader, null);
test1.newInstance();
编译方法:
javac test.java————>test.class
test.class——>test.jar
打包成jar包:jar cvf 要生成的jar文件名 类名