请教大家一个java面试题,关于堆内存。

qq_29448025 2017-01-03 02:34:40
以下两种方法,仅箭头所指的语句不同,为什么会有不同的结果,请解释说明?





...全文
890 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
baij1230 2017-01-06
  • 打赏
  • 举报
回复
8楼终结,实际上是因为数组Arrays的copyof方法使得大量字符数组占用的内存没有来得及被回收
BluntKnifee 2017-01-06
  • 打赏
  • 举报
回复
测试了一下,没到32次就停止了,所以长度没问题,假设28次停止,相当于有2^28的长度都没到,如果从内存分析,String一个单位长度的存储为2个字节;那么内存2^29 b;相当于2^9 M;但是我的运行内存有750M,怎么就停止了呢……
紫守笨 2017-01-04
  • 打赏
  • 举报
回复
应该就是长度问题,在内存回收方面,第一个和第二个都是一样的,都是在堆中回收,每次进行str += str 或者 str += i时,会不断创建StringBuilder对象然后不使用,导致堆内内存不够使用。
bree06 2017-01-04
  • 打赏
  • 举报
回复
只能说面试官想多了, #8楼已经验证了, 只循环27次就OOM了不可能存在内存回收的问题. 实际报错位置是java.util.Arrays.copyOf()3332行, 而这一行代码是char[] copy = new char[newLength]; 也就是说分配内存不足引起的OOM. 瞎扯什么内存回收. 以下方法直接使用StringBuilder不存在内存回收的问题也同样会OOM.
public static void main(String[] args) {
    StringBuilder s = new StringBuilder("b");
    for (int i = 0; i < 134217730; i++) { // 这里的的最大值是#8楼str.length最大值+2
        s.append(i);
    }
}
ps45221 2017-01-04
  • 打赏
  • 举报
回复
感觉没有说到点子上!
面试官说的是对的,报OOM这个错误跟长度确实没多大关系,准确的说是还没有到那个长度就已经OOM了。
看下报错的堆栈信息就晓得了,我稍微修改下这个程序,打印出一些信息,主要为了观察报OOM异常时,
当前的str长度

String str = "b";
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i + ", str.lenth = " + str.length());
str = str + str;
}
System.out.println(str);

在我的机器上执行结果是这样的,

可见,当前是执行到i=28的时候才报OOM,也就是str的长度为2^28个长度,此时这个长度还没有超过Integer.MAX_VALUE,
(我这里的JVM内存调的算比较大了,如果设置的小,报错会更早)
再仔细看下报错的堆栈信息,第一行就是java.util.Arrays.copyOf(Arrays.java:3332),说明是由这个引起的,跟进源码
看下,发现是StringBuilder的扩容(字符串相加,编译后会优化成stringbuilder,然后调用append方法),
然后copy char数组导致的堆内存空间不足导致的
第二个程序,自己加上打印语句就很简单就看出来了
当然,长度到Integer.MAX_VALUE也会报OOM异常,只是内存那时早已经不够了。
chen_ya_ping 2017-01-04
  • 打赏
  • 举报
回复
http://stackoverflow.com/questions/816142/strings-maximum-length-in-java-calling-length-method
qq_29448025 2017-01-03
  • 打赏
  • 举报
回复
ryuugu_rena 2017-01-03
  • 打赏
  • 举报
回复
第一个翻倍装不下,第二个可以装下。也就是说String类型是有长度的。
qq_29448025 2017-01-03
  • 打赏
  • 举报
回复
楼上所有的回答,都是关于str长度的问题,但我当时私下问了一下面试官,是不是str长度的问题,他说不是,要我从内存的回收方面考虑。
Defonds 2017-01-03
  • 打赏
  • 举报
回复
考察的是你对内存的理解、代码运行时的预分析能力
qq_32825349 2017-01-03
  • 打赏
  • 举报
回复
String内部是以char数组的形式存储,数组的长度是int类型,那么String允许的最大长度就是Integer.MAX_VALUE了,2147483647; 方法1的长度是2的一百次方,显然超过了 方法二 的长度200不到,191
qq_32825349 2017-01-03
  • 打赏
  • 举报
回复
String内部是以char数组的形式存储,数组的长度是int类型,那么String允许的最大长度就是Integer.MAX_VALUE了,2147483647;
zhangen80 2017-01-03
  • 打赏
  • 举报
回复
第一个是str每次的长度都是翻倍的最后长度有2^100次方,而下面只是加个数字,最长也就100位多点

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧