java類加載器

1,什麼是類加載器?html

        加載類的工具.java

 

2,類加載器有什麼做用?web

        當程序須要的某個類,那麼須要經過類加載器把類的二進制加載到內存中.tomcat

類加載器也是Java類服務器

 

3,類加載器之間的父子關係和管轄範圍.ide

  ClassLoader classLoader = ClassLoadTest.class.getClassLoader();
  while(classLoader != null){
   System.out.println(classLoader.getClass().getName());
   classLoader=classLoader.getParent();
  }
  System.out.println(classLoader);
 結果:
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
null

四、類加載器的委託機制工具

 1>當Java虛擬機要加載一個類時,到底派出哪一個類加載器去加載呢?測試

                    ①首先當前線程的類加載器去加載線程中的第一個類.this

                    ②若是類A中引用了類B,Java虛擬機將使用加載類A的類加載器加載類B加密

                    ③還能夠直接調用ClassLoader.loadClass()方法來指定某個類加載器去加載某個類.

         2>每一個類加載器加載類時,又先委託給其上級類加載器.

                    ①當全部祖宗類加載器沒有加載到類

,回到發起者類加載器,若是還加載不了,則拋出ClassNotFoundException異常,它不會 去找發起者類加載器的兒子,由於沒有getChild()方法,即便有,有那麼多的兒子交給那一個呢?因此幹錯就不叫給兒子處理了.               

        委託機制有什麼好處?集中管理,若是咱們寫了幾個類加載器,都去加載某個類,那麼內存中就有多份這個類的字節碼

        能不能本身寫一個類叫java.lang.System?

爲了避免讓咱們寫System類,類加載採用委託機制,這樣能夠保證爸爸優先,也就是使用的永遠是爸爸的(系統的)

System類,而不是咱們寫的System類.

 

5,編寫本身的類加載器

public static void main(String[] args) throws Exception {

        String srcPath = args[0];

        String destDir = args[1];

        FileInputStream fis = new FileInputStream(srcPath);

        String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);

        String destPath = destDir + "\\" + destFileName;

        FileOutputStream fos = new FileOutputStream(destPath);

        cypher(fis,fos);

        fis.close();

        fos.close();

    }

 

    /**

     * 加密方法,同時也是解密方法

     * @param ips

     * @param ops

     * @throws Exception

     */

    private static void cypher(InputStream ips ,OutputStream ops) throws Exception{

        int b = -1;

        while((b=ips.read())!=-1){

            ops.write(b ^ 0xff);//若是是1就變成0,若是是0就變成1

        }

    }

而後在新建一個類,經過上面的方法將新建的類的字節碼進行加密:

public class ClassLoaderAttachment extends Date { //爲何要繼承Date待會再說?

    public String toString(){

        return "hello,itcast";

    } 

}

並在工程裏新建一個文件夾,用來保存加密後的class文件.



那麼這就須要使用咱們本身的類加載器來進行解密了.

public class MyClassLoader extends ClassLoader{

 

    public static void main(String[] args) throws Exception {

        String srcPath = args[0];

        String destDir = args[1];

        FileInputStream fis = new FileInputStream(srcPath);

        String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);

        String destPath = destDir + "\\" + destFileName;

        FileOutputStream fos = new FileOutputStream(destPath);

        cypher(fis,fos);

        fis.close();

        fos.close();

    }

 

    /**

     * 加密方法,同時也是解密方法

     * @param ips

     * @param ops

     * @throws Exception

     */

    private static void cypher(InputStream ips ,OutputStream ops) throws Exception{

        int b = -1;

        while((b=ips.read())!=-1){

            ops.write(b ^ 0xff);//若是是1就變成0,若是是0就變成1

        }

    }

 

    private String classDir;

 

    @Override

    protected Class<?> findClass(String name) throws ClassNotFoundException {

        String classFileName = classDir + "\\" + name.substring(name.lastIndexOf('.')+1) + ".class";

        try {

            FileInputStream fis = new FileInputStream(classFileName);

            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            cypher(fis,bos);

            fis.close();

            System.out.println("aaa");

            byte[] bytes = bos.toByteArray();

            return defineClass(bytes, 0, bytes.length);

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

 

    public MyClassLoader(){

    }

 

    public MyClassLoader(String classDir){

        this.classDir = classDir;

    }

}

測試運行代碼:

 

        Class clazz = new MyClassLoader("myClass").loadClass("ClassLoaderAttachment");

        //此處不能在使用ClassLoaderAttachment由於一旦用了以後,

        //系統的類加載器就會去加載,致使失敗,因此該類就繼承了Date類了.

        Date date = (Date)clazz.newInstance();

        System.out.println(date);

運行結果:




6,一個類加載器的高級問題:

        咱們知道tomcat服務器,是一個大大的java程序,那麼它就必須在JVM上運行.

這個大大的java程序內部也寫了不少類加載器,它用這些類加載器去加載一些特定的類.注入servlet類.

下面咱們新建一個javaweb工程,新建一個servlet程序.

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        response.setContentType("text/html");

        PrintWriter out = response.getWriter();

        ClassLoader classload = this.getClass().getClassLoader();

        while (classload != null) {

            out.println(classload.getClass().getName()+"<br>");

            classload = classload.getParent();

        }

        out.println();

        out.close();

    }

而後配置服務器,部署應用程序,啓動tomcat服務器.在頁面訪問咱們這個servlet,在頁面打印的

結果以下圖所示:

 


這是從小到大排序的.

如今呢?我想把該servlet打成jar包,放在ExtClassLoad類加載器加載的路徑.

經過Eclipse便可完成





轉載請註明出處: http://blog.csdn.net/johnny901114/article/details/7738958

相關文章
相關標籤/搜索