类加载的控制逻辑(loadClass): ——> java.lang.ClassLoader#loadClass
findLoadedClass // 检查是否已经被加载
loadClass // 使用parent class loader进行加载
findClass // 进行自定义的路径加载
resolveClass // 根据入参true或者false,进行动态链接。
线程默认类加载器:
AppClassLoader ——> 继承URLClassLoader
双亲委派模式:AppClassLoader ——> ExtClassLoader ——> bootClassLoader
AppClassLoader的类层次结构:
ClassLoader
SecureClassLoader
URLClassLoader
AppClassLoader
类加载的关键方法:
loadClass // 定义加载的控制逻辑
findClass // 定义寻找的控制逻辑
defineClass // 将二进制数据转换成一个class对象
自定义类加载器举例:spring-boot-devtools#RestartClassLoader
重写findClass、loadClass
重写getResources、getResource、findResource
反序列化 VS 类加载:
(1) 类加载:二进制到class——> java.lang.ClassLoader#defineClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/* 将一个ByteBuffer转换成一个class */ protected final Class<?> defineClass(String name, java.nio.ByteBuffer b, ProtectionDomain protectionDomain) throws ClassFormatError { int len = b.remaining(); // Use byte[] if not a direct ByteBufer: if (!b.isDirect()) { if (b.hasArray()) { return defineClass(name, b.array(), b.position() + b.arrayOffset(), len, protectionDomain); } else { // no array, or read-only array byte[] tb = new byte[len]; b.get(tb); // get bytes out of byte buffer. return defineClass(name, tb, 0, len, protectionDomain); } } protectionDomain = preDefineClass(name, protectionDomain); String source = defineClassSourceLocation(protectionDomain); // native 方法 Class<?> c = defineClass2(name, b, b.position(), len, protectionDomain, source); postDefineClass(c, protectionDomain); return c; }
(2) 反序列化:类加载 + 实例化。
默认类加载器 ——> java.io.ObjectInputStream#resolveClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { // latestUserDefinedLoader() == AppClassLoader return Class.forName(name, false, latestUserDefinedLoader()); } catch (ClassNotFoundException ex) { Class<?> cl = primClasses.get(name); if (cl != null) { return cl; } else { throw ex; } } }
配置自定义类加载器 ——> org.springframework.core#ConfigurableObjectInputStream
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
protected Class<?> resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { try { if (this.classLoader != null) { // Use the specified ClassLoader to resolve local classes. return ClassUtils.forName(classDesc.getName(), this.classLoader); } else { // Use the default ClassLoader... return super.resolveClass(classDesc); } } catch (ClassNotFoundException ex) { return resolveFallbackIfPossible(classDesc.getName(), ex); } }
近期评论