Java虚拟机类型卸载和类型更新解析 - 编程入门网
状态)15 System.out.println(Main.class.getClassLoader().getParent());16 } catch (Exception e) {17 e.printStackTrace();18 }19 }20 }
我们增加虚拟机参数-verbose:gc来观察垃圾收集的情况,对应输出如下:
关于启动类加载器我们就不需再做相关的测试了,jvm规范和JLS中已经有明确的说明了. 【类型卸载总结】 通过以上的相关测试(虽然测试的场景较为简单)我们可以大致这样概括: 1、有启动类加载器加载的类型在整个运行期间是不可能被卸载的(jvm和jls规范). 2、被系统类加载器和标准扩展类加载器加载的类型在运行期间不太可能被卸载,因为系统类加载器实例或者标准扩展类的实例基本上在整个运行期间总能直接或者间接的访问的到,其达到unreachable的可能性极小.(当然,在虚拟机快退出的时候可以,因为不管ClassLoader实例或者Class(java.lang.Class)实例也都是在堆中存在,同样遵循垃圾收集的规则). 3、被开发者自定义的类加载器实例加载的类型只有在很简单的上下文环境中才能被卸载,而且一般还要借助于强制调用虚拟机的垃圾收集功能才可以做到.可以预想,稍微复杂点的应用场景中(尤其很多时候,用户在开发自定义类加载器实例的时候采用缓存的策略以提高系统性能),被加载的类型在运行期间也是几乎不太可能被卸载的(至少卸载的时间是不确定的). 综合以上三点,我们可以默认前面的结论1,一个已经加载的类型被卸载的几率很小至少被卸载的时间是不确定的.同时,我们可以看的出来,开发者在开发代码时候,不应该对虚拟机的类型卸载做任何假设的前提下来实现系统中的特定功能. 【类型更新进一步分析】 前面已经明确说过,被一个特定类加载器实例加载的特定类型在运行时是无法被更新的.注意这里说的 是一个特定的类加载器实例,而非一个特定的类加载器类型. Java虚拟机类型卸载和类型更新解析(4)时间:2011-01-03 zhuxing【测试场景四】 说明:现在要删除前面已经放在工程输出目录下和扩展目录下的对应的MyClass类型对应的字节码 1 public class Main { 2 public static void main(String[] args) { 3 try { 4 MyURLClassLoader classLoader = new MyURLClassLoader(); 5 Class classLoaded1 = classLoader.loadClass("MyClass"); 6 Class classLoaded2 = classLoader.loadClass("MyClass"); 7 //判断两次加载classloader实例是否相同 8 System.out.println(classLoaded1.getClassLoader() == classLoaded2.getClassLoader()); 910 //判断两个Class实例是否相同11 System.out.println(classLoaded1 == classLoaded2);12 } catch (Exception e) {13 e.printStackTrace();14 }15 }16 } 输出如下: true true 通过结果我们可以看出来,两次加载获取到的两个Class类型实例是相同的.那是不是确实是我们的自定义 类加载器真正意义上加载了两次呢(即从获取class字节码到定义class类型…整个过程呢)? 通过对java.lang.ClassLoader的loadClass(String name,boolean resolve)方法进行调试,我们可以看出来,第二 次 加载并不是真正意义上的加载,而是直接返回了上次加载的结果. 说明:为了调试方便,在Class classLoaded2 = classLoader.loadClass("MyClass");行设置断点,然后单步跳入,可以看到第二次加载请求返回的结果直接是上次加载的Class实例. 调试过程中的截图, |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |