当前页面: 开发资料首页 → J2SE 专题 → new StringBuffer() 与new StringBuffer(int) 内存问题
new StringBuffer() 与new StringBuffer(int) 内存问题
摘要: new StringBuffer() 与new StringBuffer(int) 内存问题
环境 jdk 1.5.0_06-b05
操作系统 win2003
目的:大概了解一下一个大的StringBuffer所占的内存。
代码一:
public static void main(String[] args) throws IOException {
long start = Runtime.getRuntime().totalMemory(); //启动前系统使用内存
StringBuffer sb = new StringBuffer("");
String tmp="0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"; //长度为100的字符串
for(long i=1;i<(1000*50+1);i++){ //5w行
sb.append(tmp);
if((i % 1000)==0){
long nowMen = Runtime.getRuntime().totalMemory() -start ;
System.out.println("加入到 "+i +" mem=" + (nowMen/1024)+"k");
}
}
//通过Runtime 计算内存使用量
long nowMen = Runtime.getRuntime().totalMemory() -start ;
System.out.println("加入到完成 mem=" + (nowMen/1024)+"k");
//通过串行化计算内存使用量
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bs);
os.writeObject(sb);
os.flush();
System.out.println(bs.size()/1024);
}
代码一结果
加入到 1000 mem=0k
加入到 2000 mem=0k
加入到 3000 mem=0k
加入到 4000 mem=0k
加入到 5000 mem=1832k
加入到 6000 mem=1832k
加入到 7000 mem=1832k
加入到 8000 mem=1832k
加入到 9000 mem=5100k
加入到 10000 mem=5100k
加入到 11000 mem=5100k
加入到 12000 mem=5100k
加入到 13000 mem=5100k
加入到 14000 mem=5100k
加入到 15000 mem=5100k
加入到 16000 mem=5100k
加入到 17000 mem=11632k
加入到 18000 mem=11632k
加入到 19000 mem=11632k
加入到 20000 mem=11632k
加入到 21000 mem=11632k
加入到 22000 mem=11632k
加入到 23000 mem=11632k
加入到 24000 mem=11632k
加入到 25000 mem=11632k
加入到 26000 mem=11632k
加入到 27000 mem=11632k
加入到 28000 mem=11632k
加入到 29000 mem=11632k
加入到 30000 mem=11632k
加入到 31000 mem=11632k
加入到 32000 mem=11632k
加入到 33000 mem=11632k
加入到 34000 mem=25204k
加入到 35000 mem=25204k
加入到 36000 mem=25204k
加入到 37000 mem=25204k
加入到 38000 mem=25204k
加入到 39000 mem=25204k
加入到 40000 mem=25204k
加入到 41000 mem=25204k
加入到 42000 mem=25204k
加入到 43000 mem=25204k
加入到 44000 mem=25204k
加入到 45000 mem=25204k
加入到 46000 mem=25204k
加入到 47000 mem=25204k
加入到 48000 mem=25204k
加入到 49000 mem=25204k
加入到 50000 mem=25204k
加入到完成 mem=25204k
13056
代码二 修改第三行
StringBuffer sb = new StringBuffer("");
改为 StringBuffer sb = new StringBuffer(1000*50*100);
结果
加入到 1000 mem=9768k
加入到 2000 mem=9768k
加入到 3000 mem=9768k
加入到 4000 mem=9768k
加入到 5000 mem=9768k
加入到 6000 mem=9768k
加入到 7000 mem=9768k
加入到 8000 mem=9768k
加入到 9000 mem=9768k
加入到 10000 mem=9768k
加入到 11000 mem=9768k
加入到 12000 mem=9768k
加入到 13000 mem=9768k
加入到 14000 mem=9768k
加入到 15000 mem=9768k
加入到 16000 mem=9768k
加入到 17000 mem=9768k
加入到 18000 mem=9768k
加入到 19000 mem=9768k
加入到 20000 mem=9768k
加入到 21000 mem=9768k
加入到 22000 mem=9768k
加入到 23000 mem=9768k
加入到 24000 mem=9768k
加入到 25000 mem=9768k
加入到 26000 mem=9768k
加入到 27000 mem=9768k
加入到 28000 mem=9768k
加入到 29000 mem=9768k
加入到 30000 mem=9768k
加入到 31000 mem=9768k
加入到 32000 mem=9768k
加入到 33000 mem=9768k
加入到 34000 mem=9768k
加入到 35000 mem=9768k
加入到 36000 mem=9768k
加入到 37000 mem=9768k
加入到 38000 mem=9768k
加入到 39000 mem=9768k
加入到 40000 mem=9768k
加入到 41000 mem=9768k
加入到 42000 mem=9768k
加入到 43000 mem=9768k
加入到 44000 mem=9768k
加入到 45000 mem=9768k
加入到 46000 mem=9768k
加入到 47000 mem=9768k
加入到 48000 mem=9768k
加入到 49000 mem=9768k
加入到 50000 mem=9768k
加入到完成 mem=9768k
9765
有XD了解jvm的可以说一下吗?
关注
是不是前一种方式的内存是动态增长的,而后一种是一直固定不变的?
mark
学习了
关注
StringBuffer sb = new StringBuffer(1000*50*100)
设的太大了,改小一点也会变化的。不太清楚stringbuffer调整缓存大小的机制,不过这也没啥好研究的了。
关注,学习。。。
long nowMen = Runtime.getRuntime().totalMemory() -start
该做法没有意义,因为某次循环刚好在执行gc之前或之后,打印的内容就不一样了。
具体到StringBuffer或者ArrayList之类动态数组的初始大小,严重建议诸位在能确认最终大小的范围或者数量级的时候,使用合适的初始大小,避免多次重新分配及arraycopy
>>long nowMen = Runtime.getRuntime().totalMemory() -start
>>该做法没有意义,因为某次循环刚好在执行gc之前或之后,打印的内容就不一样了。
这个问题也想过,不过只是想很得一个大概的范围,而且只是一个单线程的测试,没有释放任何对象,应当也没有gc,运行时间也很短,不超过秒,也没什么其它程序在运行,基本上这个数据与实际数据没什么差别。
to danjiewu(阿丹) ;
1000*50*100 这个值不大不小,刚好是5w条100个字符,从实际运行情况来说也是一样,没有再进行内存分配。最后的结果 13056 与9765 是如何产生的,第一种情况运行时通过Runtime与用串行化两种方法计算内存差别很大,第二种则差别基本上可以忽略不计,为什么会产生这种情况?
我是这么认为的,不知道对不
在你new StringBuffer(1000*50*100);的时候,系统在内存中分配了1000*50*100的容量,所以你每次append只要向已经分派好的内存中写入就好
而new StringBuffer(“”)并没有分配足够的内存容量,所以在你每次append的时候,StringBuffer需要把前面的内存块和现在的100个字符连接起来,换句话说就是有5W-1个连接点,每个连接点需要占用内存吧!那5W-1个连接点需要占用多少的内存呢?
我想,他们之间的差值就是那些连接点所占用的内存空间吧!
以上完全属于个人假想
可能的解释是,ByteArrayOutputStream,ObjectOutputStream有自己的缓存,bs.size()的区别与ByteArrayOutputStream,ObjectOutputStream具体实现有关。
没必要研究这些细节末枝吧
没必要研究这些细节末枝吧
事实上我测试的目的已经达到了,但对结果有点好奇,所以想看看那位兄台对这个有见解。晚上再看看源代码看看能找出什么东西。
StringBuffer是动态增长的
当容量不足的时候,就自动按一定规则来进行容量扩充
看lz的测试代码,似乎是在容量不足的时候*2来扩充容量的
而直接给StringBuffer传一个数值来初始化,容量足够的情况下不需要进行扩充容量的操作
而StringBuffer实际所占的内存应该是按其容量大小来计算的
StringBuffer.capacity()可以返回StringBuffer的当前容量
以此来衡量比简单用内存变化来衡量要更准确一些