Pagina 1 di 6 1 2 3 ... ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 57
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    177

    [java] [OutOfMemoryError] Come evitare il sovraccarico della memoria

    L'applicazione che ho creato genera OutOfMemoryError, lavora con migliaia di file .pdf con dimensioni molto grandi, devo svuotare la memoria in qualche modo o diminuire il sovraccarico. L'errore completo è:
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.io.ByteArrayOutputStream.write(Unknown Source)
    at com.itextpdf.text.pdf.RandomAccessFileOrArray.Inpu tStreamToArray(Rand
    omAccessFileOrArray.java:209)
    at com.itextpdf.text.pdf.RandomAccessFileOrArray.<ini t>(RandomAccessFile
    OrArray.java:199)
    at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.j ava:237)
    at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.j ava:248)
    at code.PDF.<init>(PDF.java:23)
    at code.Start.main(Start.java:89)

    Devo usare periodicamente un comando particolare?
    Su questo link trovate la classe PDF da cui parte l'errore, se volete altre parti del codice posso postarle.
    Teo

  2. #2
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    177
    Posto anche il codice di Starter dove si propaga l'errore
    codice:
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class Start {
    	/**
    	 * @param args
    	 */
    	public static void main(String [] args) throws IOException {
    		if(args.length==3){
    			Gestione database;
    			System.out.println(">   Inizio caricamento");
    			if(args[2].equals("0")){
    				database=new Gestione(args[0]);
    				database.svuotaDatabase();
    				database.chiudiConnessione();
    				System.out.println(">>>   Database svuotato");
    			}
    			try{
    				File f = new File (args[1]);
    				File[] files = f.listFiles();
    				for (int i = 0; i < files.length; i++){
    					if(files[i].isFile()){
    						if(files[i].getName().toLowerCase().endsWith(".pdf")){
    							FileInputStream fis=new FileInputStream(files[i]);
    	riga 89 ----> PDF gt=new PDF(fis, files[i].getName());
    							database=new Gestione(args[0]);
    							database.caricaPDF(gt);
    							database.chiudiConnessione();
    						}
    					}
    				}
    			}catch(NullPointerException e){//errore da gestire meglio
    				System.out.println("<<La directory della cartella e' errata>>");
    				e.printStackTrace();
    			}
    			System.out.println(">   Fine caricamento");
    		}else
    			System.out.println("<<Nessun argomento valido inserito>>");
    	}
    }
    la riga segnata è quella in cui si propaga l'errore di esubero. Io penso sia un errore del garbage collector, magari gli impedisco di prendere dei dati che non mi servono più.
    Teo

  3. #3
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    devi chiudere gli stream fis ad ogni ciclo (dopo database.chiudiconnessione()) e piu in generale tutto cio che al suo interno usa risorse unmanaged (files, database, ecc.). va chiuso il prima possibile perche su quelle risorse (le unmanaged) il GC non passa mai

  4. #4
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    177
    ho messo un fis.close() dopo database.chiudiConnessione() è ho fatto la stessa cosa con il fis passato alla classe pdf dentro la stessa classe. Dentro la classe GestioneDatabase erano già gestite la chiusura dello statement e del connection. ora vediamo come procede e posto i risultati.
    Teo

  5. #5
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    Non serve che chiudi il fis anche nella classe PDF, anzi è sbagliato: e se lo stream ti servisse per una operazione successiva? alla classe questo non importa ( e non puo saperlo) percio è bene che se gli arriva uno stream in input si limiti ad usarlo senza chiuderlo. Peraltro quando proverai a richiuderlo nella starter "credo" ti solleverà un eccezione.
    Poi un altra cosa: se apri e chiudi il db ad ogni ciclo sottoponi il programma (e potenzialmente anche la GC) ad un sovraccarico inutile. Aprilo prima e chiudilo solo dopo il FOR.

  6. #6
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    177
    ok, grazie dei consigli, ora li provo e vedo come va.
    Teo

  7. #7
    Utente di HTML.it L'avatar di Alex'87
    Registrato dal
    Aug 2001
    residenza
    Verona
    Messaggi
    5,802

    Re: [java] [OutOfMemoryError] Come evitare il sovraccarico della memoria

    Originariamente inviato da Vixer
    L'applicazione che ho creato genera OutOfMemoryError, lavora con migliaia di file .pdf con dimensioni molto grandi, devo svuotare la memoria in qualche modo o diminuire il sovraccarico
    Aumenta l'heap
    SpringSource Certified Spring Professional | Pivotal Certified Enterprise Integration Specialist
    Di questo libro e degli altri (blog personale di recensioni libri) | ​NO M.P. TECNICI

  8. #8
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    177

    Re: Re: [java] [OutOfMemoryError] Come evitare il sovraccarico della memoria

    Originariamente inviato da Alex'87
    Aumenta l'heap
    Questa procedura è la mia ultima sponda, purtroppo il codice non deve girare sul mio pc
    Teo

  9. #9
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    una considerazione:
    come ti hanno già detto non apire e chiudere la connessione al database ad ogni ciclo.
    Seconda cosa, se i file sono molto grandi, caricare prima il file in memoria e poi passarlo al database non è corretto. Cosa fa la funzione che passa i dati nel db?
    Penso che puoi bypassare una copia (se vedo il codice mi rendo conto meglio)
    RTFM Read That F*** Manual!!!

  10. #10
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    177
    Originariamente inviato da valia
    una considerazione:
    come ti hanno già detto non apire e chiudere la connessione al database ad ogni ciclo.
    Seconda cosa, se i file sono molto grandi, caricare prima il file in memoria e poi passarlo al database non è corretto. Cosa fa la funzione che passa i dati nel db?
    Penso che puoi bypassare una copia (se vedo il codice mi rendo conto meglio)
    purtroppo non posso baipassare la copia. il file pdf viene copiato pagina per pagina dentro il database. In alcuni casi io devo sbloccare il pdf ed anche il testo della pagina. La classe di utilità pdf la trovate lincata nel post se volete darle un occhiata.
    Vi inserisco la classe gestione cosi potete capire meglio il funzionamento e aiutarmi a capire come risolvere il tutto. Le modifiche fatte alla classe Start sono quelle segnalate da rsdpzedrsdpzed
    codice:
    public class Gestione {
    	
    	private DatabaseBridge database;
    	private int protette=0,vuote=0;
    	
    	public Gestione(String linkDatabase){
    		database=new DatabaseBridge(linkDatabase);
    	}
    	public void caricaPDF(PDF pdf) throws IOException{
    		String nome=pdf.getNome();
    		if(!isProcessato(nome)){
    			if(!pdf.isProtetto()){
    				database.queryAggiornamento("INSERT INTO files (NomeFile,Protetto,Processato) VALUES ('"+nome+"',0,1)");
    				caricaTesto(pdf,getIdPDF(nome));
    			}else{
    				database.queryAggiornamento("INSERT INTO files (NomeFile,Protetto,Processato) VALUES ('"+nome+"',1,1)");
    			}
    			System.out.println("> Caricato nel database "+nome);
    			System.out.println("-Protetto= "+pdf.isProtetto());
    			System.out.println("-Pagine-> protette= "+protette+" vuote= "+vuote+" non inserite= "+database.getNonInserite());
    		}
    		else
    			System.out.println("> Preesistente nel database "+nome);
    		
    	}
    	private void caricaTesto(PDF pdf, int idPDF) throws IOException {
    		for(int i=1;i<=pdf.getNumeroPg();i++){
    			String parole=pdf.getTestoPagina(i);
    			if(parole!=null)
    				if(paginaConCaratteri(parole))
    					database.queryAggiornamento("INSERT INTO testo (IDFile,Pagina,Testo) VALUES ("+idPDF+","+i+",'"+parole+"')");
    				else
    					vuote++;
    			else
    				protette++;
    		}
    	}
    	private boolean paginaConCaratteri(String parole) {
    		StringTokenizer st=new StringTokenizer(parole);
    		while(st.hasMoreTokens())
    			return st.nextToken()!=" ";
    		return false;
    	}
    	private int getIdPDF(String nome) {
    		return database.queryRicercaInt("SELECT ID FROM files WHERE files.NomeFile='"+nome+"'");
    	}
    	private boolean isProcessato(String nome) {
    		return database.queryRicercaInt("SELECT Processato FROM files WHERE files.NomeFile='"+nome+"'")==1;
    	}
    	public void chiudiConnessione() {
    		database.chiudi();
    	}
    	public void svuotaDatabase(){
    		database.queryAggiornamento("DELETE FROM testo");
    		database.queryAggiornamento("DELETE FROM files");
    	}
    }
    Teo

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.