在给热部署系统热加载资源时,如果不掌握对象和资源的生命周期,系统运行时很容易产生一些意想不到的错误。从Jar 加载到系统中,到被替换,不同的资源生命周期是不一样的。
首先是对象,如果一个对象没有手动的丢弃,那么它的生命周期与加载它的 ClassLoader 生命周期一样。销毁对象时,只需要确保对象的引用为 null 即可,清理游离的对象的工作由GC处理。
其次是静态资源,被加载的静态资源的生命周期与系统的生命周期一样,对象的销毁时,静态资源并不能被一起被销毁。因此,在销毁对象前,一定要将静态变量的引用对象置为null,否则,被引用的对象将不能被GC处理。
然后是 NativeLibrary, 本地库又称为动态库 DLL(Dynamic Link Library),通过Java平台提供的API——System.load(dllPath)、System.loadLibrary(libname) 加载进系统。它的生命周期和系统一样,虽然 ClassLoader 保存了对 NativeLibrary 的引用,但是ClassLoader的销毁,NativeLibrary 也不会被销毁。
因此,热部署时,销毁对象只需要对其引用置为 null 即可,而静态资源只需要把它对对象的引用给释放掉, 但是对于 NativeLibrary, Java 没有现成的 API 将其销毁。但是,可以通过反射销毁 NativeLibrary 资源。
通过 System.load() 加载的 NativeLibrary 对象被保存在被调用对象的 ClassLoader 中。