2015-02-09 5 views
21

Gestisco una libreria che avvia un thread daemon per eseguire il lavoro in background. Nelle normali applicazioni Java e Android, questo thread viene avviato una volta e viene eseguito per tutta la durata del processo. Non esce mai e va bene.Esci da un thread dopo lo scaricamento delle app

Quando la mia libreria è inclusa in un contenitore un'applicazione che supporta lo scarico applicazione (come Tomcat), l'applicazione non sborra. Il mio thread in esecuzione contiene forti riferimenti alla propria classe e impedisce che l'intera applicazione venga scaricata. Gli utenti della mia libreria non possono scambiare la propria app a caldo senza perdite di memoria ogni volta.

Qual è il modo migliore per ottenere segnalata quando il contenitore applicazione vuole scaricare la mia biblioteca?

Si tratta di una piccola libreria senza alcuna dipendenza da API contenitore di applicazioni. Non sa quale contenitore di applicazioni è in esecuzione e non vuole farlo!

Il fatto che questa libreria inizi una discussione è un dettaglio di implementazione. Gli utenti finali della libreria non devono sapere che è in corso l'avvio di un thread e che non è responsabilità chiuderlo.

+0

C'è qualche altro oggetto che è possibile rilevare il garbage collection di? – immibis

+0

Non sono sicuro di aver compreso correttamente il problema, ma forse questo: https://weblogs.java.net/blog/kcpeppe/archive/2011/09/29/mysterious-phantom-reference sarà utile? –

risposta

6

Non è possibile determinare se la lib è stata utilizzata dall'applicazione negli ultimi x minuti/secondi e arrestare il thread in caso contrario? Riavvia al prossimo utilizzo? Il java.util.concurrent.ThreadPoolExecutor funziona in questo modo.

+0

Questo può funzionare. È spiacevole arrestare lo sfratto del processo, ma non è impraticabile. –

2

Questo è un problema interessante. Un'idea da provare:

Il thread daemon utilizza riferimenti deboli alla libreria. Quindi fare in modo che alcuni oggetti guard della libreria abbiano il metodo finalize() per rimuovere il thread del daemon.

Qualcosa del genere funzionerebbe?

+0

Sfortunatamente, la libreria non contiene riferimenti all'applicazione, quindi quell'approccio non funzionerà per me. –

+0

Jesse - Ah - Penso di aver causato qualche confusione con il mio uso del termine "applicazione". Intendevo la tua biblioteca. Sono abbastanza sicuro che la strategia che ho descritto funzionerà. Cambierò il testo della mia risposta per renderlo più chiaro. –

+0

Il garbage collector non è in grado di segnalare che l'app è stata scaricata. I valori sono raccolti troppo presto (prima di scaricare); le lezioni sono troppo tardi (dopo che il mio thread è uscito). –

7

La soluzione migliore è fornire un metodo per ripulire la libreria. L'utente finale dovrà chiamarlo (presumibilmente in base alla gestione del ciclo di vita dell'applicazione nel contenitore). È anche possibile fornire un valore Listener per quei casi quando viene utilizzato in un contenitore di servlet compatibile (ad esempio, Tomcat), ma l'utente finale deve comunque essere consapevole e inserire il descrittore nel file web.xml.

L'unica altra alternativa è che il vostro utente finale sta per avere per creare un listener che riesce a ottenere il filo di morire. Ho dovuto farlo in diverse occasioni e non è carino. Di solito comporta l'uso del riflesso per afferrare il filo e ucciderlo. Naturalmente, l'eccezione ThreadDeath è gestita da alcune librerie e i thread si rifiutano di morire. Ciò richiede quindi un uso più significativo della riflessione per ripulire il caos.

Gli utenti finali stanno molto meglio se gli dai un modo semplice per ripulire la libreria. Fa schifo sapere che devono conoscere i dettagli della tua implementazione, ma lo fanno già perché stai mantenendo l'app da scaricare.

+0

Preferirei che i futuri utenti della mia biblioteca non debbano scoprire che le loro app non stanno scaricando e quindi devono cercare la correzione. Molto meglio se funziona! –

+0

@JesseWilson Sono completamente d'accordo! Tuttavia, la realtà è che non esiste un modo automatico e affidabile per rilevare che si sta eseguendo in una webapp e tanto meno quando l'app viene scaricata. È meglio rendere più semplice per l'utente gestire questo problema piuttosto che lasciarlo come un problema doloroso. – Rob

+2

Forse potresti offrire questa API (per la pulizia immediata da parte dei consumatori informati), * e * fornendo un qualche tipo di approccio basato sul timeout automatico come suggerisce @Cfx per (consumatori non informati). – rewbs

1

È possibile utilizzare ComponentCallbacks2.onTrimMemory(). Questo viene chiamato quando il sistema ha poche risorse e l'app in background dovrebbe rilasciare risorse.

La mia esperienza è che quando onTrimMemory (TRIM_MEMORY_COMPLETE) è chiamato quindi l'applicazione è in procinto di essere ucciso.

+0

Sono interessato in particolare ai casi in cui il processo continua a funzionare, ma l'applicazione al suo interno viene scaricata. ComponentCallbacks non aiuterà perché Android non implementa le classi di scarico. –

Problemi correlati