1

我已经编写了下面的代码,但是在调用了将近 150 次之后,它抛出了“线程中的异常“Thread-245”java.lang.OutOfMemoryError:Java 堆空间”问题只是出现在 (b = new byte[1024 * 1024] ;) Java 代码:

class Client implements Runnable {
private Socket socket;
private BufferedInputStream bufin = null;
private BufferedOutputStream bufout = null;
String path;
private byte[] b;

Client(Socket socket, String path) {
    this.socket = socket;
    this.path = path;
}

@Override
public void run() {
    try {
        bufin = new BufferedInputStream(socket.getInputStream());
        bufout = new BufferedOutputStream(new FileOutputStream(path));

        b = new byte[1024 * 1024];
        int num = 0;
        while ((num = bufin.read(b)) != -1)
            bufout .write(b, 0, num);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            bufin.close();
            bufout .close();
            b = null;
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}

我试图更清楚地描述这个问题。是这样的:我写了我的ServerSocket,当客户端发送请求时,服务器然后将请求放在一个新线程中,如下所示:

public void start() {
      boolean started = false;
      try {
              ServerSocket ss = new ServerSocket(8888);
              started = true;
              while (started) {
              String path = "C:/Pic/"+ new SimpleDateFormat("yy-MM-dd-HH_mm_ss_ms").format(new Date()) + ".jpg";
              Socket s = ss.accept();
              new Thread(new Client(s, path)).start();
             }
       } catch (IOException e) {
              e.printStackTrace();
       }

}

在这种情况下,服务器将接收来自任何客户端的请求......还有第二个问题,我认为该问题将导致 Java 堆空间异常,即当服务器收到图片时,图片无法从中删除关闭服务器之前的磁盘,当我删除它时,它显示“操作无法完成,因为文件在 Java(TM) 平台 SE 二进制文件中打开”。而我已经关闭了客户端线程中的输入输出。现在我无法找到问题的根源,1.为什么会发生 Heap Exception anr 2.为什么在服务器运行期间文件无法从磁盘中删除。非常感谢您的回复!

4

2 回答 2

0

我怀疑堆耗尽不允许程序在异常发生后正常运行,然后在 finally 块中,使流保持打开状态。我建议你在打开流之前更改程序以分配内存块;此外,要关闭 finally 块中的流,我建议您使用示例中所述的 IOUtils commons-io 类:

悄悄靠近

byte[] data = "Hello, World".getBytes();

OutputStream out = null;
try {
 out = new FileOutputStream("foo.txt");
 out.write(data);
 out.close(); //close errors are handled
} catch (IOException e) {
 // error handling
} finally {
 IOUtils.closeQuietly(out);
}

这使您可以确保在 finally 块中关闭所有流。

于 2012-12-27T17:19:34.270 回答
0

由于每个线程都在创建一个 1MB 的数组缓冲区,因此您的内存不足。您想查看最大堆大小是多少(这取决于几个变量)并在命令行增加最大大小,例如:java -Xmx1024M myclass.class

另外,你说你开始了 150 个客户。为什么他们不收集垃圾?也许所有 150 个线程都立即启动并且所有线程都在同时获取该内存?我建议使用线程池来执行这些操作,这样您就可以限制正在运行的客户端数量。

对于您保存文件的服务器的问题(您无法删除它)是因为您遇到了堆内存错误。当你得到这个时,所有的赌注都结束了。服务器仍然持有对该文件的引用,并且 bufout.close() 可能没有工作。

于 2012-12-27T17:03:07.097 回答