站内搜索: 请输入搜索关键词

当前页面: 开发资料首页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的当前容量
以此来衡量比简单用内存变化来衡量要更准确一些


↑返回目录
前一篇: 关于一道基础题的想法和疑问~
后一篇: 正则表达式怎么实现匹配?