2017-07-14 3 views
0

A écrit ce programme pour décompresser et extraire des fichiers vers amazon S3. J'ai rencontré un bug Java. Choses que j'ai essayées: Augmenter l'espace de tas sur les arguments. Modifier la taille en octets à [1024 * 1024]Java Heap Space - ByteArrayOutputStream.Write

Obtention d'un bogue sur outputStream.write (buffer, 0, len). La taille de l'octet est initialisée à 1024. Ce code fonctionne pour la plupart des fichiers jusqu'à la taille 166 mb jusqu'à présent. Java taille du tas est à Xmx4096m Java version 1.7

Méthode de décompressé:

public static void extractObjects(byte[] buffer, AmazonS3 s3Client, ZipInputStream zis, ZipEntry entry) 
       throws IOException { 
      try { 
       while (entry != null) { 
        String fileName = entry.getName(); 
        if (fileName == "lib") { 
         fileName = entry.getName(); 
        } 
        boolean containsBackup = fileName.contains(doc.getDesiredFile()); 

        if (containsBackup == true) { 
         System.out.println("A back up file was found"); 
         formatSchemaName(); 
         System.out.println("Extracting :" + app.getCurrentPacsId()); 
         log.info("Extracting " + app.getCurrentPacsId() + ", compressed: " + entry.getCompressedSize() + " bytes, extracted: " + entry.getSize() + " bytes"); 
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
         int len; 

while ((len = zis.read(buffer)) >= 0) 
         { 
          outputStream.write(buffer, 0, len); 
         } 
         InputStream is = new ByteArrayInputStream(outputStream.toByteArray()); 
         meta = new ObjectMetadata(); 
         meta.setContentLength(outputStream.size()); 
         fileName = app.getCurrentPacsId(); 
         runDataConversion(is,s3Client,fileName); 

         is.close(); 
         outputStream.close(); 
         System.out.println("Unzip complete");    
        } 
        else{ 
         System.out.println("No back up found"); 
        } 
        entry = zis.getNextEntry(); 
       } 
       zis.closeEntry(); 
       zis.close(); 
      } catch (AmazonServiceException e) { 
       log.error(e); 
      } catch (SdkClientException e) { 
       log.error(e); 
      } 
     } 

Erreur

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Arrays.java:2271) 
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118) 
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93) 
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153) 
    at com.amazonaws.image.DataMiner.extractObjects(DataMiner.java:112) 
    at com.amazonaws.image.DataMiner.downloadBucket(DataMiner.java:76) 
    at com.amazonaws.image.DataMiner.obtainConnection(DataMiner.java:58) 
    at com.amazonaws.image.DataMiner.main(DataMiner.java:208) 

Répondre

0

-vous vraiment besoin le ByteArrayOutputStream? . Il semble que vous l'utilisiez uniquement pour obtenir la taille non compressée, mais vous l'avez déjà à entry.getSize(). Pourriez-vous passer le ZipInputStream directement à runDataConversion(...)? En ce qui concerne le problème que vous observez, lorsque vous atteignez ces niveaux de consommation de mémoire, il n'est pas rare de rencontrer des problèmes de fragmentation. En d'autres termes, bien que vous ayez plus de mémoire libre que vous le souhaitez, vous n'avez pas de bloc contigu aussi grand et l'allocation échoue donc. Un garbage collector de compactage devrait prendre soin de cela, mais tous les éboueurs de la JVM ne se compactent pas, IIRC.

+0

J'ai trouvé qu'en augmentant l'espace de tas Java dans la commande d'exécution par rapport à la console java, le problème a été résolu. Mais je pense que votre droit encore, je pense que le tableau d'octets est inutile dans le remplissage de la mémoire inutile gaspillée. Je reviendrai sur ce code mais actuellement il fonctionne jusqu'à des fichiers de taille 1gb mais je parie que cela pourrait être beaucoup mieux. –