2014-04-18 3 views
0

원격 컴퓨터에서 실행할 수있는 백업 서버를 구축 중입니다. 문제는 지금 메모리 누수가 있다고 생각합니다. 큰 파일을 전송할 때, 잠시 후 다음과 같은 오류 메시지가 나타납니다자바 - 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) 
'길이'알려진 파일 길이

에 루프 조건을 수정해야 'total'은 처음에는 0입니다. 루프 내에서 'total'을 'count'만큼 증가시켜야합니다.

+0

감사합니다. 나는 전에 그런 것을 시도했지만 조용히하지 않았다. 이제 작동합니다 :) – SBylemans

+0

바이트 배열로 파일 이름을 보내고 파일 이름의 길이를 사용하여 매번 서버 측에 새 바이트 배열을 만듭니다. 또한 메모리 부족 오류가 발생합니다. 어떻게이 문제를 해결할 수 있습니까? – SBylemans

+0

DataOutputStream.writeUTF()와 그 반대를 사용하십시오. – EJP