环境 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的可以说一下吗?

解决方案 »

  1.   

    StringBuffer sb = new StringBuffer(1000*50*100)
    设的太大了,改小一点也会变化的。不太清楚stringbuffer调整缓存大小的机制,不过这也没啥好研究的了。
      

  2.   

    long nowMen = Runtime.getRuntime().totalMemory() -start该做法没有意义,因为某次循环刚好在执行gc之前或之后,打印的内容就不一样了。具体到StringBuffer或者ArrayList之类动态数组的初始大小,严重建议诸位在能确认最终大小的范围或者数量级的时候,使用合适的初始大小,避免多次重新分配及arraycopy
      

  3.   

    >>long nowMen = Runtime.getRuntime().totalMemory() -start
    >>该做法没有意义,因为某次循环刚好在执行gc之前或之后,打印的内容就不一样了。这个问题也想过,不过只是想很得一个大概的范围,而且只是一个单线程的测试,没有释放任何对象,应当也没有gc,运行时间也很短,不超过秒,也没什么其它程序在运行,基本上这个数据与实际数据没什么差别。
      

  4.   

    to danjiewu(阿丹) ;
    1000*50*100 这个值不大不小,刚好是5w条100个字符,从实际运行情况来说也是一样,没有再进行内存分配。最后的结果 13056 与9765 是如何产生的,第一种情况运行时通过Runtime与用串行化两种方法计算内存差别很大,第二种则差别基本上可以忽略不计,为什么会产生这种情况?
      

  5.   

    我是这么认为的,不知道对不
    在你new StringBuffer(1000*50*100);的时候,系统在内存中分配了1000*50*100的容量,所以你每次append只要向已经分派好的内存中写入就好
    而new StringBuffer(“”)并没有分配足够的内存容量,所以在你每次append的时候,StringBuffer需要把前面的内存块和现在的100个字符连接起来,换句话说就是有5W-1个连接点,每个连接点需要占用内存吧!那5W-1个连接点需要占用多少的内存呢?   
    我想,他们之间的差值就是那些连接点所占用的内存空间吧!
    以上完全属于个人假想
      

  6.   

    可能的解释是,ByteArrayOutputStream,ObjectOutputStream有自己的缓存,bs.size()的区别与ByteArrayOutputStream,ObjectOutputStream具体实现有关。没必要研究这些细节末枝吧
      

  7.   

    StringBuffer是动态增长的
    当容量不足的时候,就自动按一定规则来进行容量扩充
    看lz的测试代码,似乎是在容量不足的时候*2来扩充容量的
    而直接给StringBuffer传一个数值来初始化,容量足够的情况下不需要进行扩充容量的操作
    而StringBuffer实际所占的内存应该是按其容量大小来计算的
    StringBuffer.capacity()可以返回StringBuffer的当前容量
    以此来衡量比简单用内存变化来衡量要更准确一些