2012-12-19 14 views
12

Ho UrlClassLoader figlio-primo per caricare dinamicamente il file jar. Quindi eseguo una riflessione per richiamare un metodo all'interno del file jar caricato. Una volta finito, preferisco scaricare il classloader. Quindi provo a fare un codice di stress test per assicurarmi che il mio codice funzioni senza intoppi. Fondamentalmente, quello che cerco di fare è caricare e scaricare jar all'interno dell'istruzione looping. Qui è il mio codice:JDK1.7 Perdita di memoria ClassLoader

for (int i = 0; i < 1000; i++) { 
     //Just to show the progress 
     System.out.println("LOAD NUMBER : " + i); 

     ChildFirstURLClassLoader classLoader = null; 
     try { 
      File file = new File("C:\\library.jar"); 
      String classToLoad = "com.test.MyClass"; 
      URL jarUrl = new URL("file:" + file.getAbsolutePath()); 

      classLoader = new ChildFirstURLClassLoader(new URL[] {jarUrl}, null); 
      Class<?> loadedClass = classLoader.loadClass(classToLoad); 
      Method method = loadedClass.getDeclaredMethod("execute", 
        new Class[] {}); 

      ClassLoader currCl= Thread.currentThread().getContextClassLoader(); 
      Thread.currentThread().setContextClassLoader(classLoader); 
      method.invoke(null); 
      Thread.currentThread().setContextClassLoader(currCl); 

      method = null; 
      loadedClass = null; 
     } finally { 
      if (classLoader != null) { 
       classLoader.close(); 
       classLoader = null; 
      } 
     } 
    } 

quando sono in esecuzione di questo codice sotto JDK1.6, senza classLoader.close(); dichiarazione, che il codice funziona perfettamente. Ma quando mi trasformo in JDK1.7, a volte ho l'errore java.lang.OutOfMemoryError: PermGen space. Sfortunatamente si verifica in modo incoerente.

+2

Si potrebbe provare a impostare la massima perm gen per vedere se questo accade più spesso con valori più bassi. È anche possibile verificare che il massimo sia lo stesso per Java 6 quando ciò non avviene. –

+3

Cosa fa la tua classe com.test.MyClass? C'è stato un cambiamento in Java 7 in modo tale che i metodi finalizzati in sospeso possono impedire alla classe di essere deallocata, forse questo è il problema che stai vedendo qui. Crea un dump di heap su OutOfMemory, caricalo su MemoryAnalyzer (o uno strumento simile), elenca i programmi di caricamento classe e cerca riferimenti ad essi. – mihi

+0

Grazie a Peter e Mihi, ho cercato di aumentare il permgen massimo, ma è sempre lo stesso. In Java 6, eseguo solo con 64m permgen space senza problemi. In realtà, com.test.MyClass sta eseguendo una query nel database utilizzando Spring JDBC. Ho già analizzato il mio heap dump e ho visto che non ci sono riferimenti forti nel classloader. Ringrazia tutti. – user1915918

risposta

2

Il modo più semplice per confermare da dove proviene la perdita è utilizzare un profiler per monitorare l'utilizzo della memoria. Prova JProfiler o VisualVM. Ti consentirà di individuare la posizione esatta della perdita e fornirti anche indizi su come e se è possibile risolverlo.