It is said that substring
method in String class causes memory leak. Is it true? How? What is an alternative for it?
Especially looking for answer,
What are all other things which can causes of memory leak in java? This will help me to take care while coding.
相关问题
- Delete Messages from a Topic in Apache Kafka
- Jackson Deserialization not calling deserialize on
- How to maintain order of key-value in DataFrame sa
- StackExchange API - Deserialize Date in JSON Respo
- Difference between Types.INTEGER and Types.NULL in
In past versions of the JDK, the implementation of the
substring
method would build a newString
object keeping a reference to the whole char array, to avoid copying it. You could thus inadvertently keep a reference to a very big character array with just a one character string. Here's an example of a bug this could induce.This method has now been changed and this "leak" doesn't exist anymore.
If you want to use an old JDK (that is older than OpenJDK 7, Update 6) and you want to have minimal strings after
substring
, use the constructor taking another string :As for your second question, regarding " other things which can causes of memory leak in java", it's impossible to answer in a constructive way. There aren't in java standard libs many instances of cases where you could so easily keep hidden references to objects. In the general case, pay attention to all the references you build, the most frequent problems probably arising in uncleaned collections or external resources (files, database transactions, native widgets, etc.).
The
substring()
method doesn't allocate a new character array for aString
, but rather simply produces aString
with a window onto the existing char array. This is an impementation of a flyweight pattern and was regarded as an optimisation.So if I have a huge
String
(char array) and then create a substring, even if I garbage collect the original string, the original char array remains (despite the fact that you think you have a substring of, say, 2 chars). This problem is often encountered when (say) parsing a huge stream of input data (perhaps an XML file) and extracting a small amount of text viasubstring()
Using the seemingly redundant
String(String str)
constructor (aString
constructor taking aString
!) resolves this since it allocates a new (potentially smaller) char array, allowing the original to be garbage collected.Note this behaviour has changed as of Java 7u6.
In the String object, when you call
substring
, thevalue
property is shared between the two strings.So, if you get a substring from a big string and keep it for a long time, the big string won't be garbage collected. It could result in a memory leak, actually.
String substring can result in retaining more memory than you might expect. As such it's not a memory leak as this memory can be recovered normally.
The simplest solution is to use a recent version of Java 7, which doesn't do this. As this is the only freely supported version from Oracle, you should consider doing this anyway.
As such it was "fixed" in Java 7 update 5. IMHO it is not so much a fix as a simplification of the implementation. Taking a copy of every substring takes much more work and is likely to consume more memory, but it does mean there is one less thing to worry about.
Any object can be cleaned up as such it's not possible to create a memory leak in the C/C++ sense of the term. What you can do is hold onto objects incorrectly. A common example of this is forgetting to close resources like JDBC resource. This can cause you to retain memory in ways you don't expect.