2013-03-25 14 views
12

Si dice che il metodo substring nella classe String causi una perdita di memoria. È vero? Come? Qual è un'alternativa per questo?
Particolarmente in cerca di risposta,
Quali sono tutte le altre cose che possono causare perdite di memoria in java? Questo mi aiuterà a fare attenzione durante la codifica.nella classe String causa la perdita di memoria

+0

Sei un po 'vago, non credi? Che cosa te lo fa pensare? –

+1

La modalità di implementazione della sottostringa è stata modificata di recente. – Thilo

+1

Quando dici "Si dice che ...", dovresti includere un riferimento a tale affermazione nella tua domanda ... –

risposta

25

Nelle versioni precedenti di JDK, l'implementazione del metodo substring creava un nuovo oggetto String mantenendo un riferimento all'intero array di caratteri, per evitare di copiarlo. In tal modo potresti inavvertitamente mantenere un riferimento a un array di caratteri molto grande con una sola stringa di caratteri. Here's an example di un bug che questo potrebbe indurre.

Questo metodo è stato modificato e questa "perdita" non esiste più.

Se si desidera utilizzare un vecchio JDK (che è più vecchio di OpenJDK 7, Update 6) e si desidera avere le stringhe minimi dopo substring, utilizzare il costruttore di prendere un'altra stringa:

String s2 = new String(s1.substring(0,1)); 

quanto riguarda la tua seconda domanda, riguardante "altre cose che possono causare perdite di memoria in java", è impossibile rispondere in modo costruttivo. Non ci sono in lib di java standard molte istanze di casi in cui è possibile mantenere facilmente riferimenti nascosti agli oggetti. Nel caso generale, presta attenzione a tutti i riferimenti che crei, i problemi più frequenti che si verificano probabilmente in raccolte non pulite o risorse esterne (file, transazioni di database, widget nativi, ecc.).

+2

Potresti essere più specifico con le "versioni precedenti" in cui esiste un problema ? –

+1

"Problema" è un po 'duro. L'implementazione è cambiata con 7u6, quindi qualsiasi cosa prima sarebbe "interessata". – Thilo

+0

quale versione di java? – AmitG

8

La sottostringa delle stringhe può comportare il mantenimento di più memoria di quanto ci si potrebbe aspettare. Come tale non è una perdita di memoria in quanto questa memoria può essere ripristinata normalmente.

La soluzione più semplice è utilizzare una versione recente di Java 7, che non lo fa. Poiché questa è l'unica versione liberamente supportata da Oracle, dovresti considerare comunque di farlo.

Come tale è stato "corretto" nell'aggiornamento di Java 7. 5. IMHO non è tanto una correzione quanto una semplificazione dell'implementazione. Prendere una copia di ogni sottostringa richiede molto più lavoro ed è probabile che consuma più memoria, ma significa che c'è una cosa in meno di cui preoccuparsi.

Quali sono tutte le altre cose che possono causare perdite di memoria in java?

Qualsiasi oggetto può essere ripulito in quanto tale non è possibile creare una perdita di memoria nel senso C/C++ del termine. Quello che puoi fare è tenere gli oggetti in modo errato. Un esempio comune di questo è dimenticare di chiudere risorse come la risorsa JDBC. Ciò può farti conservare la memoria in modi che non ti aspetti.

11

Il metodo substring() non alloca un nuovo array di caratteri per una String, bensì semplicemente produce un String con una finestra sul char esistente. Questa è una impementazione di un modello di peso mosca ed è stata considerata un'ottimizzazione.

Quindi, se ho un enorme String (array di caratteri) e quindi creo una sottostringa, anche se io raccolgo la stringa originale, il char array originale rimane (nonostante il fatto che pensi di avere una sottostringa di, per esempio, 2 caratteri).Questo problema si incontra spesso quando (ad esempio) l'analisi di un enorme flusso di dati in ingresso (forse un file XML) e l'estrazione di una piccola quantità di testo tramite substring()

Utilizzando la String(String str) costruttore apparentemente ridondante (un String costruttore di prendere una String!) risolve questo dato che assegna un nuovo array di caratteri (potenzialmente più piccolo), consentendo di raccogliere l'originale.

Nota questo comportamento è stato modificato a partire da Java 7u6.

5

Nell'oggetto String, quando si chiama substring, la proprietà value viene condivisa tra le due stringhe.

Quindi, se si ottiene una sottostringa da una stringa grande e la si conserva per un lungo periodo, la stringa grande non verrà raccolta. Potrebbe causare una perdita di memoria, in realtà.

+1

Si noti che questo non è più il caso della recente JVM Oracle. – Thilo

+0

Hai ragione: avrei dovuto dirlo. Grazie per la precisione! –