7.3卸载类型

7.3卸载类型

在很多方面,虚拟机中类的生命周期和对象的生命周期很相似。虚拟机创建并初始化对象,使程序能使用对象,然后在对象变得不再被引用后可选地执行垃圾收集。同样,虚拟机装 载、连接并初始化类,使程序能使用类,当程序不在引用它们的时候可选地卸载它们。

类的垃圾收集和卸载之所以在Java虚拟机中很重要,是因为Java稈序可以在运行时通过用户 自定义的类装载器装载类型来动态地扩展程序。所有被装载的类型都在方法区占据内存空间。 如果Java程序持续通过用户自定义的类装载器装载类型,方法区的内存足迹就会不断增长。如果 某些动态装载的类型只是临时需要,当它们不再被引用之后,占据的内存空间可以通过卸载类 型而释放。

Java虚拟机通过何种方法来确定一个动态装载的类型是否仍然被程序需要呢,其判断方式与判断对象是否仍然被程序需要的方式很类似。如果程序不再引用某类型,那么这个类型就无法再对未来的计算过程产生影响。类型变成不可触及的,而且可以被垃圾收集。

使用启动类装载器装载的类型永远是可触及的,所以永远不会被卸载。只有使用用户定义 的类装载器装载的类型才会变成不可触及的,从而被虚拟机回收。如果某个类型的Class实例被 发现无法通过正常的垃圾收集堆触及,那么这个类型就是不可触及的。

判断动态装载的类型的Class实例在正常的垃圾收集过程中是否可以触及有两种方式。第一 种,也是最明显的,如果程序保持对Class实例的明确引用,它就是可触及的。其次,如果在堆中还存在一个可触及的对象,在方法区中它的类型数据指向一个Class实例,那么这个Class实例 就是可触及的。在第5章讲过,仅仅给出一个对象的引用,实现必须能够在方法区中找到对象的类的类型数据。因此,从类型数据,Java虚拟机必须能够确定对象的类、它的所有超类以及所有 超接口的Class实例。图7-2是关于这种“触及” Class实例的图形化描述。

图7-2显示了垃圾收集器必须从可触及的MyThread类的对象,通过它在方法区中的类型数据 找到可触及的Class实例。在该图中,堆中的对象显示为圆圈;在方法区中的类型数据显示为灰 色的四边形。MyThread类有如下的声明:

也就是说,仅仅给出一个可触及的类MyThread的实例,垃圾收集器可以“触及” 和它所有超类型(包括Cloncable、Thread、Runnable和Object)的Class实例。

第8章的最后给出了一个动态装载的类变得无法触及从而被卸载的例子。

原文地址:https://www.cnblogs.com/mongotea/p/11979552.html