hsm*_*mit 193 java memory string performance
我说,我使用了一个包含大量数据的变量String data.我想以下列方式使用此字符串的一小部分:
this.smallpart = data.substring(12,18);
Run Code Online (Sandbox Code Playgroud)
经过几个小时的调试(使用内存可视化器)后,我发现对象字段smallpart记住了所有数据data,尽管它只包含子字符串.
当我将代码更改为:
this.smallpart = data.substring(12,18)+"";
Run Code Online (Sandbox Code Playgroud)
..问题解决了!现在我的应用程序现在使用很少的内存!
怎么可能?有谁能解释一下?我认为这个小部分一直在引用数据,但为什么呢?
更新: 如何清除大字符串呢?data = new String(data.substring(0,100))会做什么吗?
Bri*_*new 159
执行以下操作:
data.substring(x, y) + ""
Run Code Online (Sandbox Code Playgroud)
创建一个新的(较小的)String对象,并抛弃对substring()创建的String的引用,从而实现对此的垃圾收集.
要实现的重要一点是,substring()在现有 String 上提供一个窗口- 或者更确切地说,是原始String下面的字符数组.因此它将消耗与原始String相同的内存.这在某些情况下可能是有利的,但如果你想获得一个子字符串并处理原始字符串(如你所知),则会有问题.
有关详细信息,请查看JDK String源中的substring()方法.
编辑:要回答您的补充问题,从子字符串构造一个新的字符串将减少您的内存消耗,前提是您对原始字符串的任何引用.
注意(2013年1月).Java 7u6中的上述行为已发生变化.不再使用flyweight模式,并且substring()可以按预期工作.
Pas*_*ent 28
如果你看一下它的来源substring(int, int),你会看到它返回:
new String(offset + beginIndex, endIndex - beginIndex, value);
Run Code Online (Sandbox Code Playgroud)
value原来在哪里char[].所以你得到一个新的String但具有相同的底层char[].
当你这样做时data.substring() + "",你得到一个带有新底层的新String char[].
实际上,您的用例是您应该使用String(String)构造函数的唯一情况:
String tiny = new String(huge.substring(12,18));
Run Code Online (Sandbox Code Playgroud)
Chr*_*ung 17
使用时substring,它实际上不会创建新字符串.它仍然引用您的原始字符串,具有偏移和大小约束.
因此,要允许收集原始字符串,您需要创建一个新字符串(使用new String或者您已经获得).
在Java中,字符串是可以计算的对象,一旦创建了一个字符串,它就会保留在内存中,直到被垃圾回收器清理(并且这种清理不是你认为理所当然的事情).
当您调用substring方法时,Java不会创建一个新的字符串,而只是在原始字符串中存储一系列字符.
因此,当您使用以下代码创建新字符串时:
this.smallpart = data.substring(12, 18) + "";
Run Code Online (Sandbox Code Playgroud)
实际上,当您将结果与空字符串连接时,您创建了一个新字符串.这就是为什么.
我认为这个小部分一直在引用数据,但为什么呢?
因为Java字符串由char数组,起始偏移量和长度(以及缓存的hashCode)组成.一些String操作,比如substring()创建一个新的String对象,该对象共享原始的char数组,并且只有不同的偏移和/或长度字段.这是有效的,因为String的char数组在创建后永远不会被修改.
当许多子串引用相同的基本字符串而不复制重叠部分时,这可以节省内存.正如您所注意到的,在某些情况下,它可以保留不再需要的数据来进行垃圾回收.
解决这个问题的"正确"方法是new String(String)构造函数,即
this.smallpart = new String(data.substring(12,18));
Run Code Online (Sandbox Code Playgroud)
顺便说一句,总体上最好的解决方案是首先避免使用非常大的字符串,并以较小的块处理任何输入,一次几KB.
| 归档时间: |
|
| 查看次数: |
8137 次 |
| 最近记录: |