帮助解决java rmi任务中的问题

我想编写一个应用程序,用java rmi在客户端和服务器之间共享桌面。 这是界面:

public interface IServer extends Remote{ public void share(BufferedImage image) throws RemoteException; } ----------------------------- 

//这是服务器端代码:

 public class ServerFrame extends JFrame implements IServer{ public static void main(String args[]) { try { ServerFrame frame = new ServerFrame(); frame.setVisible(true); LocateRegistry.createRegistry(1099); Naming.bind("test", frame); System.out.println("Server Started Successfully..."); } catch (Exception e) { e.printStackTrace(); } } . . . public ServerFrame() { super(); try { UnicastRemoteObject.exportObject((Remote) this); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } . . . // bulding the ServerFrame GUI . . . public void share(BufferedImage image) throws RemoteException { label.setIcon(new ImageIcon(image)); } } --------------- 

//最后这是客户端:ClientFrame中有一个按钮,我想在单击此按钮后在客户端和服务器之间共享桌面。

 public class ClientFrame extends JFrame implements Remote,Serializable{ IServer serve; ... public ClientFrame() { super(); try { serve = (IServer) Naming.lookup("test"); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } . . . // codes for building client gui final JButton shareDesktopButton = new JButton(); shareDesktopButton.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent arg0) { try { BufferedImage screenShot = new Robot() .createScreenCapture(new Rectangle(Toolkit .getDefaultToolkit().getScreenSize())); label.setIcon(new ImageIcon(screenShot)); serve.share(screenShot); } catch (HeadlessException e) { e.printStackTrace(); } catch (AWTException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }); . . . } // but there is a problem that causes these exceptions that I can not understand it. Please help me to complete my project. 

非常感谢

例外:

 java.rmi.MarshalException: error marshalling arguments; nested exception is: java.io.NotSerializableException: java.awt.image.BufferedImage at sun.rmi.server.UnicastRef.invoke(Unknown Source) at server.ServerFrame_Stub.share(Unknown Source) at client.ClientFrame$1.mouseClicked(ClientFrame.java:86) at java.awt.AWTEventMulticaster.mouseClicked(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) Caused by: java.io.NotSerializableException: java.awt.image.BufferedImage at java.io.ObjectOutputStream.writeObject0(Unknown Source) at java.io.ObjectOutputStream.writeObject(Unknown Source) at sun.rmi.server.UnicastRef.marshalValue(Unknown Source) ... 24 more 

您不能将BufferedImage用作远程参数,因为它既不是Remote也不是Serializable

您可以将BufferedImage包装在ImageIcon但效率非常低,因为它将转换为位图并通过网络进行未压缩传输。

我会让参数Share一个代表压缩图像格式的字节数组(例如PNG)。

 public interface IServer extends Remote{ public void share(byte[] imagePNGBytes) throws RemoteException; } public void mouseClicked(MouseEvent arg0) { try { BufferedImage screenShot = new Robot() .createScreenCapture(new Rectangle(Toolkit .getDefaultToolkit().getScreenSize())); ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ImageIO.write(screenShot, "PNG", bytes); server.share(bytes.toByteArray()); } catch (...) { // ... } } public class ServerFrame extends JFrame implements IServer { // . . . public void share(byte[] imagePNGBytes) throws IOException, RemoteException { RenderedImage image = ImageIO.read(new ByteArrayInputStream(imagePNGBytes)); label.setIcon(new ImageIcon(image)); } } 

如堆栈跟踪所示,根本原因是:

 Caused by: java.io.NotSerializableException: java.awt.image.BufferedImage 

这意味着您尝试序列化不可序列化的类,即BufferedImage

另一种方法是使用和ImageIcon而不是BufferedImage

@finnw

你的代码工作正常,除了

 label.setIcon(new ImageIcon(image)); 

ImageIcon类没有接受RenderedImage对象的构造函数。

所以你需要将RenderedImage转换为BufferedImage。 代码就在这里

 public BufferedImage convertRenderedImage(RenderedImage img) { if (img instanceof BufferedImage) { return (BufferedImage) img; } ColorModel cm = img.getColorModel(); int width = img.getWidth(); int height = img.getHeight(); WritableRaster raster = cm.createCompatibleWritableRaster(width, height); boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); Hashtable properties = new Hashtable(); String[] keys = img.getPropertyNames(); if (keys != null) { for (int i = 0; i < keys.length; i++) { properties.put(keys[i], img.getProperty(keys[i])); } } BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties); img.copyData(raster); return result; } 

现在将代码更改为

 label.setIcon(new ImageIcon(convertRenderedImage(image))); 

作品