我想编写一个应用程序,用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
答案 0 :(得分: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 :(得分:0)
如堆栈跟踪所示,根本原因是:
Caused by: java.io.NotSerializableException: java.awt.image.BufferedImage
表示您尝试序列化不可序列化的类,即BufferedImage
。
另一种方法是使用和ImageIcon
而不是BufferedImage
。
答案 2 :(得分:0)
@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)));
作品