如何解决OutOfMemory:我的客户端程序上的Java堆空间(使用Eclipse)

时间:2014-10-10 12:03:52

标签: java client-server out-of-memory heap-memory

我正在编写客户端 - 服务器程序。客户端位于同一WLAN上的另一台计算机上。我遇到的问题是客户端的这个例外:java.lang.OutOfMemoryError: Java heap space

问题是如果我也使用服务器计算机作为客户端(同一台机器上的Server-Client),它不会抛出此异常。但是,每次我从另一台计算机运行客户端以下载文档时,它都会抛出异常。

请帮助我们轻松解决这个问题。我使用Eclipse。

以下是我的客户端类:

public void run() {
     try {
            servsock = new ServerSocket(13330);

        while (true) {
          System.out.println("Waiting on question server...");
          try {
          sock = servsock.accept();
          System.out.println("Accepted connection : " + sock);
          // receive file
          byte [] mybytearray  = new byte [FILE_SIZE];
          InputStream is = sock.getInputStream();
          String LocalLocation = "C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject+"\\"+filename;
            File LocalFile = new File(LocalLocation);

            File file = new File("C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject);
            if (!file.exists()) {
                new File("C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject).mkdirs();
                System.out.println(file+ " now exists.");
                }
          File outputfile = new File("C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject+"\\"+filename);
          fos = new FileOutputStream(outputfile);
          bos = new BufferedOutputStream(fos);
          bytesRead = is.read(mybytearray,0,mybytearray.length);
          current = bytesRead;

          do {
             bytesRead =
                is.read(mybytearray, current, (mybytearray.length-current));
             if(bytesRead >= 0) current += bytesRead;
          } while(bytesRead > -1);

          bos.write(mybytearray, 0 , current);
          bos.flush();
          System.out.println("File " + FILE_TO_RECEIVED
              + " downloaded (" + current + " bytes read)");
        }
        finally {
          if (fos != null) fos.close();
          if (bos != null) bos.close();
          if (sock != null) sock.close();
        } }
        } catch (IOException e) {
            e.printStackTrace();
        }

......这是我上传文件的服务器类:

public void uploadIt(InetAddress retur2, String fileLocation2){
    try{
    File myFile = new File (fileLocation2);
    sock = new Socket(retur2, 13330);
    System.out.println("Connection on "+sock.getRemoteSocketAddress());
    os = sock.getOutputStream();
    byte [] mybytearray  = new byte [(int)myFile.length()];
    fis = new FileInputStream(myFile);
    bis = new BufferedInputStream(fis);
    bis.read(mybytearray,0,mybytearray.length);
    os.write(mybytearray,0,mybytearray.length);
    fis.close();
    bis.close();
    os.flush();
    os.close();
    System.out.println("Sent " + fileLocation2 + "(" + mybytearray.length + " bytes)");
  } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
  finally {
    try {
      if (bis != null)bis.close();
    if (os != null) os.close();
    if (sock!=null) sock.close();
    System.out.println("Completed Upload");
        } catch (IOException e) {
            e.printStackTrace();
        }}

}

4 个答案:

答案 0 :(得分:1)

如果您正在阅读文本文件,那么您应该使用 BufferedReader& BufferedWriter ,而不是一次读取整个文件,比如

File file = new File("your file");
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
BufferedReader br = new BufferedReader(new FileReader("your file"));
while ((currentLine = br.readLine()) != null) {
    bw.write(currentLine);
}
bw.close();
br.close();

如果您正在读取二进制文件,则建议使用 BufferedInputStream&的BufferedOutputStream 即可。您无法使用BufferedReader 读取二进制数据,因为它将二进制数据转换为字符串格式&您的文件将损坏或损坏。

您的文件中可能没有行终止符。在这种情况下,读者继续读取文件,直到堆内存中有空间。这就是为什么你得到 OutOfMemory 错误。


编辑:

要对音频文件执行读/写操作, Java Standard Edition - Sound 中有一个扩展名。您可以使用 javax.sound.sampled。* 包中的类。

音频文件示例:

File fileIn = new File("your file");
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(fileIn);
// do something
File fileOut = new File("new file");
if (AudioSystem.isFileTypeSupported(AudioFileFormat.Type.WAVE, audioInputStream)) {
    AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, fileOut);
}

要详细了解声音包,请查看此Java Sound API


要使用视频文件格式,您可以执行以下操作: -

Java getResourceAsStream("your video file")中有一个返回InputStream对象的方法。您可以使用此流来读取视频文件数据&将它写入另一个文件或任何你想做的事情。

InputStream getResourceAsStream(String name) - Java Doc一些示例代码如下所示: -

try {
    InputStream in = this.getClass().getResourceAsStream("your video file");
    BufferedInputStream bis = new BufferedInputStream(in);
    BufferedOutputStream bus = new BufferedOutputStream(new FileOutputStream(
                                       new File("your new video file")));
    byte[] data = new byte[in.available()];
    int read = in.read(data);
    bus.write(read);
} catch (IOException ex) {
}

答案 1 :(得分:0)

实际上,您只需调整VM将使用的最大内存量即可。只需使用-Xmx<size>参数进行调整即可。例如,-Xmx512m将使用最大512 MB的内存。

我还注意到你正在将一个文件作为一大块内容读入内存。我会一块一块地做(如1或2 kb的碎片),以防止巨大的即时记忆需求。

答案 2 :(得分:0)

HotSpot根据计算机上的总物理RAM调整其堆大小。更改主机时,会隐式更改堆限制。看起来,在您的远程计算机上,您拥有较少的RAM,因此您达到了极限。

但是,真正的建议是不要将整个文件加载到内存中;而是以块的形式读取文件并将它们直接写入网络套接字。然后,无论文件大小如何,您都不会遇到此问题。同样的推理也适用于服务器端:不要将整个文件从套接字读入RAM,而是将其直接转储到文件中。

答案 3 :(得分:-1)

尝试提高perm空间,将以下参数添加到vm启动

-XX:PermSize = 256m -XX:MaxPermSize = 256m

还添加 -XX:MaxPermSize = 256m to Tomcat in Eclipse: Server > Open Launch Configuration > Arguments

参考链接在这里:Out of memory