繁体   English   中英

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

[英]Java OutOfMemory when sending images via socket

我创建了一个应用程序,该应用程序基本上使用机器人在客户端中获取图像并每隔几秒钟发送到服务器,因此我可以观察另一台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) {
        }
    }
}

我看不到代码的唯一提示是使用内存分析器,例如VisualVMYourKit

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

OutOfMemory是由堆空间不足引起的。

您可以尝试一些操作:

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

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

如果这样做没有帮助,请尝试重用对象而不是创建新对象。

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

这似乎是ObjectOutputStream的问题,它(根据序列化常见问题解答本网站的介绍 )保留所有写入对象的缓存,以便可以将重复的对象优化为缓存引用。 当重新发送对象之前对象中的值发生更改,但是缓存的对象保留旧值时,这也会引起问题。 在这两种情况下,调用reset()都可以解决此问题。 不幸的是,在类文档中没有任何解释。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM