深刻理解ClassLoader(五)—類的卸載

原文地址:http://yhjhappy234.blog.163.com/blog/static/316328322011101413730764/?suggestedreading&wumiijava

咱們知道,當一個類被加載、鏈接和初始化以後,他的生命週期就開始了,當該類的class對象再也不被引用以後,該類的生命週期也就結束了,以後,該類會被類加載器卸載!app

咱們來看如下代碼:jvm

package com.yhj.jvm.classloader.uninstall;< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />

 

import com.yhj.jvm.classloader.user_defined.MyClassLoader;

/**

 * @Described:類的卸載測試

 * @author YHJ create at 2011-10-17 下午10:15:52

 * @FileNmae com.yhj.jvm.classloader.uninstall.UninstallTest.java

 */

public class UninstallTest {

 

    /**

     * @param args

     * @throws ClassNotFoundException

     * @throws IllegalAccessException

     * @throws InstantiationException

     * @Author YHJ create at 2011-10-17 下午10:15:40

     */

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

       MyClassLoader classLoader1 = new MyClassLoader("classLoader1");

       classLoader1.setClassPath("d:/jvmTest/server/");

       Class<?> clazz = classLoader1.loadClass("TestCase1");

       @SuppressWarnings("unused")

       Object obj = clazz.newInstance();

       System.out.println("1:"+clazz.hashCode());

       obj=null;

       System.out.println("2:"+clazz.hashCode());

       classLoader1 = null;

       System.out.println("3:"+clazz.hashCode());

       clazz = null;

       System.out.println("===========");

       classLoader1 = new MyClassLoader("classLoader1");

       classLoader1.setClassPath("d:/jvmTest/server/");

       clazz = classLoader1.loadClass("TestCase1");

       System.out.println("4:"+clazz.hashCode());

    }

}

如下代碼先經過自定義類加載器classloader1加載類Testcase1,而後經過反射獲取對應的obj對象,而後逐個將對應的對象設置爲null以便於銷燬對象,執行結果是是什麼樣子的呢?測試

咱們看到,前三次打印對象的spa

hashCode是一致的,說明是一個對象,可是最後一次卻反生了變化,說明對象的地址變化了,也就是以前被卸載了(由於咱們知道,類的class對象在整個類加載過程當中只會被加載一次,只有一個實例對象,除非類被卸載了),而後又被加載了一次(加載了2次)。指針

咱們再來看這幾個類的關係,咱們把它畫成圖,以下code

棧空間變量指向堆控件的數據,已經沒什麼爭論,以前(上幾篇文章)已經討論過,loader1對象能夠經過findClass方法拿到對應的TestCase1類,所以有一個指針指向TestCase1Class實例,而TestCase1能夠經過getClassLoader的方法拿到對應的類加載器,所以有一個指針指向MyClassloader的對象,TestCase1的實例obj經過getClass方法能夠拿到對應的TestCase1實例。咱們這樣能夠看到,MyClassloader對象有2個引用指針,TestCase13個引用指針,當cloder1nullobjClassnullobjnull的時候,系統還剩下MyClassloaderTestCase1的一個相互引用。server

咱們知道,只要class引用不在有,那麼這個類就能夠回收了,指向方法區的就不看了,可是MyClassloaderTestCase1每一個還有一個引用麼人這兩個其實已經沒有其餘引用了,可是從程序結果咱們能夠看到,類已經被卸載了,說明JVM已經對這種雙向引用也作了卸載和回收操做,可是按照咱們以前的理論,只有當引用計數器爲0的時候纔會被回收,這又如何理解呢?這個咱們會在下面的文章,深刻理解JVM—垃圾回收機制作詳細介紹,敬請期待哦!xml

相關文章
相關標籤/搜索