Class Loading ---(類裝載機制,開發人員不得不知道的故事) --下篇

來源:互聯網
上載者:User
 

如何構造使用自訂的ClassLoader

既然自訂的ClassLoader,能解決上述問題,那接下去看看,我們如何來使用自訂的ClassLoader。

結合本文種的原碼---(在differentversionspush的目錄裡),有個FileSystemClassLoader,類圖描述如下:


圖9.

 

看看他的方法 findClassBytes(String className);

    public byte[] findClassBytes(String className){

        try{
            String pathName = currentRoot +
                File.separatorChar + className.
                replace('.', File.separatorChar)
                + ".class";
            FileInputStream inFile = new
                FileInputStream(pathName);
            byte[] classBytes = new
                byte[inFile.available()];
            inFile.read(classBytes);
            return classBytes;
        }
        catch (java.io.IOException ioEx){
            return null;
        }
    }

    public Class findClass(String name)throws
        ClassNotFoundException{

        byte[] classBytes = findClassBytes(name);
        if (classBytes==null){
            throw new ClassNotFoundException();
        }
        else{
            return defineClass(name, classBytes,
                0, classBytes.length);
        }
    }

    public Class findClass(String name, byte[]
        classBytes)throws ClassNotFoundException{

        if (classBytes==null){
            throw new ClassNotFoundException(
                "(classBytes==null)");
        }
        else{
            return defineClass(name, classBytes,
                0, classBytes.length);
        }
    }

    public void execute(String codeName,
        byte[] code){

        Class klass = null;
        try{
            klass = findClass(codeName, code);
            TaskIntf task = (TaskIntf)
                klass.newInstance();
            task.execute();
        }
        catch(Exception exception){
            exception.printStackTrace();
        }
    }

這個類FileSystemClassLoader 被client使用了,用來定義class, 並且把它把client.TaskImpl(v1)轉化為 byte[], 然後 byte[]發送到RMI Server執行。(上面講了defineClass()能夠執行任何位元組碼,來自編譯後的檔案,網路甚至是BCEL 位元組碼引擎庫),   在Server端 ,又可以通過FileSystemClassLoader 以為byte[]的形式定義出 client.TaskImpl。

 

請看Client端的代碼:

public class Client{

    public static void main (String[] args){

        try{
            byte[] code = getClassDefinition
                ("client.TaskImpl");
            serverIntf.execute("client.TaskImpl",
                code);
            }
            catch(RemoteException remoteException){
                remoteException.printStackTrace();
            }
        }

    private static byte[] getClassDefinition
        (String codeName){
        String userDir = System.getProperties().
            getProperty("BytePath");
        FileSystemClassLoader fscl1 = null;

        try{
            fscl1 = new FileSystemClassLoader
                (userDir);
        }
        catch(FileNotFoundException
            fileNotFoundException){
            fileNotFoundException.printStackTrace();
        }
        return fscl1.findClassBytes(codeName);
    }
}

在RMI伺服器端ServerImpl 程式裡, 接受到來自client的位元組碼(byte[]),於是FileSystemClassLoader 會從byte[]構造出一個class, 執行個體話,並且執行。

有一點要注意:每次接收到一個client的請求,FileSystemClassLoader都會重新執行個體化(執行結果中可以看出來),這就意味著,client.Impl不在是在classpath中被找到的,而是通過FileSystemClassLoader 的findClass() 來執行deFineClass(),這樣每次 FileSystemClassLoader 都是建立新的執行個體,,自然 deFine出來的class也是不同的。 這樣,我們就能在RMI的執行中區分出 這兩個class來。(client.TaskImpl != client.TaskImp  在上篇就已經得出結論了。 )

看看伺服器端的執行代碼:

public void execute(String codeName, byte[] code)throws RemoteException{

        FileSystemClassLoader fileSystemClassLoader = null;

        try{
            fileSystemClassLoader = new FileSystemClassLoader();
            fileSystemClassLoader.execute(codeName, code);
        }
        catch(Exception exception){
            throw new RemoteException(exception.getMessage());
        }
    }

 

伺服器端的執行結果:


圖10,伺服器端顯示

下面兩圖分別是用戶端顯示的。


圖11. client1的執行顯示


圖12. client2執行結果

 

哈,上面洋洋洒洒那麼多,總算是一步一步的教會了大家 如何在同一個VM虛擬機器中,執行“不同版本”的代碼 。(這些代碼有同樣的類名和包名)。

 

Class Loaders 在 J2EE 中應用。 到這裡你其實已經不足為奇下面一些東西了。。。
      我的一個A_war.war的web項目中 代碼是 com.mycom.Test 而我在另外一個B_war.war的wenb項目中的 代碼也是com.mycom.Test 而他們照樣工作的好好的。
      當一個大型的 EJB項目,一台伺服器上部署了多個 EJB,War工程時候,他們也不會互相影響。AppServer還會有自己的裝載策略,比如你web中用的jar包,會優先於AppServer本身所帶有的。
    另外,J2EE的ClassLoader機制更詳細的能容你可以參考Tss上的這篇文章。 Understanding J2EE Application Server Class Loading Architectures

資源檔:

  • Sample code for this article
  • JDK 1.5 API Docs
  • The Java language specification
  • "Understanding Extension Class Loading " in the Java tutorial
  • "Inside Class Loaders" from ONJava
  • "Inside Class Loaders: Debugging" from ONJava
  • "What version is your Java code?" from JavaWorld
  • " Understanding J2EE Application Server Class Loading Architectures" from TheServerSide
  • Byte Code Engineering Library
  • Server-Based Java Programming by Ted Neward
  • 原文:
    http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.htm

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.