La mia applicazione registra l'utilizzo di determinati oggetti - la mia configurazione utilizza AspectJ per identificare i contesti che mi interessano e registra questi usi. Successivamente caricherò i file di log per l'analisi, ma per motivi di efficienza è utile sapere quando un oggetto non è più raggiungibile.Registrazione quando gli oggetti sono dati inutili raccolti
Il mio attuale approccio consiste nel registrare gli oggetti a cui sono interessato con un 'garbage logger', che crea quindi un oggetto 'saver' contenente il codice hash dell'identità dell'oggetto e lo memorizza in una mappa hash debole. L'idea è che quando l'oggetto viene raccolto, l'oggetto saver verrà rimosso dalla mappa hash debole e raccolto, eseguendo così il codice per registrare il codice hash dell'identità dell'oggetto raccolto. Io uso un thread e una coda separati per evitare di causare un collo di bottiglia nel garbage collector. Ecco il codice spazzatura logger:
public class GarbageLogger extends Thread {
private final Map<Object,Saver> Savings =
Collections.synchronizedMap(new WeakIdentityHashMap<Object,Saver>());
private final ConcurrentLinkedQueue<Integer> clearTheseHash =
new ConcurrentLinkedQueue<Integer>();
public void register(Object o){
Savings.put(o,new Saver(System.identityHashCode(o));
}
private class Saver{
public Saver(int hash){ this.hash=hash;}
private final int hash;
@Override
public void finalize(){
clearTheseHash.add(hash);
}
}
@Override
public void run(){
while(running){
if((clearTheseHash.peek() !=null)){
int h = clearTheseHash.poll();
log(h);
}
else sleep(100);
}
}
// logging and start/end code omitted
}
mio problema è che questo sembra molto contorta e, perché deboli mappa di hash non necessariamente cancellare le sue voci a meno che non è necessario spazio, potrebbe essere in attesa di un lungo periodo di tempo dopo l'oggetto è raccolto prima di registrarlo. Fondamentalmente, sto cercando un modo migliore per raggiungere questo obiettivo.
Nota: sto monitorando oggetti arbitrari e non ho alcun controllo sulla loro creazione, quindi non posso sovrascrivere i loro metodi di finalizzazione.
Sembra che quello che vuoi veramente sia una [coda di riferimento] (http://stackoverflow.com/a/14450693/869736). –
Quindi sostituirò WeakIdentityHashMap e ConcurrentLinkedQueue con un ReferenceQueue, ma sarebbe comunque necessario il thread GarbageLogger per inserire i riferimenti raccolti e registrarli? – selig
Questo è corretto. –