【问题标题】:help for solving problems in a java rmi assignment帮助解决 java rmi 分配中的问题
【发布时间】:2010-02-09 08:45:55
【问题描述】:

我想编写一个应用程序来使用 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

【问题讨论】:

    标签: java rmi


    【解决方案1】:

    您不能将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));
        }
    }
    

    【讨论】:

    • +1:为了包括压缩,这对于远程处理很重要
    【解决方案2】:

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

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

    这意味着你试图序列化一个不可序列化的类,即BufferedImage

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

    【讨论】:

      【解决方案3】:

      @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)));
      

      作品

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-23
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多