quote:
public class testString{
public static void main(String args[])
{
String s="abbbbb";
System.out.System.out.println("JVM IS USING MEMORY:"+Runtime.getRuntime().totalMemory()/1024/1024+"M");
Runtime.getRuntime().traceMethodCalls(true);
while(true)
{
try{
s=s+s;
}catch(Exception e)
{
System.out.println(e);
}
catch(Error o)
{ String unit = null;
int sizeb = s.length();
int size = sizeb;
int time = 0;
while(size>1024)
{
size = size/1024;
time++;
}
switch(time)
{
case 0: unit = "byte";break;
case 1: unit = "k"; break;
case 2: unit = "M"; break;
default : unit = "byte";
}
System.out.println("String has used memory:"+size+unit);
System.out.println("JVM IS USING MEMORY:"+(float)Runtime.getRuntime().totalMemory()/1024/1024+"M");
System.out.println("MemoryError:"+o);
break;
}
}
}
}
然后我們用JVM的默認參數執行(我的機器內存是128M)
java testString
結果:
JVM MAX MEMORY: 128M
JVM IS USING MEMORY:1M
String has used memory:12M
JVM IS USING MEMORY:63.5625M
MemoryError:java.lang.OutOfMemoryError
開始JVM使用的內存是1M,當String為12M,JVM使用了63M多時
JVM溢出。
然后,我們用限制JVM內存大小的參數來執行,限制最大內存5M
java -mx5m testString
結果:
JVM MAX MEMORY: 70M
JVM IS USING MEMORY:1M
String has used memory:768.0k
JVM IS USING MEMORY:5.9375M
MemoryError:java.lang.OutOfMemoryError
開始JVM使用的內存是1M,當String為768k,JVM使用了5M多時
JVM溢出。
大家還可以改變 -mx參數,來進一步做實驗。
以上兩個實驗證實,String是沒有長度限制的,而是有JVM的內存限制了String的長度。同時說明,并不會拋出任何Exception而只會拋出Error.
OutMemoryError表明程序的設計很差,或者碰到了超出編程人員所預想的大批量的數據。不管哪種情況,都只有下面這幾種解決辦法。它們是:
設計人員重新設計程序,不致使程序一次載入所有的數據。
數據可以分割成更小的塊。
可以為程序分配更多的內存。
為Java虛擬機提供更多的內存。
而上面的例子是為虛擬機提供更多的內存
=======================================
其實應該少用String這東西,非凡是 String的 +=操作
不僅原來的String對象不能繼續使用,主要是又要new出N多的新對象出來,再多的memory也要out~~
String用char array實現,就肯定由長度限制的,不能用memory來衡量
==================================
例如上面的程序改用StringBuffer實現,就可以得到極大的改善。
下面是我改用StringBuffer做的測試:
注重:程序循環了2097150次!
是使用String的程序的99864倍!
public class TestStringBuffer{
public static void main(String args[])
{
String s="abbbbb";
StringBuffer sb = new StringBuffer(s);
System.out.println("JVM IS USING MEMORY:"+
(Runtime.getRuntime().totalMemory()/1024/1024)+
"M");
Runtime.getRuntime().traceMethodCalls(true);
int count = 0;
while(true)
{
try{
sb.append(s);
count++;
}catch(Exception e)
{
System.out.println(e);
}
catch(Error o)
{
String unit = null;
int size = sb.length();
size *= 2;
int time = 0;
while(size>1024)
{
size = size/1024;
time++;
}
switch(time)
{
case 0: unit = "byte";break;
case 1: unit = "k"; break;
case 2: unit = "M"; break;
default : unit = "byte";
}
System.out.println("Loop times:"+count);
System.out.println("String has used memory:"+size+unit);
System.out.println("JVM IS USING MEMORY:"+
(float)Runtime.getRuntime().totalMemory()/1024/1024+
"M");
System.out.println("MemoryError:"+o);
break;
}
}
}
}
輸出結果:
JVM IS USING MEMORY:1M
Loop times:2097150
String has used memory:23M
JVM IS USING MEMORY:63.75M
MemoryError:java.lang.OutOfMemoryError
=====================
從另一方面說,假如你要處理的字符串達到百兆甚至上GB,使用String對象,根本沒法工作,所以這個問題不需要太多討論。看一下jdk的源文件,String的長度是String對象的一個成員count,類型是int,不是long,也不是char。知道這些,我認為夠了。
新聞熱點
疑難解答