2017-01-31 28 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(); 

如果有任何问题,我在这里回答。 :)

相关问题