簡體   English   中英

ObjectInputStream消耗太多內存

[英]ObjectInputStream consumes too much memory

我有一個套接字,它每隔幾秒鍾通過ObjectOutputStream向客戶端發送一個對象列表。 在服務器端,每執行一次writeObject(myList)我都要執行flushreset 使用VisualVM檢查內存使用情況,在服務器上沒有內存泄漏,但是在客戶端上,以前讀取的列表似乎保留在內存中。 我試圖在客戶端的ObjectInputStream上執行reset ,但看起來ObjectInputStream不支持此方法(它拋出java.io.IOException: mark/reset not supported )。

這是我的服務器套接字:

public class ConsultaBombas {

    public static void inicializarServidorSocket() {
        try {
            ServerSocket serverSocket = new ServerSocket(5963);
            Thread thread = new Thread(() -> {
                while (!serverSocket.isClosed()) {
                    try {
                        final Socket socket = serverSocket.accept();
                        new ThreadComunicacao(socket).start();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.setName("Consulta bombas (Inicializador)");
            thread.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static class ThreadComunicacao extends Thread {
        private Socket socket;

        public ThreadComunicacao(Socket socket) {
            this.socket = socket;
            setName("Consulta bombas (Comunicação) com início: " + new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date()));
        }

        @Override
        public void run() {
            try {
                ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                while (!socket.isClosed()) {
                    List<Bomba> bombas = new DaoBomba().findAll();
                    out.writeObject(bombas);
                    out.flush();
                    out.reset();
                    Thread.sleep(1000);
                }
            } catch (SocketException e) {
                if (e.getLocalizedMessage() != null && e.getLocalizedMessage().equalsIgnoreCase("Connection reset by peer: socket write error")) {
                    System.out.println("Cliente desconectou...");
                } else {
                    e.printStackTrace();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

這是客戶端(從start()方法開始):

public class ConsultaBombasClient {

    private Socket socket;
    private Thread threadConsulta;

    public ConsultaBombasClient(BombasListener bombasListener, String maquinaDestino) {
        threadConsulta = new Thread(() -> {
            try {
                Thread.currentThread().setName("Consulta Bombas");
                System.out.println("Endereço bagual: "+maquinaDestino);
                socket = new Socket(maquinaDestino, 5963);
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                Object leitura;
                while ((leitura = in.readObject()) != null) {
                    List<Bomba> bombas = (List<Bomba>) leitura;
                    bombasListener.run(bombas);
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        });
        threadConsulta.setDaemon(true);
    }

    public void start() {
        threadConsulta.start();
    }

    public interface BombasListener {
        void run(List<Bomba> bombas);
    }

}

我究竟做錯了什么?

垃圾回收不是立即進行的,您有任何實際的內存麻煩嗎? 您是否嘗試過以低-Xmx值運行客戶端,是否收到OutOfMemoryError – user3707125

沒錯,一段時間后,當內存接近最大堆大小時,它將清除內存中的對象。 我沒看到這是因為我的電腦中有很多RAM,但是有了Xmx50m,我可以看到此功能如您所說。 – Mateus Viccari

顯然bombasListener.run()bombasListener.run()不會釋放提供的列表。

NB ObjectInputStream.readObject()在流的末尾不返回null。 因此,將此測試用作讀取循環的終止條件是不正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM