Questa pagina spiega come ridurre in modo proattivo la memoria utilizzata all'interno dell'app. Per informazioni su come il sistema operativo Android gestisce la memoria, consulta la panoramica della gestione della memoria.
La memoria ad accesso casuale (RAM) è una risorsa preziosa per qualsiasi ambiente di sviluppo software ed è ancora più preziosa per un sistema operativo mobile in cui la memoria fisica è spesso limitata. Sebbene sia Android Runtime (ART) sia la macchina virtuale Dalvik eseguano la garbage collection di routine, ciò non significa che tu possa ignorare quando e dove la tua app alloca e rilascia memoria. Devi comunque
evitare di introdurre perdite di memoria, in genere causate dalla conservazione
di riferimenti a oggetti in variabili membro statiche, e rilasciare gli oggetti Reference
al momento opportuno, come definito dai callback del ciclo di vita.
Riduci il footprint del codice e delle risorse della tua app
Alcune risorse e librerie all'interno del codice possono consumare memoria senza che tu te ne accorga. Le dimensioni complessive dell'app, incluse le librerie di terze parti o le risorse incorporate, possono influire sulla quantità di memoria consumata dall'app. Puoi migliorare il consumo di memoria della tua app rimuovendo componenti, risorse e librerie ridondanti, non necessari o eccessivi dal codice.
Ridurre le dimensioni complessive dell'app abilitando R8
Il codice dell'applicazione compilato è una parte attiva dell'impronta della memoria runtime. Ogni classe, metodo, dipendenza della libreria e costante stringa deve essere caricata nella RAM durante l'esecuzione. Più grande è la base di codice compilata, maggiore è la RAM fisica richiesta dalla tua app.
Puoi utilizzare R8 per ridurre il footprint della memoria della tua app. Sebbene R8 sia tradizionalmente noto per la riduzione delle dimensioni degli APK, ha un impatto diretto e positivo sulla memoria di runtime (RAM). R8 analizza il bytecode della tua app per rimuovere il codice inutilizzato, unire le classi ridondanti, inserire i metodi inline e minimizzare gli identificatori. Caricando meno bytecode compilati dall'APK nella RAM, si riduce il footprint della memoria di base complessivo dell'app. Inoltre, la minimizzazione dei nomi di campi, metodi e classi in identificatori più brevi riduce direttamente il sovraccarico della RAM. Ottimizzazioni come l'unione delle classi e l'inlining esteso dei metodi sostituiscono anche le costose ricerche e i costosi pattern di allocazione in fase di runtime, con conseguente ottimizzazione dell'heap e della memoria dello stack.
Informazioni sulle regole di conservazione
Le regole Keep sono istruzioni di configurazione che indicano a R8 quali parti del codice conservare durante l'ottimizzazione, impedendo la rimozione o la riduzione del codice su cui si basa la tua app. Per saperne di più, consulta la Panoramica delle regole di conservazione.
Le regole di conservazione scritte male impediscono a R8 di ottimizzare grandi porzioni della tua base di codice. Evita regole di conservazione troppo generiche e segui queste best practice:
- Regole globali da evitare:
-dontoptimize: disattiva completamente l'ottimizzazione per l'intera app, con conseguenti eseguibili più grandi e più lenti.-dontshrink: impedisce la rimozione di codice e risorse inutilizzati.-dontobfuscate: impedisce la minificazione dei nomi, perdendo preziosi risparmi di memoria (soprattutto nelle app di grandi dimensioni).
Evita i caratteri jolly a livello di pacchetto: regole generali come
-keep class com.example.package.** { *; }forzano R8 a conservare ogni classe, campo e metodo nel pacchetto. In questo modo, R8 non potrà rimuovere, ottimizzare o comprimere il codice nel pacchetto.Utilizza il file di configurazione R8 predefinito: utilizza sempre
proguard-android-optimize.txt.
Per saperne di più sulla scrittura delle regole di conservazione, consulta la Panoramica delle regole di conservazione. Per i pattern specifici da utilizzare ed evitare, consulta Best practice per le regole di conservazione.
R8 Configuration Analyzer fornisce informazioni sulla configurazione di R8 e sull'impatto di ogni regola di conservazione sull'app. Per saperne di più su come identificare le regole che bloccano l'ottimizzazione, consulta R8 Configuration Analyzer.
Fai attenzione all'utilizzo di librerie esterne
Il codice della libreria esterna spesso non è scritto per gli ambienti mobile e può essere inefficiente per l'utilizzo su un client mobile. Quando utilizzi una libreria esterna, potresti doverla ottimizzare per i dispositivi mobili. Pianifica questo lavoro in anticipo e analizza la libreria in termini di dimensioni del codice e footprint della RAM prima di utilizzarla.
Anche alcune librerie ottimizzate per il mobile possono causare problemi a causa di implementazioni diverse. Ad esempio, una libreria potrebbe utilizzare protobuf lite, mentre un'altra utilizza micro protobuf, il che comporta due diverse implementazioni di protobuf nella tua app. Ciò può accadere con diverse implementazioni di logging, analisi, framework di caricamento delle immagini, memorizzazione nella cache e molte altre cose che non ti aspetti.
Sebbene l'ottimizzazione dell'app tramite R8 possa rimuovere il codice inutilizzato dalle dipendenze, la sua efficacia è spesso limitata dalla configurazione interna della libreria. Ad esempio, regole di conservazione generali o l'utilizzo della reflection all'interno di una libreria possono impedire a R8 di ridurre il codice, con conseguente aumento dell'utilizzo di memoria. Per strategie sulla selezione di librerie efficienti, consulta Scegliere le librerie con saggezza.
Evita di utilizzare una libreria condivisa per una o due funzionalità su decine. Non inserire una grande quantità di codice e overhead che non utilizzi. Quando valuti se utilizzare una libreria, cerca un'implementazione che corrisponda esattamente a ciò che ti serve. In caso contrario, potresti decidere di creare una tua implementazione.
Utilizzare Hilt o Dagger 2 per l'inserimento delle dipendenze
I framework di inserimento delle dipendenze possono semplificare il codice che scrivi e fornire un ambiente adattivo utile per i test e altre modifiche alla configurazione.
Se intendi utilizzare un framework di iniezione delle dipendenze nella tua app, valuta la possibilità di utilizzare Hilt o Dagger. Hilt è una libreria di inserimento delle dipendenze per Android che viene eseguita sopra Dagger. Dagger non utilizza la reflection per scansionare il codice della tua app. Puoi utilizzare l'implementazione statica in fase di compilazione di Dagger nelle app per Android senza costi in tempo di esecuzione o memoria utilizzata inutili.
Altri framework di inserimento delle dipendenze che utilizzano la reflection inizializzano i processi scansionando il codice alla ricerca di annotazioni. Questo processo può richiedere molti più cicli di CPU e RAM e può causare un ritardo notevole all'avvio dell'app.
Quando utilizzi l'inserimento delle dipendenze, fai attenzione a evitare perdite di memoria assicurandoti che gli oggetti siano inclusi nell'ambito appropriato. La conservazione degli oggetti più a lungo del necessario collegandoli al ciclo di vita errato può causare perdite di memoria. Per saperne di più, consulta le indicazioni su come evitare perdite di memoria con oggetti con ambito.
Carica le immagini in modo intenzionale
Le bitmap grafiche sono in genere gli oggetti comuni più grandi che risiedono nella memoria della tua app. Anche se lavori con file compressi come i JPEG, il file deve essere decompresso in una bitmap non compressa per essere visualizzato sullo schermo. Un piccolo file immagine compresso può espandersi in una bitmap molto grande.
Ad esempio, la maggior parte delle bitmap utilizza la configurazione ARGB_8888, il che significa che ogni pixel richiede 4 byte di memoria: uno per il rosso, uno per il verde, uno per il blu e uno per l'alfa (trasparenza). Se hai un JPEG da 100 KB e lo visualizzi in una visualizzazione di 1000 × 1000 pixel, la bitmap richiederà 4 byte per ciascuno di questi 1.000.000 di pixel, per un totale di 4 MB di memoria.
Esistono diversi accorgimenti che puoi adottare per ottimizzare l'utilizzo delle immagini. Ad esempio, l'utilizzo di librerie di caricamento delle immagini può aiutarti a liberare memoria quando non è necessaria. Per informazioni su come gestire le immagini in modo efficiente, consulta Ottimizzazione delle immagini bitmap.
Monitorare la memoria disponibile e la memoria utilizzata
Prima di poter risolvere i problemi di memoria utilizzata della tua app, devi individuarli. Il profiler di memoria di Android Studio ti aiuta a trovare e diagnosticare i problemi di memoria nei seguenti modi:
- Scopri come la tua app alloca la memoria nel tempo. Il Profiler di memoria mostra un grafico in tempo reale della quantità di memoria utilizzata dall'app, il numero di oggetti Java allocati e quando si verifica la garbage collection.
- Avvia eventi di garbage collection e acquisisci un'istantanea dell'heap Java durante l'esecuzione dell'app.
- Registra le allocazioni di memoria della tua app, esamina tutti gli oggetti allocati, visualizza l'analisi dello stack per ogni allocazione e vai al codice corrispondente nell'editor di Android Studio.
Il Profiler di memoria si integra anche con la libreria di rilevamento delle perdite di memoria LeakCanary. Utilizzando LeakCanary, puoi spostare l'analisi delle perdite di memoria dal dispositivo di test alla macchina di sviluppo, il che può accelerare notevolmente il workflow. Per saperne di più, consulta le note di rilascio di Android Studio.
Esistono altri strumenti che puoi utilizzare per diagnosticare i problemi di memoria in base ai dati degli utenti che eseguono la tua app di produzione:
- Utilizza Android vitals per monitorare gli eventi di interruzione per memoria insufficiente (LMK).
- Utilizza Profiling Manager per monitorare gli errori di esaurimento della memoria, nonché il comportamento anomalo delle app che potrebbe essere causato da perdite di memoria.
Rilasciare la memoria in risposta agli eventi
Android può recuperare memoria dalla tua app o arrestarla completamente, se necessario,
per liberare memoria per le attività critiche, come spiegato in Panoramica della gestione
della memoria. Per bilanciare ulteriormente la memoria di sistema ed evitare che il sistema
debba interrompere il processo dell'app, puoi implementare l'interfaccia ComponentCallbacks2
nelle classi Activity. Il metodo di callback onTrimMemory() fornito notifica alla tua app gli eventi relativi al ciclo di vita o alla memoria che rappresentano una buona opportunità per la tua app di ridurre volontariamente la memoria utilizzata.
Liberare memoria può ridurre la frequenza con cui l'app viene chiusa dal
low-memory killer.
L'implementazione di onTrimMemory() deve concentrarsi esclusivamente sugli eventi
TRIM_MEMORY_UI_HIDDEN e TRIM_MEMORY_BACKGROUND. A partire da Android 14, il sistema non invia più notifiche per le altre costanti legacy. Queste costanti sono state ritirate ufficialmente in Android 15.)
TRIM_MEMORY_UI_HIDDEN: questo segnale indica che l'interfaccia utente della tua app non è più visibile all'utente. Questa transizione offre l'opportunità di rilasciare allocazioni di memoria sostanziali legate strettamente all'interfaccia utente, come bitmap, buffer di riproduzione video o risorse di animazione complesse.TRIM_MEMORY_BACKGROUND: questo segnale indica che il processo risiede in background ed è ora un candidato per la terminazione per soddisfare le esigenze di memoria globali del sistema. Per estendere la durata in cui il processo rimane nello stato memorizzato nella cache e ridurre il numero di avvii a freddo dell'app, devi rilasciare in modo aggressivo tutte le risorse che possono essere facilmente ricostruite una volta che l'utente riprende la sessione.
Questo esempio di codice mostra come implementare il callback onTrimMemory() per rispondere
a diversi eventi correlati alla memoria:
Kotlin
import android.content.ComponentCallbacks2
// Other import statements.
class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
// Other activity code.
/**
* Release memory when the UI becomes hidden or when system resources become low.
* @param level the memory-related event that is raised.
*/
override fun onTrimMemory(level: Int) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// Release memory related to UI elements, such as bitmap caches.
}
if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Release memory related to background processing, such as by
// closing a database connection.
}
}
}
Java
import android.content.ComponentCallbacks2;
// Other import statements.
public class MainActivity extends AppCompatActivity
implements ComponentCallbacks2 {
// Other activity code.
/**
* Release memory when the UI becomes hidden or when system resources become low.
* @param level the memory-related event that is raised.
*/
public void onTrimMemory(int level) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// Release memory related to UI elements, such as bitmap caches.
}
if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Release memory related to background processing, such as by
// closing a database connection.
}
}
}
Controllare la quantità di memoria necessaria
Per consentire l'esecuzione di più processi, Android imposta un limite rigido per le dimensioni dell'heap
assegnato a ogni app. Il limite esatto delle dimensioni dell'heap varia a seconda dei dispositivi in base
alla quantità di RAM disponibile complessivamente sul dispositivo. Se la tua app raggiunge la capacità dell'heap e tenta di allocare più memoria, il sistema genera un errore OutOfMemoryError.
Per evitare di esaurire la memoria, puoi eseguire query sul sistema per determinare la quantità di spazio heap disponibile sul dispositivo corrente. Puoi richiedere questa cifra al sistema chiamando il numero getMemoryInfo(). Restituisce un oggetto
ActivityManager.MemoryInfo che fornisce informazioni sullo stato attuale della memoria del dispositivo, inclusi memoria disponibile, memoria totale e soglia di memoria, ovvero il livello di memoria in corrispondenza del quale il sistema inizia a interrompere i processi. L'oggetto ActivityManager.MemoryInfo espone anche
lowMemory, un semplice valore booleano che indica se la memoria del dispositivo
è quasi esaurita.
Il seguente snippet di codice di esempio mostra come utilizzare il metodo getMemoryInfo()
nella tua app.
Kotlin
fun doSomethingMemoryIntensive() {
// Before doing something that requires a lot of memory,
// check whether the device is in a low memory state.
if (!getAvailableMemory().lowMemory) {
// Do memory intensive work.
}
}
// Get a MemoryInfo object for the device's current memory status.
private fun getAvailableMemory(): ActivityManager.MemoryInfo {
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
return ActivityManager.MemoryInfo().also { memoryInfo ->
activityManager.getMemoryInfo(memoryInfo)
}
}
Java
public void doSomethingMemoryIntensive() {
// Before doing something that requires a lot of memory,
// check whether the device is in a low memory state.
ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();
if (!memoryInfo.lowMemory) {
// Do memory intensive work.
}
}
// Get a MemoryInfo object for the device's current memory status.
private ActivityManager.MemoryInfo getAvailableMemory() {
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
Monitorare le chiusure per memoria insufficiente
Le interruzioni per memoria insufficiente (LMK) visibili agli utenti si verificano quando la memoria di sistema è
criticamente insufficiente. Quando la memoria è insufficiente, il
lmkd (daemon di terminazione per memoria insufficiente)
termina i processi in base al loro oom_adj_score. Le app memorizzate nella cache o che eseguono un servizio senza UI associata (ad esempio un job) hanno i punteggi più alti e vengono terminate per prime. Se la memoria rimane molto bassa, il
daemon è costretto a recuperare memoria dai processi con un valore oom_adj_score pari a 0.
Poiché questo punteggio è riservato alle app visibili, la loro chiusura comporta un'uscita immediata e non controllata dal processo. Per l'utente finale, sembra che l'app
si sia arrestata in modo anomalo, spesso bypassando i meccanismi standard di salvataggio dello stato del ciclo di vita e
comportando la perdita dei progressi dell'utente.
L'interruzione dei processi in primo piano è un obiettivo primario di Android Vitals perché rappresentano un proxy ad alta fedeltà per la gestione errata della memoria. Sebbene qualsiasi tasso LMK superiore all'1% indichi la necessità critica di un'azione immediata, un tasso basso non è necessariamente un indicatore di integrità. Una bassa percentuale di interruzioni per memoria insufficiente (LMK) percepite dall'utente potrebbe significare che il daemon LMK interrompe spesso i processi in background, il che peggiora le prestazioni dell'"avvio tiepido" e la fluidità del multitasking. Pertanto, ti consigliamo di rispettare le best practice per la memoria indipendentemente dal tuo punteggio LMK attuale, per garantire stabilità e stato del dispositivo a lungo termine.
Utilizzare ProfilingManager per monitorare i problemi di memoria
La piattaforma Android fornisce
ProfilingManager, un'API
di osservabilità avanzata che ti consente di acquisire i dati degli utenti in produzione in base
ai trigger che imposti. In questo modo puoi identificare i problemi di memoria difficili da riprodurre.
Due nuovi trigger introdotti con Android 17 sono particolarmente utili per individuare problemi di memoria:
TRIGGER_TYPE_OOMindica che l'app ha generato unOutOfMemoryError. Si attiva la successiva volta che l'app viene avviata dopo l'arresto anomalo, quando l'app si registra per i trigger di profilazione.TRIGGER_TYPE_ANOMALYsi attiva quando il sistema rileva un comportamento anomalo dell'app. Tra le altre cose, può essere attivato da un utilizzo eccessivo della memoria utilizzata. Viene attivato dopo che l'app ha mostrato un utilizzo eccessivo della memoria utilizzata e prima che il sistema intraprenda qualsiasi azione per arrestare il processo incriminato. Ad esempio, se l'app supera i limiti di memoria introdotti in Android 17,TRIGGER_TYPE_ANOMALYsi attiva prima che il sistema chiuda l'app.
Per ulteriori informazioni sull'utilizzo di ProfilingManager per registrare e recuperare in modo programmatico i trigger, consulta la documentazione relativa alla profilazione basata sui trigger.
Puoi anche utilizzare la profilazione basata sulle app per definire manualmente i punti di inizio e fine della traccia. Ti consigliamo di farlo per acquisire manualmente dump dell'heap o profili heap nelle aree in cui sospetti che possano esserci perdite di memoria o un utilizzo eccessivo della memoria utilizzata.
Utilizza costrutti di codice più efficienti in termini di memoria
Alcune funzionalità Android, classi Java e costrutti di codice utilizzano più memoria di altri. Puoi ridurre al minimo la quantità di memoria utilizzata dalla tua app scegliendo alternative più efficienti nel codice.
Utilizzare i servizi con parsimonia
Ti consigliamo vivamente di non lasciare i servizi in esecuzione quando non è necessario. Lasciare in esecuzione servizi non necessari è uno dei peggiori errori di gestione della memoria che un'app per Android possa commettere. Se la tua app ha bisogno di un servizio per funzionare in background, non lasciarlo in esecuzione a meno che non debba eseguire un'attività. Interrompi il servizio al termine dell'attività. In caso contrario, potresti causare una perdita di memoria.
Quando avvii un servizio, il sistema preferisce mantenere in esecuzione il processo per quel servizio. Questo comportamento rende i processi di servizio molto costosi perché la RAM utilizzata da un servizio rimane non disponibile per altri processi. In questo modo si riduce il numero di processi memorizzati nella cache che il sistema può conservare nella cache LRU, rendendo il cambio di app meno efficiente. Può persino causare un'attività eccessiva nel sistema quando la memoria è limitata e il sistema non riesce a mantenere un numero sufficiente di processi per ospitare tutti i servizi attualmente in esecuzione.
In generale, evita di utilizzare servizi persistenti a causa delle continue richieste che
pongono sulla memoria disponibile. Ti consigliamo invece di utilizzare un'implementazione
alternativa, ad esempio WorkManager.
Per ulteriori informazioni su come utilizzare WorkManager per pianificare i processi in background, consulta Persistent work.
Utilizzare container di dati ottimizzati
Alcune delle classi fornite dal linguaggio di programmazione non sono ottimizzate per
l'utilizzo su dispositivi mobili. Ad esempio, l'implementazione generica
HashMap può essere inefficiente in termini di memoria
perché richiede un oggetto di voce separato per ogni mappatura.
Il framework Android include diversi contenitori di dati ottimizzati, tra cui
SparseArray,
SparseBooleanArray e
LongSparseArray. Ad esempio, le classi SparseArray sono più efficienti perché evitano la necessità del sistema di eseguire l'autoboxing della chiave e a volte del valore, il che crea un altro oggetto o due per voce.
Se necessario, puoi sempre passare agli array non elaborati per una struttura dei dati semplice.
Fai attenzione alle astrazioni del codice
Gli sviluppatori spesso utilizzano le astrazioni come buona pratica di programmazione perché possono migliorare la flessibilità e la manutenzione del codice. Tuttavia, le astrazioni in genere richiedono l'esecuzione di più codice. Come descritto in Ridurre l'impronta del codice e delle risorse dell'app, una codebase compilata più grande aumenta direttamente la RAM fisica richiesta dall'app. Se le tue astrazioni non sono significativamente vantaggiose, evitale.
Utilizzare protobuf leggeri per i dati serializzati
I buffer di protocollo (protobuf) sono un meccanismo estensibile, indipendente dal linguaggio e dalla piattaforma, progettato da Google per la serializzazione dei dati strutturati, simile a XML, ma più piccolo, più veloce e più semplice. Se utilizzi protobuf per i tuoi dati, utilizza sempre protobuf lite nel codice lato client. I protobuf regolari generano codice estremamente dettagliato, il che aumenta l'impronta del codice dell'app nella RAM (vedi Gestire e ottimizzare l'impronta del codice dell'app) e contribuisce all'aumento delle dimensioni dell'APK.
Per saperne di più, consulta il file README di protobuf.
Fai attenzione alle perdite di memoria
Una gestione impropria dei riferimenti può causare perdite di memoria in cui gli oggetti sopravvivono alla loro durata utile, impedendo al garbage collector di recuperare la memoria dell'oggetto perso. Per evitare perdite di memoria, implementa un design consapevole del ciclo di vita.
Per saperne di più, consulta la sezione Perdite di memoria.
Evitare la saturazione della memoria
Gli eventi di Garbage Collection non influiscono sulle prestazioni della tua app. Tuttavia, molti eventi di Garbage Collection che si verificano in un breve periodo di tempo possono scaricare rapidamente la batteria, oltre ad aumentare leggermente il tempo di configurazione dei frame a causa delle interazioni necessarie tra il Garbage Collector e i thread dell'app. Più tempo il sistema dedica alla garbage collection, più velocemente si scarica la batteria.
Spesso, la saturazione della memoria può causare un numero elevato di eventi di garbage collection. In pratica, il churn della memoria descrive il numero di oggetti temporanei allocati che si verificano in un determinato periodo di tempo.
Ad esempio, potresti allocare più oggetti temporanei all'interno di un ciclo for.
In alternativa, puoi creare nuovi oggetti Paint o Bitmap all'interno della funzione onDraw() di una vista. In entrambi i casi, l'app crea rapidamente molti oggetti a
volume elevato. Questi possono consumare rapidamente tutta la memoria disponibile nella generazione
giovane, forzando l'esecuzione di un evento di garbage collection.
Utilizza Memory Profiler per trovare i punti del codice in cui il churn della memoria è elevato prima di poterli correggere.
Dopo aver identificato le aree problematiche nel codice, prova a ridurre il numero di allocazioni all'interno delle aree critiche per le prestazioni. Valuta la possibilità di spostare gli elementi fuori dai loop interni o di inserirli in una struttura di allocazione basata su factory.
Puoi anche valutare se i pool di oggetti sono utili per il caso d'uso. Con un pool di oggetti, anziché rilasciare un'istanza di oggetto sul pavimento, la rilasci in un pool dopo che non è più necessaria. La prossima volta che è necessaria un'istanza oggetto di quel tipo, puoi acquisirla dal pool anziché allocarla.
Valuta attentamente il rendimento per determinare se un pool di oggetti è adatto in una determinata situazione. Esistono casi in cui i pool di oggetti potrebbero peggiorare le prestazioni. Anche se i pool evitano le allocazioni, introducono altri sovraccarichi. Ad esempio, la manutenzione del pool di solito comporta la sincronizzazione, che ha un overhead non trascurabile. Inoltre, la cancellazione dell'istanza dell'oggetto in pool per evitare perdite di memoria durante il rilascio e la sua inizializzazione durante l'acquisizione può comportare un overhead diverso da zero.
Se nel pool vengono trattenute più istanze di oggetti del necessario, viene sovraccaricata anche la garbage collection. Sebbene i pool di oggetti riducano il numero di chiamate di garbage collection, finiscono per aumentare la quantità di lavoro necessaria per ogni chiamata, in quanto è proporzionale al numero di byte attivi (raggiungibili).