Reputation: 187
I'm trying to build an application where a client sends its screen to the server, the client only sends its screen if there is a difference between last send screen and the latest captured screen(so that the program is easy on the network). And the server uses a JFrame and JLabel to display the image. But the thing is after a minute or two the server is giving a java.lang.OutOfMemoryError: Java heap space.
Please consider my code
public void go() throws Exception
{
s=new Socket("127.0.0.1",5000);
remoteIP = s.getInetAddress();
remoteIPOnly = remoteIP.toString().split("\\/");
frame=new JFrame(remoteIPOnly[1]);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
InputStream iss=s.getInputStream();
ObjectInputStream is=new ObjectInputStream(iss);
JLabel a=new JLabel();
while(!s.isClosed())
{
if((ImageIcon)is.readObject()!=null)
{
System.out.println("I got here");
imageIcon=(ImageIcon) is.readObject();
image=imageIcon.getImage();
rendered = null;
if (image instanceof RenderedImage)
{
rendered = (RenderedImage)image;
}
else
{
buffered = new BufferedImage(
imageIcon.getIconWidth(),
imageIcon.getIconHeight(),
BufferedImage.TYPE_INT_RGB
);
g = buffered.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
rendered = buffered;
}
frame.setSize(rendered.getWidth(),rendered.getHeight());
a.setIcon(imageIcon);
frame.add(a);
frame.setVisible(true);
}
}
}
And here is my other piece of code, it is also showing the same problem, pls help me optimize it.
while(true)
{
s=serversocket.accept();
os=s.getOutputStream();
oss=new ObjectOutputStream(os);
image1=r.createScreenCapture(newRectangle(Toolkit.getDefaultToolkit().getScreenSize()));
imageicon=new ImageIcon(image1);
oss.writeObject(imageicon);
while(!s.isClosed()){
image2=r.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit
().getScreenSize()));
b=checkIfImagesAreEqual(image1,image2);
System.out.println(b);
if(b==false){
image1=image2;
imageicon1=new ImageIcon(image2);
oss.writeObject(imageicon1);
oss.flush();
}
Can anyone tell me if my logic for my purpose is correct or not and why am I getting the java.lang.OutOfMemoryError: Java Heap space and will extending the heap size help me as I'm planning for more than one client to be able to connect to the server?
Sorry if my question is dumb and any help will be appreciated.Thank you.
Upvotes: 0
Views: 1023
Reputation: 728
You need to manually signal for garbage collection after manually disposing of large objects. Also, general optimizing will help.
I would recommend (in your client):
Then in your loop
See how that goes. Oh and if your inbound images are of varying size, you'll probably want to wipe the BufferedImage before drawing on it again else you get funky borders :-)
As for your server, it looks alright, I'd just ditch the ImageIcons and go with just passing plain old Images. Something like this:
Begin loop
Begin inner loop
And if a perfectly clear image isnt manditory, you might also consider compressing the image before sending it, and just dealing with it as a byte array; you'd wire much less information.
public static byte[] bufferedImageToJPEGBytes(BufferedImage bi){
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, "jpg", baos);
return baos.toByteArray();
} catch (IOException e){
return null;
}
}
public static BufferedImage jpegBytesToBufferedImage(byte[] bytes){
try{
ByteArrayInputStream bais = new ByteArrayInputStream(rightImageBytes);
return ImageIO.read(bais);
} catch (IOException e){
return null;
}
}
and then just use
oos.writeObject(bufferedImageToJPEGBytes(image1)); //server side
and
image = jpegBytesToBufferedImage((byte[]) ois.readObject()); //client side
Upvotes: 1
Reputation: 1207
You keep adding the label to the frame. Shouldn't you just add it once?
There is an another problem: if((ImageIcon)is.readObject()!=null)
will read out an image and lose it. You should instead keep it and not read it inside the if
block. For instance:
if((imageIcon = (ImageIcon)is.readObject()) != null)
Upvotes: 4