Come posso evitare OutOfMemoryErrors quando si utilizza DiskFileItem di Commons FileUpload per caricare i file di grandi dimensioni?
-
18-09-2019 - |
Domanda
Io sono sempre OutOfMemoryErrors durante il caricamento di grandi dimensioni (> 300 MB) file una servlet che utilizza Commons FileUpload 1.2.1. Sembra strano, perché l'intero punto di utilizzo DiskFileItem è quello di prevenire la (possibilmente grande) file di risiedere in memoria. Sto usando la dimensione predefinita Soglia di 10KB, in modo che è tutto ciò che dovrebbe sempre essere caricata nel mucchio, giusto? Ecco l'analisi dello stack parziale:
java.lang.OutOfMemoryError
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:177)
at org.apache.commons.fileupload.disk.DiskFileItem.get(DiskFileItem.java:334)
at org.springframework.web.multipart.commons.CommonsMultipartFile.getBytes(CommonsMultipartFile.java:114)
Perché succede questo? C'è una certa configurazione che mi manca? Eventuali suggerimenti / trucchi per evitare questa situazione oltre ad aumentare la mia dimensione heap ?
Io davvero non avrei dovuto aumentare il mio mucchio, perché in teoria più che dovrebbe essere caricato in memoria da questa operazione è un po 'più di 10KB. In più, il mio mucchio max (-Xmx) è già impostata per 1 GB, che dovrebbe essere un sacco.
Soluzione
Quando si tratta di upload di file, soprattutto quelli grandi, si dovrebbe elaborare i file come flussi che si trangugiare in un buffer di medie dimensioni in memoria e copiare direttamente nel file di output. Il modo sbagliato per farlo è quello di inalare il tutto in memoria prima di scrivere fuori.
Il doc su beni comuni-upload menziona, appena sotto la metà, come " elaborare un caricamento di file". Se vi ricordate di copiare dal InputStream al OutputStream in blocchi di dimensioni ragionevoli (per esempio, 1 MB), si dovrebbe avere alcun problema.
Altri suggerimenti
Mentre la risposta di Carl Smotricz è probabilmente meglio nel caso generale, l'eccezione che si ottiene è un bug JVM che viene segnalato qui:
http://bugs.sun.com/bugdatabase/view_bug.do? bug_id = 6478546