2014-04-18 51 views
0

我正在構建可以在遠程計算機上運行的備份服務器。我想現在的問題是我有內存泄漏。當傳輸大文件,一段時間後會出現以下錯誤:Java - OutofMemory客戶端/服務器應用程序

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:149) 
    at java.lang.StringCoding.decode(StringCoding.java:193) 
    at java.lang.StringCoding.decode(StringCoding.java:254) 
    at java.lang.String.<init>(String.java:536) 
    at java.lang.String.<init>(String.java:556) 
    at Server.run(Server.java:61) 
    at Server.main(Server.java:107) 

我讀過一個安靜一些的這個文章,但沒有人真的給了我一個答案,如何解決這個問題。代碼在下面。提前致謝。

服務器:

private ServerSocket server; 
private Socket acceptingSocket; 

public Server(int port){ 
    try { 
     server = new ServerSocket(port); 
    } catch (IOException e) { 
     System.out.println("Try again"); 
    } 
} 

/** 
* Reads all files and puts them in the back-up folder. Also creates the appropriate dirs. 
*/ 
public void run(){ 
    BufferedInputStream buffer = null; 
    DataInputStream reader = null; 
    BufferedOutputStream out = null; 
    DataOutputStream writer = null; 
    int size = 0; 
    try { 
     acceptingSocket = server.accept(); 
     buffer = new BufferedInputStream(acceptingSocket.getInputStream()); 
     reader = new DataInputStream(buffer); 
     out = new BufferedOutputStream(acceptingSocket.getOutputStream()); 
     writer = new DataOutputStream(out); 
     size = reader.readInt(); 
    } catch (IOException e1) { 
    } 
    System.out.println("Size: " + size); 
      //Variables I need later on, I thought this would help 
    byte[] name; 
    int fileNameLength = 0; 
    long length=0; 
    boolean dir = false; 
    int t = 0; 
    String dirs = ""; 
    File direcs; 
    File file; 
    byte[] b; 
    int bytes=0; 
    for(int j = 0; j < size; j++){ 
     try { 
      fileNameLength = reader.readInt(); 
      name = new byte[fileNameLength]; 
      reader.read(name, 0,fileNameLength); 
      String path = new String(name); 
      System.out.println("Path: " + path); 
      length = reader.readLong(); 
      dir = reader.readBoolean(); 
      path = "/backup" + path; 
      file = new File(path); 
      if(!dir){ 
       t = file.getAbsolutePath().lastIndexOf("/"); 
       dirs = file.getAbsolutePath().substring(0, t); 
       direcs = new File(dirs); 
       System.out.println(direcs.mkdirs()); 
       FileOutputStream fos = new FileOutputStream(file); 
       BufferedOutputStream bos = new BufferedOutputStream(fos); 
       b = new byte[(int) length]; 
       bytes = reader.read(b, 0, (int)length); 
       if(bytes != -1) 
        bos.write(b,0,(int)length);     

       writer.writeUTF("File " + file.getAbsolutePath() + " is created!"); 
       writer.flush(); 
       bos.flush(); 
       fos.flush(); 
       bos.close(); 
       fos.close(); 
       out.flush(); 

      } else file.mkdirs(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    try { 
     buffer.close(); 
     reader.close(); 
     out.close(); 
     writer.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

public static void main(String[] args){ 
    int port = Integer.parseInt(args[0]); 
    Server server = new Server(port); 
    while(true) 
     server.run(); 
} 

客戶:

private DataInputStream serverToClient; 
private Socket client; 
private DataOutputStream clientToServer; 
private String name; 

public Client(String name, int port){ 
    try { 
     client = new Socket(name, port); 
     //receive response server 
     serverToClient = new DataInputStream(client.getInputStream()); 
     //send message to server 
     clientToServer = new DataOutputStream(client.getOutputStream()); 
     this.name = name; 
    } 
    catch (IOException e) { 
    } 
} 

/** 
* Closes all connections 
*/ 
public void stop(){ 

    try { 
     client.close(); 
     serverToClient.close(); 
     clientToServer.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

/** 
* Sends all files and content of the files to the back-up server 
* @param filePath 
*/ 
public void backUp(String filePath){ 
    ArrayList<File> files = new ArrayList<File>(); 
    boolean dir = false; 
    long length = 0; 
    byte[] buffer; 
    try{ 
     listf(filePath, files, 0); 
     System.out.println(files.toString()); 
     clientToServer.writeInt(files.size()); 

     for(File fi : files){ 
      dir = false; 
      if(fi.isDirectory()) dir = true; 
      clientToServer.writeInt(fi.getAbsolutePath().length()); 
      System.out.println(fi.getAbsolutePath().length()); 
      clientToServer.writeBytes(fi.getAbsolutePath()); 
      System.out.println(fi.getAbsolutePath()); 
      length = fi.length(); 
      clientToServer.writeLong(length); 
      clientToServer.writeBoolean(dir); 
      System.out.println("Dir? " + dir); 
      System.out.println(length); 
      if(!dir){ 
       FileInputStream fis = new FileInputStream(fi); 
       BufferedInputStream bis = new BufferedInputStream(fis); 

       buffer = new byte[(int)length]; 

       bis.read(buffer, 0, (int)length); 
       clientToServer.write(buffer); 
       System.out.println(serverToClient.readUTF()); 
       bis.close(); 
       fis.close(); 
       clientToServer.flush(); 
      } 
     } 

    } catch(IOException e){ 
     e.printStackTrace(); 
    } 
} 

/** 
* Get all files, folders and subfolders in the file specified by directoryName, recursively. 
* @param directoryName 
* @param files 
* @param size 
*/ 
private void listf(String directoryName, ArrayList<File> files, int size) { 
    File directory = new File(directoryName); 
    size = files.size(); 
    if(size > 100){ 
     System.out.println(size); 
     size += 100; 
    } 
    if(directory.isFile()) files.add(directory); 
    else{ 
     File[] fList = directory.listFiles(); 
     for (File file : fList) { 
      if(file.isDirectory() && file.listFiles().length == 0) files.add(file); 
      else{ 
       if (file.isFile()) { 
        files.add(file); 
       } else if (file.isDirectory()) { 
        listf(file.getAbsolutePath(), files, size); 
       } 
      } 
     } 
    } 
} 

public static void main(String[] args){ 
    String name = args[0]; 
    int port = Integer.parseInt(args[1]); 
    System.out.println("Name: " + name + " Port: " + port); 
    Client client = new Client(name, port); 
    File file = new File(args[2]); 
    if(file.exists())client.backUp(args[2]); 
    else System.out.println("File doesn't exist"); 
    client.stop(); 

} 

回答

0

你並不需要一個緩衝文件的大小。這隻會浪費內存並增加延遲,顯然它不會擴展到大型文件。請參閱this answer以瞭解複製流的正確方法。

如果你需要保持套接字打開後傳中,你需要知道的長度事先,你需要修改循環條件

while (total < length && (count = in.read(buffer, 0, length-total > buffer.length ? buffer.length : (int)(length-total))) > 0) 

其中「長」是已知的文件長度, '總'最初爲零。您還必須在循環內通過'count'增加'total'。

+0

謝謝!我之前曾嘗試過類似的東西,但沒有正確安靜。它現在的作品:) – SBylemans

+0

我也發送字節數組的文件名稱,並在服務器端每次創建一個新的字節數組與文件名的長度。這也會導致內存不足錯誤。我該如何解決這個問題? – SBylemans

+0

使用DataOutputStream.writeUTF()及其相反。 – EJP

相關問題