首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解决OutOfMemory:程序(使用HeapSpace )

如何解决OutOfMemory:程序(使用HeapSpace )
EN

Stack Overflow用户
提问于 2014-10-10 12:03:51
回答 4查看 1.4K关注 0票数 0

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

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

请用一个简单的方法来解决这个问题。我用Eclipse。

下面是我的客户类:

代码语言:javascript
复制
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();
        }

.下面是上传文件的服务器类:

代码语言:javascript
复制
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();
        }}

}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-10-10 12:51:59

如果您正在读取文本文件,则应该使用BufferedReader & BufferedWriter,而不是一次读取整个文件,如下所示

代码语言:javascript
复制
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标准版-声音中提供一个扩展。您可以在javax.sound.sampled.*包中使用类。

音频文件示例:

代码语言:javascript
复制
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声音API

要使用视频文件格式,可以如下所示:

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

InputStream getResourceAsStream(字符串名)- Java一些示例代码如下所示:-

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2014-10-10 12:13:07

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

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

票数 0
EN

Stack Overflow用户

发布于 2014-10-10 12:38:11

HotSpot根据机器上的总物理内存来调整堆的大小。更改主机时,可以隐式更改堆限制。似乎,在您的远程计算机上,您有较少的RAM,因此您达到了极限。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26299026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档