简体   繁体   English

Java中子字符串方法的内存泄漏

[英]Memory leak of the substring method in java

I am searching about the memory leak that was caused by subString() method in java. 我正在搜索由java中的subString()方法引起的内存泄漏。 I have read few articles in the internet and got some knowledge but I was ended up with a little confusion. 我在互联网上读过几篇文章并获得了一些知识,但最后却有些困惑。 One article has mentioned "substring method inside String class, calls String (int offset, int count, char value []) constructor to create new String object. What is interesting here is, value[], which is the same character array used to represent original string". 一篇文章提到“ String类内部的子字符串方法,调用String(int偏移量,int计数,char值[])构造函数来创建新的String对象。这里有趣的是value [],它与用于代表原始字符串”。 This is clear to me. 这对我来说很清楚。

It also mentioned "If the original string is very long, and has array of size 1GB, no matter how small a substring is, it will hold 1GB array. This will also stop original string to be garbage collected, in case if doesn't have any live reference ". 文章还提到:“如果原始字符串很长,并且数组大小为1GB,则无论子字符串有多小,它都将容纳1GB数组。 这也将阻止原始字符串被垃圾回收,以防万一。有任何实时参考资料

The link to the article is here { http://javarevisited.blogspot.sg/2011/10/how-substring-in-java-works.html } 本文的链接在此处 { http://javarevisited.blogspot.sg/2011/10/how-substring-in-java-works.html }

I cannot understand this. 我无法理解这。 Please anybody explain me how does it stop the original string to be garbage collected if it does't have any live reference? 请有人解释我,如果没有任何实时引用,它将如何阻止原始字符串被垃圾回收?

According to my little understanding, in java any object which doesn't have direct or indirect reference will be eligible for garbage collector to collect. 根据我的一点理解,在Java中,任何没有直接或间接引用的对象都可以进行垃圾收集器收集。 If subString method uses the same character array used to represent original string how can the original String stay without being garbage collected ? 如果subString方法使用与表示原始字符串相同的字符数组,那么如何在不进行垃圾回收的情况下保留原始String?

Likewise I want to know does the memory leak is caused due to use the same character array used to represent original string because the new string {String returned by subString method} would be very little compared with the original String or since the original string is still staying without being garbage collected? 同样,我想知道内存泄漏是否是由于使用与表示原始字符串相同的字符数组引起的,因为新字符串{subString方法返回的字符串}与原始字符串相比将很小,或者由于原始字符串仍然住而不被垃圾收集?

Please anybody help me to clarify this 请任何人帮我澄清一下

When you allocate anything in Java, and in this case a String , it stays in memory for as long as you still have a way of accessing it. 当您使用Java分配任何内容(在这种情况下为String ,只要您仍然可以访问它,它就会在内存中保留。 If you write 如果你写

String s = "blah";

then s is a reference to that String . 那么s是对该String引用 As long as there's at least one reference to the String , then the JVM knows it needs to be kept around in memory. 只要至少有一个对String引用,那么JVM便知道它需要保留在内存中。 Once there are no more references, then the JVM can clean it up and reclaim the memory when it needs to. 一旦没有更多引用,JVM便可以清理它并在需要时回收内存。

If you write 如果你写

String s = "myverylongstring...somemore...someotherstuff";

then you've used up quite a lot of memory. 则您已经消耗了很多内存。 Internally, this will be represented as a char[] containing all of the characters of your String , with some extra gubbins round the edge to allow you to access it using the String API. 在内部,这将表示为char[]其中包含String所有字符,边缘带有一些额外的gubbins,以允许您使用String API对其进行访问。

Now, what happens if you then write 现在,如果您随后写

s = s.substring(20,30);

so that s is now a reference just to part of the original String ? 所以s现在只是对原始String一部分的引用? There are two ways the JVM might deal with it. JVM有两种处理方式。 One is to keep the whole char[] in memory, but just change which bit of the char[] it's prepared to let you get access to. 一种是将整个char[]保留在内存中,但只需更改它准备让您可以访问的char[]的哪一部分即可。 The other is to copy the relevant bit of the char[] into a new array, and then get rid of all references to the old one. 另一种是将char[]的相关位复制到新数组中,然后除去对旧数组的所有引用。

The first approach is quick, because it doesn't need any copying. 第一种方法是快速的,因为它不需要任何复制。 But if you now only want a small bit of your huge String , then the whole of the big String can't ever be fully cleaned up because the whole of its char[] is still in memory being used. 但是,如果您现在只需要一小部分巨大的String ,那么就无法完全清除整个大String ,因为它的整个char[]仍在使用中。 The fact that only part of it is being used means that none of its memory can be reclaimed. 仅使用其中一部分的事实意味着无法回收其任何内存。

The second approach is slower, because it needs a copy operation. 第二种方法较慢,因为它需要复制操作。 But it does mean that the previous String can be cleaned up in its entirety, because the old char[] isn't being used any more. 但这确实意味着可以完全清除以前的String ,因为不再使用旧的char[]

Java used to follow the first approach, but in recent times (Java 7 onwards) it's switched to using the second. Java 曾经遵循第一种方法,但是最近(从Java 7开始)它已切换为使用第二种方法。 So memory leaks used to be a problem with the substring() call, but aren't any longer. 因此内存泄漏曾经是substring()调用的问题,但现在不再存在。

The wording is a bit sloppy. 措词有点草率。 The original String instance will be garbage-collected. 原始的String实例将被垃圾回收。 But its internal array of characters won't, since it's still referenced by the substring. 但是它的内部字符数组不会,因为它仍然被子字符串引用。

In an extreme case, you could thus have a String instance of length 1 referencing a 1GB array. 因此,在极端情况下,您可能拥有一个长度为1的String实例,该实例引用1GB数组。

Before: 之前:

s1 ---------> object --> char[] (1GB large)
               - offset
               - count

substring is called: 子字符串称为:

s1 ---------> object --> char[] (1GB large)
              - offset  ^
              - count   |
                        |
substring --> object ---/
              - offset
              - count

s1 goes out of scope: object can be garbage collected s1超出范围:可以垃圾回收对象

                         char[] (1GB large)
                        ^
                        |
substring --> object ---/
              - offset
              - count

In accord with @chiastic-security answer, also find this reference for detailed explanation on Java 8 treatment for memory leak prevention 与@ chiastic-security答案一致,也可以找到此参考资料,以获取有关防止内存泄漏的Java 8处理的详细说明。

http://mrgyani.com/java-interview/memory-leak-problem-in-java-substring/ http://mrgyani.com/java-interview/memory-leak-problem-in-java-substring/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM