JVM Class加载过程详解

tech2022-10-16  110

类加载过程

JVM会通过加载、连接、初始化3个步骤来对该类进行初始化

类加载器

类加载器可以分为4种:启动类加载器,拓展类加载器,应用类加载器,自定义类加载器

做个简单demo测试:

System.out.println(String.class.getClassLoader()); System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());//ext包下面的类 System.out.println(ClassLoaderTest1.class.getClassLoader());//本地测试类 null sun.misc.Launcher$ExtClassLoader@60e53b93 sun.misc.Launcher$AppClassLoader@18b4aac2

第一个结果输出为什么是null?

Bootstrap ClassLoader由C++实现,Java中找不到对应的类

JVM加载采用双亲委派机制,主要出于安全考虑。Loading的过程可以理解为: findInCache --> parent.loadClass --> findClass 注:父加载器不是"类加载器的加载器",也不是"类加载器的父类加载器"!!!

System.out.println(ClassLoaderTest2.class.getClassLoader()); System.out.println(ClassLoaderTest2.class.getClassLoader().getClass().getClassLoader()); System.out.println(ClassLoaderTest2.class.getClassLoader().getParent().getClass().getClassLoader()); System.out.println(ClassLoaderTest2.class.getClassLoader().getParent()); sun.misc.Launcher$AppClassLoader@18b4aac2 null null sun.misc.Launcher$ExtClassLoader@6e0be858

自定义类加载器 为什么要用自定义类加载器?

我们需要的类不一定存放在已经设置好的ClassPath下,对于自定义路径中的class类文件的加载,我们需要自己的ClassLoader有时我们可能是从网络的输入流中读取类,这就需要做一些加密和解密操作,这就需要自己实现加载类的逻辑,当然其他的特殊处理也同样适用可以定义类的实现机制,实现类的热部署

怎样写一个自定义类加载器?源码比较简单,这里不再罗列

继承ClassLoader重写findClass方法findClass方法调用defineClass方法(将byte[]类型的数据转换成Class)

具体实现如下:

public class HelloJVM { public void hello() { System.out.println("Hello JVM!"); } } public class CustomClassLoader extends ClassLoader { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] data = loadClassData(); return super.defineClass(name, data, 0, data.length); } private byte[] loadClassData() { InputStream is = null; ByteArrayOutputStream baos = null; byte[] data = null; try { is = new FileInputStream(new File("/****/HelloJVM.class")); baos = new ByteArrayOutputStream(); int b = 0; byte[] buffer = new byte[1024]; while ((b = is.read(buffer)) != -1) { baos.write(buffer, 0, b); } data = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { is.close(); baos.close(); } catch (Exception e) { e.printStackTrace(); } } return data; } public static void main(String[] args) throws Exception { CustomClassLoader classLoader = new CustomClassLoader(); Class<?> clazz = classLoader.loadClass("HelloJVM"); Object obj = clazz.newInstance(); clazz.getMethod("hello").invoke(obj); System.out.println(clazz.getClassLoader()); } }

执行结果:

最新回复(0)