FileInputStream (Read) - Não existem recursos de sistema suficientes

7 respostas
G

Estou com um problema chato com o FileInputStream.
Tenho um algoritmo de criptografia onde antes da operação, eu preciso colocar o arquivo no FileInputStream e no final dela utilizo o FileOutputStream.
Se o arquivo possuir menos de uns 80MB, a operação flui normalmente quando eu coloco o FileInputStream.read().
Agora passou disso, esse read dá problema. Diz que não existem recursos suficientes e fecha tudo.... sendo que eu faço essa mesma operação utilizando STRING ou File como parâmetro (seria um New FileInputStream())....

A parte relevante do código é essa daqui e o erro é exatamente no read. Alguém faz idéia do que pode ser?

public Boolean criptografa(String origem) {
        
        try {
            
            File file = new File(origem);
            if(file.isFile()) {
                
                //Lê o arquivo a ser criptografado
                FileInputStream fis = new FileInputStream(file);
                byte [] texto = new byte[fis.available()];
                
                fis.read(texto); //Aqui está dando PROBLEMA

7 Respostas

G

O erro é esse aqui:

Error: Não existem recursos de sistema suficientes para concluir o serviço solicitado java.lang.OutOfMemoryError: Java heap space at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at com.sun.crypto.provider.SunJCE_ab.b(DashoA13*..) at com.sun.crypto.provider.PBEWithMD5AndDESCipher.engineDoFinal(DashoA13*..) at javax.crypto.Cipher.doFinal(DashoA13*..) at br.gov.inpi.prgguardtec.security.FileCrypt.criptografa(FileCrypt.java:78) at br.gov.inpi.prgguardtec.web.RegistroBean.armazenarMidia(RegistroBean.java:214) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.apache.el.parser.AstValue.invoke(AstValue.java:262) at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278) at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) at org.primefaces.component.fileupload.FileUpload.broadcast(FileUpload.java:279) at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:752) at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:928) at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:508) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:77) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at br.gov.inpi.prgguardtec.web.filter.LoginFilter.doFilter(LoginFilter.java:30) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)

E

Gabriel, evite carregar o arquivo inteiro na memória para criptografá-lo. Não sei que algoritmo você usa, mas normalmente nunca é necessário carregar mais que 1 KB de dados de cada vez para criptografar alguma coisa.

Isto aqui:

FileInputStream fis = new FileInputStream(file);  
                byte [] texto = new byte[fis.available()];

vai dar sempre problemas se seu arquivo for só um pouquinho grande (80 MB é muita coisa para você carregar).

E

Hum, você está usando PBEWithMD5AndDESCipher. Realmente você não precisa carregar tudo.

J

Tinha respondido a mesma coisa do colega acima (demorei pra responder)…

E

Uma forma bem boboca de criptografar alguma coisa é encapsular o seu FileInputStream em um CipherInputStream, passando seu Cipher como parâmetro.
Isso fará que cada “read” retorne os dados já criptografados do arquivo.
Outra forma é encapsular seu FileOutputStream em um CipherOutputStream .
Cada “write” irá gravar os dados criptografados no disco.

E

http://www.exampledepot.com/egs/javax.crypto/DesFile.html

G

Exemplo perfeito.
Funcionou redondinho!!!
Ajustei o meu código, usei um byte[] de 4kb mesmo… A memória ficou bem tranquila…
Vou testar com um byte[] maior pra ver se fica mais rápido sem consumir muita memória.
Obrigado brother!!!

Criado 15 de agosto de 2012
Ultima resposta 16 de ago. de 2012
Respostas 7
Participantes 3