如何解析OutOfMemory:我的客户端程序上的Java HeapSpace(使用Eclipse)

如何解析OutOfMemory:我的客户端程序上的Java HeapSpace(使用Eclipse),java,client-server,out-of-memory,heap-memory,Java,Client Server,Out Of Memory,Heap Memory,我正在编写一个客户机-服务器程序。客户端位于同一WLAN上的另一台计算机上。我遇到的问题是客户端的异常:java.lang.OutOfMemoryError:java堆空间 问题是,如果我也将服务器计算机用作客户端(同一台计算机上的服务器客户端),它不会引发此异常。但是,每次我从另一台计算机运行客户端下载文档时,它都会抛出异常 请提供一个简单的方法来解决这个问题。我使用Eclipse 下面是我的客户端类: public void run() { try { se

我正在编写一个客户机-服务器程序。客户端位于同一WLAN上的另一台计算机上。我遇到的问题是客户端的异常:
java.lang.OutOfMemoryError:java堆空间

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

请提供一个简单的方法来解决这个问题。我使用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();
        }}

}

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

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

还可以在Eclipse:Server>openlaunchconfiguration>参数中向Tomcat添加-XX:MaxPermSize=256m


参考链接在这里:

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


我还注意到,您正在将一个文件作为一大块读取到内存中。为了避免巨大的即时内存需求,我会一块一块地做(比如1或2 kb的块)。

HotSpot根据机器上的总物理RAM来调整堆的大小。更改主机时,隐式更改堆限制。看起来,在你的远程机器上,你的内存更少,因此你达到了极限

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

如果您正在读取文本文件,那么您应该使用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&BufferedOutput Stream无法使用BufferedReader读取二进制数据,因为会将二进制数据转换为字符串格式&文件将损坏。

您的文件中可能没有行终止符。在这种情况下,读取器继续读取文件,直到堆内存中有空间为止。这就是你从记忆中得到错误的原因


编辑:

要对音频文件执行读/写操作,Java标准版-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
getResourceAsStream(“您的视频文件”)中有一个方法,它返回InputStream的对象。此流可用于读取视频文件数据并将其写入另一个文件或任何您想执行的操作

一些示例代码如下所示:-

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

fis、bis、os、fos、bos的关闭看起来不健康。。。首先,你应该抽出一些时间来清理这些乱七八糟的文件。你正在阅读哪些类型的文件(二进制、文本等)?我正在阅读短视频、音频和基于文本的文件-每个文件的最大容量不能超过100MB(最坏情况下)。我需要关于如何读取小块文件的帮助uu任何人都可以提供示例代码帮助吗?这是有道理的!我正在使用代码阅读视频、音频、文本文件等。。。这可能意味着我应该分别读取每种类型的文件。我同意,我也应该一点一点地读。如果这个答案能帮助你解决错误,那么你应该接受它。读音频和视频文件的最佳方式是什么?我可以使用什么形式的读写流?@Jojo我已经用解决方案更新了我的答案,以便对音频和视频文件执行读写操作。我希望这会对你有更多帮助。看看最新的答案。是的,我真的不知道如何去阅读文件块,我上传,短视频,音频,基于文本的文件,你能帮我一个方法吗?谢谢