0

Every 50 Miliseconds I am taking a Screenshot and sending it to another Computer which is showing the Screenshot. I am mirroring the Desktop. Now the problem is the Program is stopping because the Memory usage is getting too high. My Question is how can I "clear" the RAM - I already googled and found out that I should use the Garbage Collector but this isn't working. Here is my code:

CLIENT:

Client.java

import java.awt.AWTException;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketException;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

public class Client implements Runnable {

  private Socket socket;
  private ObjectInputStream din;
  private static ObjectOutputStream dout;

  public Client(String ip, int port) {
    try {
      socket = new Socket(ip, port);
      din = new ObjectInputStream(socket.getInputStream());
      dout = new ObjectOutputStream(socket.getOutputStream());
    } catch (ConnectException e) {
      JOptionPane.showMessageDialog(null, "Server is offline");
      System.exit(0);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void run() {
    while (true) {
      try {
        Thread.sleep(50);
        Robot robot = new Robot();
        Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
        BufferedImage screenFullImage = robot.createScreenCapture(screenRect);
        ImageIO.write(screenFullImage, "jpeg", new File("C:\\Windows\\Temp\\screenshot.jpeg"));
      } catch (IOException | AWTException | InterruptedException e) {
        e.printStackTrace();
      }

      ImageIcon ii = new ImageIcon("C:\\Windows\\Temp\\screenshot.jpeg");

      send(new Obj(ii));;
    }
  }

  public static void send(Obj obj) {
    try {
      dout.writeObject(obj);
      dout.flush();
    } catch (SocketException e) {
      JOptionPane.showMessageDialog(null, "Connection closed");
      System.exit(0);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void close() {
    try {
      dout.close();
      din.close();
      socket.close();
    } catch (IOException e) {
    }
  }

}

Main.java

public class Main {
  public static void main(String[] args) {

    // Connect to the Server
    Client client = new Client("localhost", 9785);

    // Runs a new Client
    Thread clientThread = new Thread(client);
    clientThread.start();
  }
}

Obj.java

package ch.nyp.blj;


import java.io.Serializable;

import javax.swing.ImageIcon;

public class Obj implements Serializable {
  private ImageIcon img;

  public Obj(ImageIcon img) {
    super();
    this.img = img;
  }

  public ImageIcon getImg() {
    return img;
  }

  public void setImg(ImageIcon img) {
    this.img = img;
  }
}

SERVER:

Main.java

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Main {

  public static void main(String[] args) {
    GUI.open();
    try {
      ServerSocket s = new ServerSocket(9785);
      System.out.println("Server Online");
      while (true) {
        Socket client = s.accept();
        if (client != null) {
          ClientThread ct = new ClientThread(client);
          new Thread(ct).start();
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Obj.java

    import java.io.Serializable;

    import javax.swing.ImageIcon;

    public class Obj implements Serializable {
      private ImageIcon img;

      public Obj(ImageIcon img) {
        super();
        this.img = img;
      }

      public ImageIcon getImg() {
        return img;
      }

      public void setImg(ImageIcon img) {
        this.img = img;
      }
    }

GUI.java

import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JLabel;

public class GUI {

  public static JLabel img;
  private JFrame frame;
  public static Dimension d = new Dimension(400, 400);

  /**
   * Launch the application.
   */
  public static void open() {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        try {
          GUI window = new GUI();
          window.frame.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }

  /**
   * Create the application.
   */
  public GUI() {
    initialize();
  }

  /**
   * Initialize the contents of the frame.
   */
  private void initialize() {
    frame = new JFrame();
    frame.setSize(d.width, d.height);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    img = new JLabel("");
    GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
    groupLayout.setHorizontalGroup(
      groupLayout.createParallelGroup(Alignment.LEADING)
        .addComponent(img, GroupLayout.DEFAULT_SIZE, 1924, Short.MAX_VALUE)
    );
    groupLayout.setVerticalGroup(
      groupLayout.createParallelGroup(Alignment.LEADING)
        .addComponent(img, GroupLayout.DEFAULT_SIZE, 1181, Short.MAX_VALUE)
    );
    frame.getContentPane().setLayout(groupLayout);
  }
}

ClientThread.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;

public class ClientThread implements Runnable {
  private Socket socket;
  private ObjectOutputStream dout;
  private ObjectInputStream din;
  private static Obj input = null;

  ClientThread(Socket socket) {
    this.socket = socket;
    try {
      this.dout = new ObjectOutputStream(socket.getOutputStream());
      this.din = new ObjectInputStream(socket.getInputStream());
    } catch (IOException e) {
      e.printStackTrace();
      Thread.currentThread().interrupt();
    }
  }

  @Override
  public void run() {
    try {
      while (true) {
        try {
          input = (Obj) din.readObject();
        } catch (ClassNotFoundException e) {
          e.printStackTrace();
        }

        GUI.img.setIcon(input.getImg());

        System.out.println(input.getImg());

      }
    } catch (SocketException e) {
      Thread.currentThread().interrupt();
    } catch (IOException e) {
    }
  }
}

Exception after some seconds:

Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
        at java.base/java.lang.reflect.Array.newArray(Native Method)
        at java.base/java.lang.reflect.Array.newInstance(Unknown Source)
        at java.base/java.io.ObjectInputStream.readArray(Unknown Source)
        at java.base/java.io.ObjectInputStream.readObject0(Unknown Source)
        at java.base/java.io.ObjectInputStream.readObject(Unknown Source)
        at java.desktop/javax.swing.ImageIcon.readObject(Unknown Source)
        at java.base/jdk.internal.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at java.base/java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
        at java.base/java.io.ObjectInputStream.readSerialData(Unknown Source)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
        at java.base/java.io.ObjectInputStream.readObject0(Unknown Source)
        at java.base/java.io.ObjectInputStream.defaultReadFields(Unknown Source)
        at java.base/java.io.ObjectInputStream.readSerialData(Unknown Source)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
        at java.base/java.io.ObjectInputStream.readObject0(Unknown Source)
        at java.base/java.io.ObjectInputStream.readObject(Unknown Source)
        at ch.nyp.blj.ClientThread.run(ClientThread.java:31)
        at java.base/java.lang.Thread.run(Unknown Source)
Tom
  • 11
  • 5
  • Possible duplicate of [Java garbage collect to hashtable](https://stackoverflow.com/questions/12409160/java-garbage-collect-to-hashtable) – sarkasronie Mar 29 '18 at 09:02
  • @sarkasronie nah – Tom Mar 29 '18 at 09:47
  • What do you mean by "nah"? Did you read what they wrote in this question? There is an explanation how the garbage collector works. – sarkasronie Mar 29 '18 at 10:05
  • @sarkasronie - I tried it with finalize but it's not working – Tom Mar 29 '18 at 10:09
  • What did you try exactly? – sarkasronie Mar 29 '18 at 10:10
  • Maybe set `ii = null;` after sending it. Garbage Collection cleans all objects with no existing reference. – sarkasronie Mar 29 '18 at 10:35
  • @sarkasronie - Instead of System.gc(); I wrote finalize(); Good idea but It didn't worked. – Tom Mar 29 '18 at 11:13
  • System.gc(); should do the trick - but be aware that this call is only a hint for the GC - that doesn't mean that he's running instantly. And GC only cleans objects that have no more reference - so setting `ii` to null has to be done in addition. – sarkasronie Mar 29 '18 at 11:16
  • @sarkasronie - I tried it with ii = null; and System.gc(); Still not working... – Tom Mar 29 '18 at 11:22
  • What does your `send()` method do? What does _"memory usage is getting too high"_ exactly mean? How high? Would simply increasing the `-Xmx` help? I do not see any obvious problems in the code you showed - all references are being thrown away correctly. Java manages memory for you, you should never need to call `System.gc()` or `whatever.finalize()` (the latter even does not do what you think it does). – Petr Janeček Mar 29 '18 at 14:23
  • @PetrJaneček - I completeted the Code in the Post. Yeah, I tried to increase with -Xmx. The ram is going up to 2gb in 20 Seconds or something like this. – Tom Mar 29 '18 at 14:44
  • Ah, I see. Your server is dying, yet you first posted code for client :). Second of all - never, _ever_ update the Swing GUI from a thread other than the event dispatch thread. You're doing exactly that in `GUI.img.setIcon(input.getImg())`. – Petr Janeček Mar 29 '18 at 15:04
  • Either way, most of the memory is held in the ObjectInput/Output streams, and I unfortunately do not have enough time now to investigate why that might be the case. Try having a slower client, if that helps. – Petr Janeček Mar 29 '18 at 15:36
  • I found the problem - It's a simple dout.reset(); – Tom Apr 04 '18 at 06:38

0 Answers0