通过套接字发送图像时的Java OutOfMemory

通过套接字发送图像时的Java OutOfMemory,java,memory,out-of-memory,Java,Memory,Out Of Memory,我创建了一个应用程序,基本上使用robot在客户端获取图像,并每隔几秒钟发送到服务器,这样我就可以观察另一台PC上的情况。问题似乎是它一直将图像保存在数组或其他东西中,因为几秒钟后,它就会崩溃。我只是接收图像并在接收图像时将其写在屏幕上。然而,过了一段时间,它让我失去了记忆。有没有人知道是什么原因引起的 以下是请求的代码段: 服务器: private class Conexao extends Thread { public static final int PORTA = 12000

我创建了一个应用程序,基本上使用robot在客户端获取图像,并每隔几秒钟发送到服务器,这样我就可以观察另一台PC上的情况。问题似乎是它一直将图像保存在数组或其他东西中,因为几秒钟后,它就会崩溃。我只是接收图像并在接收图像时将其写在屏幕上。然而,过了一段时间,它让我失去了记忆。有没有人知道是什么原因引起的

以下是请求的代码段:

服务器:

private class Conexao extends Thread {

    public static final int PORTA = 12000;
    public ObjectOutputStream out;
    public ObjectInputStream in;
    public Image image;
    private boolean fim;

    public Conexao(String ip) throws IOException {
        try {
            Socket socket = new Socket(ip, Conexao.PORTA);
            this.out = new ObjectOutputStream(socket.getOutputStream());
            this.in = new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            throw e;
        }
    }

    public void encerrar() {
        this.fim = true;
    }

    @Override
    public void run() {
        this.fim = false;
        while (!this.fim) {
            Mensagem mensagem = null;

            try {
                mensagem = ((Mensagem) in.readObject());
            } catch (IOException | ClassNotFoundException e) {
            }

            if (mensagem != null) {
                this.image = mensagem.getImage();
                Cliente.this.painel.repaint();
            }
        }
    }
}
客户:

private static class Conexao extends Thread {

    private static Image CURSOR;
    static {
        try {
            CURSOR = ImageIO.read(new File("images\\mouse.png"));
        } catch (IOException e) {
            CURSOR = null;
        }
    }

    private ObjectOutputStream out;
    private ObjectInputStream in;

    public Conexao() throws IOException {
        try {
            ServerSocket serverSocket = new ServerSocket(Servidor.PORTA, 1);
            Socket socket = serverSocket.accept();
            this.out = new ObjectOutputStream(socket.getOutputStream());
            this.in = new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            throw e;
        }
    }

    @Override
    public void run() {
        try {
            Robot robot = new Robot();

            for (;;)
                try {
                    Thread.sleep(10);

                    Point p = MouseInfo.getPointerInfo().getLocation();
                    BufferedImage img = robot.createScreenCapture(new Rectangle(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height));
                    if (Conexao.CURSOR != null) {
                        img.getGraphics().drawImage(CURSOR, p.x, p.y, null);
                    } else {
                        Graphics2D g = (Graphics2D) img.getGraphics();
                        g.setColor(Color.WHITE);
                        g.fillOval(p.x - 5, p.y - 5, 10, 10);
                        g.setStroke(new BasicStroke(2));
                        g.setColor(Color.BLACK);
                        g.drawOval(p.x - 5, p.y - 5, 10, 10);
                        g.dispose();
                    }

                    this.out.writeObject(new Mensagem(img, p));
                    this.out.flush();
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                }

        } catch (AWTException e) {
        }
    }
}

在不查看代码的情况下,我能提供的唯一具体提示是使用内存分析器,如或


某个地方正在保留对可能不应该保留的对象的引用。

在不查看代码的情况下,我可以提供的唯一具体提示是使用内存分析器,例如或


某个地方保存了对可能不应该保存的对象的引用。

在没有看到任何代码的情况下,您很可能正在填充类或实例范围内的
字节[]
ByteArrayOutputStream
。您应该将收到的内容写入文件,然后根据需要访问它。这意味着在切换到新图像时,删除对内容的引用(使其超出范围)


如果您可以提供有关应用程序工作方式的更多详细信息,其他人应该能够找出问题所在。

在没有看到任何代码的情况下,您很可能正在填充一个类或实例范围内的
字节[]
ByteArrayOutputStream
。您应该将收到的内容写入文件,然后根据需要访问它。这意味着在切换到新图像时,删除对内容的引用(使其超出范围)


如果您可以提供有关应用程序工作方式的更多详细信息,其他人应该能够找出问题所在。

OutOfMemory是由堆空间不足引起的

您可以尝试以下操作:

运行应用程序时,请确保有足够大小的堆空间可用。(
-Xmx128M
在java命令行上,其中128由要分配的兆字节数替换)

发送图片后,释放对不再需要的对象的所有引用(通过让变量超出范围或将对象变量显式设置为null)


如果这无助于重用对象而不是创建新对象。

OutOfMemory是由堆空间不足引起的

您可以尝试以下操作:

运行应用程序时,请确保有足够大小的堆空间可用。(
-Xmx128M
在java命令行上,其中128由要分配的兆字节数替换)

发送图片后,释放对不再需要的对象的所有引用(通过让变量超出范围或将对象变量显式设置为null)


如果这无助于重用对象而不是创建新对象。

尝试调用
this.out.reset()
this.out.flush()之后


这似乎是一个问题,它(根据and)保留一个所有写入它的对象的缓存,以便可以将重复的对象优化为缓存引用。当对象中的值在重新发送对象之前更改,但缓存的对象保留旧值时,这也会导致问题。在这两种情况下,调用
reset()。不幸的是,这些都没有在类文档中解释。

尝试调用
this.out.reset()
this.out.flush()之后


这似乎是一个问题,它(根据and)保留一个所有写入它的对象的缓存,以便可以将重复的对象优化为缓存引用。当对象中的值在重新发送对象之前更改,但缓存的对象保留旧值时,这也会导致问题。在这两种情况下,调用
reset()。不幸的是,这些都没有在类文档中解释。

您是否使用IDE来运行此应用程序?我告诉你你在用哪个IDE?我在NetBeans中遇到了这个问题,我已经解决了这个问题。请确保您阅读和绘制图像的速度比它们进来的速度快。否则您的网络缓冲区将成为OOMYes,我正在使用netbeanside…我如何确保它?您是否使用任何IDE来运行此应用程序?我告诉你你在用哪个IDE?我在NetBeans中遇到了这个问题,我已经解决了这个问题。请确保您阅读和绘制图像的速度比它们进来的速度快。否则您的网络缓冲区将成为OOMYes,我正在使用NetBeans IDE…我如何确保它?调用
System.gc()
是一个糟糕的主意。在这方面肯定没有帮助。(见)这要看情况而定。我认为sleskes的评论适用于这种情况,因为这个应用程序所做的就是每隔几秒钟发送一个图像。如果内存不足,JVM无论如何都会调用GC。只有当GC尝试回收足够的内存以继续时,才会抛出OOME。显式调用GC没有帮助。“一点也没有。@Stephen删掉了显式call.FWIW-sleskes评论是关于一个特定的案例,您试图减少破坏性垃圾收集暂停。。。在您知道暂停不会中断的情况下。这与这里无关。调用
System.gc()
是个糟糕的主意。在这方面肯定没有帮助。(见)这要看情况而定。我认为sleskes的评论适用于这种情况,因为这个应用程序所做的就是每隔几秒钟发送一个图像。如果内存不足,JVM无论如何都会调用GC。只有当GC尝试回收足够的内存以继续时,才会抛出OOME。显式调用GC没有帮助。斯蒂芬删掉了显式的call。FWIW-sleskes评论是关于一个特定的案例,其中y