L'applicazione CDI e gli ambiti dipendenti possono cospirare per avere un impatto sulla raccolta dei rifiuti?
-
28-10-2019 - |
Domanda
Stiamo iniziando a sperimentare l'implementazione dei nostri servizi di backend utilizzando CDI. Lo scenario è questo:
EJB con @startup viene avviato quando l'orecchio viene distribuito. Un fagiolo copicato viene iniettato su questo:
@ApplicationScoped
public class JobPlatform {
private PooledExecutor threadHolder;
@Inject @Any
private Instance<Worker> workerSource;
...
Il fagiolo ha anche un metodo Observer, che, quando si osserva un evento, ottiene un fagiolo dei lavoratori dall'istanza dei lavoratori e lo mette sul threadpool, dove alla fine corre al completamento.
Tutti lavorano bene. Tuttavia ... abbiamo iniziato a vedere problemi di raccolta dei rifiuti. Un istogramma di heap JMAP mostra che ci sono molti di questi lavoratori in giro, raccolti non-garbage.
Crediamo che ciò dipenda dalla combinazione di Scoping CDI. La pagina API per @dipendant (http://docs.jboss.org/cdi/api/1.0-Sp1/javax/enterprise/context/dipendent.html) rafforza più chiaramente ciò che è nei documenti:
- Un'istanza di un fagiolo con portata @dipendente iniettata in un campo, il costruttore di fagioli o il metodo di inizializzatore è un oggetto dipendente del fagiolo o dell'istanza della classe dei componenti di java ee in cui è stato iniettato.
- Un'istanza di un fagiolo con portata @dipendente iniettata in un metodo produttore è un oggetto dipendente dell'istanza del metodo del produttore che viene prodotto.
- Un'istanza di un fagiolo con portata @dipendente ottenuta mediante invocazione diretta di un'istanza è un oggetto dipendente dell'istanza di istanza.
Quindi, seguendo questo:
- Il bean workersource è vincolato alla piattaforma e quindi ha una durata delle applicazioni
- Qualsiasi fagiolo di lavoratore recuperato utilizzando tale istanza è vincolato ad essa e quindi hanno una durata delle applicazioni
- Poiché il fagiolo del contesto di applicazioni (la mia conoscenza della terminologia diventa un po 'confusa qui) ha ancora un riferimento ai fagioli dei lavoratori, non sono distrutti/immondizia raccolta
Qualcuno che usa CDI è d'accordo con questo? Hai sperimentato questa mancanza di garbage collection e, in tal caso, puoi suggerire delle soluzioni alternative?
I lavoratori non possono essere applicati, tuttavia la piattaforma deve essere. Se dovessimo creare un Custom WorkerCope (uh ohhh ...) e annotare ogni classe di lavoratori con esso, sarebbe sufficiente per separare la dipendenza tra lavoratore e fonte di istanza?
Ci sono anche alcuni suggerimenti a È possibile distruggere un ambito CDI? Che guarderò, ma volevo un backup sul fatto che lo scoping sembrasse un motivo valido.
Spero che tu possa aiutare, grazie.
Soluzione
La tua comprensione è corretta. Questa è stata una svista nelle specifiche e qualcosa che sarà fissato in CDI 1.1. Instance
Può avere una perdita di memoria proprio come hai descritto quando usato in un ambito di lunga durata come SessionScoped
o ApplicationScoped
. Quello che dovrai fare è ottenere una presa del Contextual
o Bean
per caso e distruggerlo in questo modo.
Per quello che stai facendo e per evitare la perdita di memoria, è meglio utilizzare i metodi BeanManager per creare istanze (in questo modo avrai anche una maniglia sul Bean
e può distruggerlo) invece di Instance
.
Altri suggerimenti
Durante la ricerca nell'implementazione della soluzione consigliata di Jason, ho trovato altre risorse relative al problema:
Il problema: https://issues.jboss.org/browse/cdi-139 e https://issues.jboss.org/browse/weld-920
Esempio di operazioni di BeanManager:https://issues.jboss.org/browse/cdi-14?focusedcommentId=12601344 &page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-12601344
oorg.jboss.seam.faces.util.BeanManagerUtils