2017-01-31 27 views
-1

我有nio通道,我的客戶端應該從服務器計算機加載類文件。他們在相同的知識產權範圍內。我有兩個在服務器和客戶端機器上常見的接口。以及一個在服務器機器上實現接口的類。我在客戶機上使用下面的代碼,但是當我運行它時會出現ClassNotFoundException異常。如何使用classloader從服務器加載類文件到客戶端

URL url = new URL("file:///E:/Computing/Master/classes/"); 
URLClassLoader ucl = new URLClassLoader(new URL[]{url}); 
Class clazz = ucl.loadClass("com.counter.controller.Action"); 
ProcessAlgorithm iAction = (ProcessAlgorithm) clazz.newInstance(); 

在這種情況下類加載的完整過程是什麼?

+0

我有一個問題。你的問題在哪裏? :D – Matt

+0

你應該在這裏提出一個問題。你確實可以回答你自己的問題,但首先你需要問一個問題 –

+0

Java的內置RMI使用這種類的分佈,所以它可以工作,但我會警告說,這不太可能是一個好主意。我建議儘可能分發數據而不是代碼。 –

回答

1

我找到了解決方案,並希望在此分享。首先,這項工作是網絡類加載。它可以在javadoc中找到這個名字。 其實是沒有辦法通過使用下面的代碼加載從遠程計算機類文件中:即使你改變它的URL

URL url = new URL("file:///E:/Computing/Master/classes/"); 
URLClassLoader ucl = new URLClassLoader(new URL[]{url}); 
Class clazz = ucl.loadClass("com.counter.controller.Action"); 
ProcessAlgorithm iAction = (ProcessAlgorithm) clazz.newInstance(); 

爲「HTTP」,而有兩個單獨的計算機之間沒有HTTP協議。那麼讓我們開始正確的方式。

假設您有兩臺帶有192.168.10.1(服務器)和192.168.10.2(客戶端)IP的計算機。有一個客戶端不應該從服務器磁盤複製到其磁盤的類文件。因此,首先,開始在兩個JVM(服務器和客戶端)上定義相同的接口。與以下接口相同的包:

package org.counter.biz; 

public interface ProcessAlgorithm { 

    int doProcess() ; 

} 

因此,此接口在服務器和客戶端上很常見。其次,你的主類應該在服務器上被定義和實現接口:

package org.counter.biz; 

public class Action implements ProcessAlgorithm { 

    @Override 
    public int doProcess() { 

     /* something to do */ 

    } 
} 

最後的類文件應該被髮送到客戶端上的插座或插槽通道。在這裏,我在我的服務器上使用Socketchannel,在我的客戶端上使用Socket。 (實際上,你必須知道如何將兩個遠程計算機通過插座中連接。)發送的類文件的字節客戶

服務器端代碼:

private void sendAlgorithmFile(SocketChannel client, String filePath) throws IOException { 

     ByteBuffer buffer = ByteBuffer.allocate(8192); 
     buffer.clear(); 

     /*file path like E:\\classes\\Action.class*/ 
     Path path = Paths.get(filePath); 
     FileChannel fileChannel = FileChannel.open(path); 
     int bytes = 0; 
     int counter = 0; 


     do { 
      bytes = fileChannel.read(buffer); 
      if (bytes <= 0) 
       break; 
      counter += bytes; 
      buffer.flip(); 
      do { 
       bytes -= client.write(buffer); 
      } while (bytes > 0); 
      buffer.clear(); 
     } while (true); 


     fileChannel.close(); 

    } 

有通過發送一個文件多途徑插座。這是我的代碼,它的正確性已經過檢查。

客戶端接收文件並將其更改爲未保存在客戶端磁盤上的類。

package org.counter.biz; 

import java.io.IOException; 
import java.io.InputStream; 
import java.net.Socket; 

public class MyClassLoader extends ClassLoader { 

    private Socket clientChannel; 
    private int count = 0; 

    public MyClassLoader(Socket channel){ 
     this.clientChannel = channel; 
    } 

    @Override 
    protected Class findClass(String className){ 

     Class myClass = null; 

     InputStream inputStream = null; 

     try { 
      inputStream = clientChannel.getInputStream(); 
     }catch (IOException e){e.printStackTrace();} 


     byte[] bytes = new byte[8192]; 
     byte[] myBytes = null; 

     try { 
      while ((count = inputStream.read(bytes)) > 0){ 
       myBytes = new byte[count]; 
       System.arraycopy(bytes, 0, myBytes, 0, count); 
       myClass = defineClass(className, myBytes, 0, myBytes.length); 
      } 
      inputStream.close(); 
     }catch (IOException io){} 


     return myClass; 

    } 

} 

然後:

public class Client { 
    public static void main(String[] args) throws Exception{ 
    MyClassLoader myClassLoader = new MyClassLoader(clientSocket); 
    Class clazz = myClassLoader.findClass(null); 
    ProcessAlgorithm iAction = (ProcessAlgorithm) clazz.newInstance(); 
    } 
} 

然後你就可以使用類這樣

iAction.doProcess(); 

如果有任何問題,我在這裏回答。 :)

相關問題