众所周知StringBuffer是安全的,而StringBuilder是不安全的,他们都有append方法,但具体实现细节你了解过吗?为什么有时候用着用着就OutOfMemoryError
,在哪报的
以StringBuffer.append(str)为例
上图可见,线程安全是因为synchronized
,正真的实现调用的是父类方法
super.append(str)
父类核心方法ensureCapacityInternal
确保容量足够,是怎么确保的呢?
ensureCapacityInternal(int)
Arrays.copyOf
只是复制用的,一会儿再看,先看一下newCapacity(minimumCapacity))
newCapacity(minimumCapacity))
下面这句就是确保容量足够的核心代码
int newCapacity = (value.length << 1) + 2;
可以看出来,为了确保容量足够,java会将容量扩大到原来的两倍再加上2,但为了确保容量合理不会超过最大值,在返回前进行了判断。当容量大到一定程度会触发hugeCapacity
方法
原来OutOfMemoryError
内存溢出在这个位置,原因就是申请的内存太大了,大到超过Integer.MAX_VALUE
,看一下hugeCapacity
,系统有确保不要超过一个最大阈值MAX_ARRAY_SIZE
,具体为:
回到ensureCapacityInternal(int)
继续深挖Arrays.copyOf(char[] original, int newLength)
Arrays.copyOf(char[] original, int newLength)
最终挖到底了,系统底层实现System.arraycopy