简体   繁体   English

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

[英]Java OutOfMemory when sending images via socket

I created an application that basically uses robot to get and image in the client and sends to the server every few seconds, so I can watch what's going on on another PC. 我创建了一个应用程序,该应用程序基本上使用机器人在客户端中获取图像并每隔几秒钟发送到服务器,因此我可以观察另一台PC上的情况。 The problem seems to be that it keeps saving the image in an array or something, because after a few seconds, it crashs. 问题似乎在于它一直将图像保存在数组或其他内容中,因为几秒钟后崩溃。 I just recieve the image and write it on the screen when I do. 我只接收图像并将其写在屏幕上。 Yet, after a while, it gives me an OutOfMemory. 然而,过了一会儿,它给了我一个内存不足。 Does anyone have a hint about what may be causing it? 是否有人暗示可能是什么原因?

Here are the code snippets that were requested: 以下是请求的代码段:

server: 服务器:

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();
            }
        }
    }
}

client: 客户:

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) {
        }
    }
}

The only concrete hint I can offer without seeing your code is to use a memory profiler, such as VisualVM or YourKit . 我看不到代码的唯一提示是使用内存分析器,例如VisualVMYourKit

Something somewhere is keeping references to objects that it probably shouldn't. 某个地方正在保留对它不应该引用的对象的引用。

The OutOfMemory is caused by insufficient heap space. OutOfMemory是由堆空间不足引起的。

Some actions you can try: 您可以尝试一些操作:

Make sure you have a good size of heap space available when you run the application. 运行应用程序时,请确保具有足够的可用堆空间大小。 ( -Xmx128M on the java command line where 128 is replaced by the number of megabytes you want to asign) (Java命令行上的-Xmx128M ,其中128被要分配的兆字节数替换)

Release all references (by letting the variables go out of scope or by explicitly setting object variables to null) to objects you no longer need after sending a picture. 发送图片后,释放所有不再需要的对象的引用(通过使变量超出范围或将对象变量显式设置为null)。

If that doesn't help try to reuse objects rather than creating new ones. 如果这样做没有帮助,请尝试重用对象而不是创建新对象。

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

This seems to be an issue with ObjectOutputStream , which (according to the Serialization FAQ and this site ) keeps a cache of all objects written to it so that repeated objects can be optimized into cache references. 这似乎是ObjectOutputStream的问题,它(根据序列化常见问题解答本网站的介绍 )保留所有写入对象的缓存,以便可以将重复的对象优化为缓存引用。 This can also cause problems when a value in the object changes before the object is resent, but the cached object retains the old value. 当重新发送对象之前对象中的值发生更改,但是缓存的对象保留旧值时,这也会引起问题。 In both cases, calling reset() will fix the issue. 在这两种情况下,调用reset()都可以解决此问题。 Unfortunately, none of this is explained in the class documentation. 不幸的是,在类文档中没有任何解释。

Without seeing any code, you are most likely populating a byte[] or ByteArrayOutputStream that is class or instance scoped. 在没有看到任何代码的情况下,您很可能填充的是类别或实例范围内的byte[]ByteArrayOutputStream You should be writing the content received to a file and then accessing it as necessary. 您应该将接收到的内容写入文件,然后根据需要进行访问。 This would mean removing the reference to the content (by having it go out of scope) whenever you switch to the new image. 这意味着每当您切换到新图像时,都将删除对内容的引用(通过使其超出范围)。

If you could provide more detail as to how your application works, others should be able to pinpoint the issue. 如果您可以提供有关应用程序工作方式的更多详细信息,那么其他人应该可以找到问题所在。

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

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