2016-09-06 2 views
0

로 표시됩니다. 소개

안녕하십니까. 나는 지금 약 2 주 동안 문제가 발생했고 이 왜 일어나는지 알 수없는 것처럼 보입니다. 그래서, 어떤 경우입니까? 내 프로젝트 Hashet 최대 크기는 961

거친 설명은 내가 저장 파일의 모든 영역에 파일을 읽고,이를 확인하는 마인 크래프트 도구를 쓰고 있어요. 플레이어가 배치 한 블록이있는 경우 해당 블록이 들어있는 청크는 안전하다고 표시되고 나중에 삭제되지 않습니다. 그렇지 않으면 청크는 몇 가지 대기열이 생성되기 때문에 대기열에 포함 된 프로세스가 완료된 후 삭제됩니다. 그것은 내가 사용하고있는 HashSet의에서 961 개 요소에 도달 할 때까지

문제는

이 프로그램은 잘 실행 것으로 보인다. 해시 세트에는 문자열이 들어있어 청크가 안전하다고 표시되었는지 확인하는 데 사용됩니다. 961 개의 요소가 있으면 메모리가 부족한 것처럼 더 이상 추가 할 수없는 것처럼 동작합니다. 사실이 아니더라도 2GB의 메모리를 할당했지만 여전히 아무것도 아닙니다. 나는 많은 다른 매개 변수로 여러 번 테스트했지만 그것은 961

오류

HashSet의에 요소를 추가하는 동안, 그것은 961에서 최대 상판 및 하지보다 더 이상 추가하지에서 꼭대기 그. 2GB의 RAM으로 테스트되었지만 운이 없음.

코드

여기 내 코드입니다. 그것을 압도하지 마라, 그것은 꽤 간단하다.

Options 클래스는 작업 할 수있는 몇 가지 옵션을로드하는 클래스입니다. 언급 할만한 가치가 없습니다.

Main 클래스 :

public class Main { 

    Options options = new Options(); 
    Deleter deleter; 

    public Main() { 
     deleter = new Deleter(this); 
    } 

    public static void main(String[] args) { 
     Main main = new Main(); 
     try { 
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
      System.out.print("Load world?"); 
      System.out.println("(Y for yes/Q for quit): "); 
      String s = br.readLine(); 
      while (!s.equalsIgnoreCase("Q")) { 
       if (s.equalsIgnoreCase("Y")) { 
        main.deleter.loadWorld(); 
        System.out.println("Enqueue?"); 
        System.out.println("(E for enqueue/Q for quit): "); 
        s = br.readLine(); 
        while (s.equalsIgnoreCase("E")) { // While user wants to enqueue 
         main.deleter.enqueue(); 
         System.out.println("Delete?"); 
         System.out.println("(E for enqueue/D for delete/Q for quit)"); 
         s = br.readLine(); 
        } 
        if (s.equalsIgnoreCase("D")) { 
         main.deleter.delete(); 
        } 

       } 
      } // If input == Quit, do this 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

왜 961 천장의 문제가 일어나고

public class Deleter { 

    private Options options; 
    private ArrayList<File> files = new ArrayList<>(1000); 
    private HashSet<String> safeChunks = new HashSet<>(20000); 
    private ArrayList<Integer> blockIDsList = new ArrayList<>(100); 
    private int totalChunksEnqueued = 0; 
    private int chunksEnqueued = 0; 

    public Deleter(Main main) { 
     this.options = main.getOptions(); 
     totalChunksEnqueued = 0; 
    } 

    public void loadWorld() { 
     String folderName = options.getSaveFolderFile().getParentFile().getName(); 
     System.out.println("--------Loading world: " + folderName + "--------"); 
     File filesTemp[] = options.getSaveFolderFile().listFiles(); 
     for (File file : filesTemp) { 
      if (file.getName().endsWith("mca")) { 
//    RegionFile regionFile = new RegionFile(file); 
       files.add(file); 
      } 
     } 
     System.out.println("--------World loaded successfully--------"); 
    } 

    public void enqueue() { 
     System.out.println("--------Enqueuing--------"); 
     chunksEnqueued = 0; 
     try { 
      options.reloadConfig(); 
     } catch (FileNotFoundException e2) { 
      e2.printStackTrace(); 
     } 
     int totalFiles = options.getSaveFolderFile().listFiles().length; 
     int counter = 0; 

     //START 

     //Actual enqueuing takes place here 
     for (File file : files) { 
      counter++; 
      System.out.println("Progress: " + counter + "/" + totalFiles + ". Total chunks enqueued: " + totalChunksEnqueued); 
      RegionFile regionFile = new RegionFile(file); 
      for (int chunkX = 0; chunkX < 32; chunkX++) { 
       for (int chunkZ = 0; chunkZ < 32; chunkZ++) { 
        DataInputStream chunk = regionFile.getChunkDataInputStream(chunkX, chunkZ); 
        if (regionFile.hasChunk(chunkX, chunkZ)) { 

         try { 
          Tag root = Tag.readNamedTag(chunk); 

          CompoundTag level = root.getCompound("Level"); 
          ListTag sections = level.getList("Sections"); 

          for (int i = 0; i < sections.size(); i++) { 
           CompoundTag section = (CompoundTag) sections.get(i); 
           byte[] blocksArray = section.getByteArray("Blocks"); 
           byte[] addsArray = section.getByteArray("Add"); 
           byte Y = section.getByte("Y"); 

           boolean worked = false; 
           for (int y = 0; y < 16; y++) { 
            for (int z = 0; z < 16; z++) { 
             for (int x = 0; x < 16; x++) { 
//           int realX = regionX * 32 + chunkX * 16 + x; 
              int realY = Y * 16 + y; 
//           int realZ = regionZ * 32 + chunkZ * 16 + z; 
              if (realY >= minY && realY <= maxY) { 
               // Copied from Chunk Format page. 
               int BlockPos = (y * 16 * 16) + (z * 16) + (x); 
               byte BlockID_a = blocksArray[BlockPos]; 
               short BlockID = BlockID_a; 
               if (addsArray.length != 0) { 
                byte BlockID_b = nibble4(addsArray, BlockPos); 
                BlockID = (short) (BlockID_a + (BlockID_b << 8)); 
               } 
               for (int block : blockIDs) { 
                if (BlockID == block) { 
                 worked = true; 
                 markSafeChunks(regionFile, chunkX, chunkZ, radius); 
                 break; 
                } 

               } 
              } 
              if (worked) 
               break; 

             } 
             if (worked) 
              break; 
            } 
            if (worked) 
             break; 
           } 
           if (worked) 
            break; 
          } 

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

      try { 
       regionFile.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

     } 

     //END 

     System.out.println("Chunks enqueued this time: " + chunksEnqueued); 
     System.out.println("Total chunks enqueued: " + totalChunksEnqueued); 
     System.out.println("--------Finished enqueueing--------"); 
    } 

    public void delete() { 
     System.out.println("--------Deleting--------"); 
     try { 
      options.reloadConfig(); 
     } catch (FileNotFoundException e2) { 
      e2.printStackTrace(); 
     } 
     int totalFiles = options.getSaveFolderFile().listFiles().length; 
     //START 

     // Deletion takes place here 

     for (File file : files) { 
      RegionFile regionFile = new RegionFile(file); 
      // You are now in a region file. 
      counter++; 
      System.out.println("Progress: " + counter + "/" + totalFiles); 
      for (int chunkX = 0; chunkX < 32; chunkX++) { 
       for (int chunkZ = 0; chunkZ < 32; chunkZ++) { 
        if (!safeChunks.contains("" + chunkX + "_" + chunkZ) && regionFile.hasChunk(chunkX, chunkZ)) { 
         try { 
          regionFile.deleteChunk(chunkX, chunkZ); 
          chunksDeleted++; 
         } catch (IOException e1) { 
          e1.printStackTrace(); 
          return; 
         } 

        } 
       } 
      } 
      try { 
       regionFile.close(); 
      } catch (IOException e2) { 
       e2.printStackTrace(); 
      } 
     } 

     //END 

     System.out.println("Chunks deleted: " + chunksDeleted); 
     System.out.println("--------Finished enqueueing--------"); 

    } 

    private synchronized void markSafeChunks(RegionFile regionFile, int chunkX, int chunkZ, int radius) { 
     if (radius == 0) 
      safeChunks.add("" + chunkX + "_" + chunkZ); 
     else 
      for (int surX = chunkX - radius; surX <= chunkX + radius; surX++) { 
       for (int surZ = chunkZ - radius; surZ <= chunkZ + radius; surZ++) { 
        boolean b = surX > chunkX/32 && surX < chunkX/32 + 32; 
        b &= surZ > chunkZ/32 && surZ < chunkZ/32 + 32; 
        if (b && regionFile.hasChunk(surX, surZ) && !safeChunks.contains("" + surX + "_" + surZ)) { 
         safeChunks.add("" + surX + "_" + surZ); 
         chunksEnqueued++; 
         totalChunksEnqueued++; 
        } 

       } 
      } 
    } 

어떤 아이디어 Deleter 클래스?

+0

디버깅에 도움이되는 질문 ('**이 코드가 작동하지 않는 이유는 무엇입니까?** ')에는 원하는 동작, 특정 문제 또는 오류 및 문제 자체 **를 재현하는 데 필요한 가장 짧은 코드가 포함되어야합니다. ** 명확한 문제 성명 **이없는 질문은 다른 독자에게 유용하지 않습니다. 참조 : [최소한의 완전하고 검증 가능한 예제를 만드는 방법] (http://stackoverflow.com/help/mcve). – Biffen

+0

코드에 HashSet에 대한 참조가 없습니다. 또한 HashSet에 이미 961 개 요소 뒤에 추가하려는 값이 포함되어 있는지 확인하십시오. – 11thdimension

+0

@ 11thdimension ** Deleter 클래스의 HashSet에 대한 참조가 ** 실제로 ** 추가 ** ** 전에 HashSet에 값이 포함되어 있는지 확인합니다 ** – Lazini

답변

0

HashSet의 용량은 항상 2의 거듭 제곱이며 10 억 개가 넘는 요소를 추가 할 수 있습니다. 그러나 중복을 무시하므로 요소를 계속 추가하지만 해당 요소가 이미 세트에 있으면 크기가 증가하지 않습니다.

OutOfMemoryError을받지 못하면 메모리가 부족하지 않습니다.

BTW 여러 루프를 벗어나는 간단한 방법은 라벨을 사용하는 것입니다.

outer: 
while (something) 
    while (nested) 
     while (moreNested) { 
     // 
     if (condition) 
      break outer; 
     } 

즉, working 변수가 필요하지 않습니다.

+1

코드 제안에 대해 감사드립니다. 나는 이미 그것을 사용하고있다! 보이는 것처럼 ** 실제로 실수로 동일한 키를 반복적으로 추가했습니다. *** 삭제 해 주셔서 감사합니다. *** – Lazini

관련 문제