2011-12-05 6 views
15

Stiamo iniziando a sperimentare con l'implementazione dei nostri servizi di back-end utilizzando CDI. Lo scenario è questo:Gli ambiti di applicazione e dipendente CDI possono cospirare per influire sulla garbage collection?

EJB con @Startup viene avviato quando EAR distribuito. Un fagiolo ApplicationScoped 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 lavoratore dal workerSource grado e mette sul ThreadPool, dove alla fine corre a completamento.

Tutto funzionante. 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, non raccolti.

Riteniamo che ciò dipenda dalla combinazione dell'oscilloscopio CDI. La pagina API per @Dependant (http://docs.jboss.org/cdi/api/1.0-SP1/javax/enterprise/context/Dependent.html) rafforza più chiaramente cosa c'è nei documenti:

  • Un esempio di un bean con scope @Dependent iniettato in un campo, costruttore di fagiolo o metodo inizializzatore è un oggetto dipendente della bean o classe di classe componente EE Java in cui è stata iniettata.
  • Un'istanza di un bean con scope @Dependent iniettato in un metodo produttore è un oggetto dipendente dell'istanza del bean del metodo produttore che viene prodotta.
  • Un'istanza di un bean con scope @Dependent ottenuto mediante invocazione diretta di un'istanza è un oggetto dipendente dell'istanza di Instance.

Quindi, seguendo questo:

  • Il fagiolo workerSource è destinato ad JobPlatform, e quindi ha una durata ApplicationScoped
  • Qualsiasi fagioli lavoratori recuperati utilizzando tale istanza sono tenuti ad esso, e pertanto ha una durata ApplicationScoped
  • Poiché il beanstore del contesto ApplicationScoped (la mia conoscenza della terminologia diventa un po 'confuso qui) ha ancora un ference to worker beans, non vengono distrutti/spazzatura raccolta

Chiunque usa CDI è d'accordo con questo? Hai sperimentato questa mancanza di raccolta dei rifiuti e, in tal caso, puoi suggerire soluzioni alternative?

I lavoratori non possono essere ApplicationScoped, tuttavia la piattaforma deve essere. Se dovessimo creare un WorkerScope personalizzato (uh ohhh ...) e annotare ogni classe worker con esso, sarebbe sufficiente separare la dipendenza tra worker e l'origine dell'istanza?

Ci sono anche alcuni suggerimenti a Is it possible to destroy a CDI scope? che vedrò, ma volevo un po 'di backup sul fatto che scoping assomiglia a un motivo valido.

Spero che tu possa aiutare, grazie.

risposta

9

La tua comprensione è corretta. Questa è stata una svista nelle specifiche e qualcosa che verrà risolto in CDI 1.1. Instance può avere una perdita di memoria proprio come hai descritto quando utilizzato in un ambito di esecuzione lungo come SessionScoped o ApplicationScoped.Quello che devi fare è prendere il numero Contextual o Bean per l'istanza e distruggerlo in questo modo.

Per quello che si sta facendo, e per evitare la perdita di memoria è meglio usare i metodi BeanManager per creare istanze (in questo modo si avrà anche un handle sullo Bean e si può distruggere) invece di Instance.

+0

Grazie mille per essere tornato così velocemente - è bello sapere che è un riconoscimento problema. Darà il via al progresso ora! Saluti! –

+0

Per chiunque altro stia leggendo qui, si noti che Weld 1.1 implementa CDI 1.0, non CDI 1.1. –

+0

Corretto Craig. Weld 2.0 implementa CDI 1.1 (sì, so che la numerazione è strana). Se vuoi vedere come sarà il CDI 1.1, prova Weld 2.0. Credo che esistano build speciali di JBoss AS7 che includono Weld 2.0. – LightGuard