You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

String类subString方法为何会引发内存溢出?

String.substring() 引发内存溢出的原理

首先明确:这个问题只存在于JDK 6及更早版本,JDK 7及之后已经修复了该缺陷。

JDK 6 中的问题根源

  1. String类的内部结构
    JDK 6里的String对象包含三个核心字段:
  • char[] value:存储实际字符的底层数组
  • int offset:字符数组中当前String的起始偏移量
  • int count:当前String的字符长度
  1. substring()的实现逻辑
    调用substring(int beginIndex, int endIndex)时,JDK 6会直接创建一个新的String对象,但不会复制原字符串的char[],而是复用原数组,仅修改新String的offset和count字段来指向原数组的对应片段。

  2. 内存溢出的触发场景
    假设你有一个超大的String对象(比如几GB的文本),当你用substring()截取其中很小的一部分(比如几个字符)后,原超大String对象即使被回收,新生成的小String对象仍会持有原超大char[]的引用。只要这个小String还存在于内存中,原超大char[]就无法被GC回收。如果大量生成这类小String,内存会被这些“无用”的超大char[]持续占用,最终引发OutOfMemoryError。

JDK 7+ 的修复方案

JDK 7及之后彻底修改了substring()的实现:调用该方法时,会直接复制需要的字符片段到新的char[]中,新String对象不再引用原数组。这样即使原大String被回收,对应的char[]也会被正常GC,不会再出现内存泄漏问题。

示例代码(JDK 6 场景)

// 创建一个100MB的超大字符串
String largeString = new String(new char[1024 * 1024 * 100]);
// 截取仅10个字符的小字符串
String smallString = largeString.substring(0, 10);
// 此时largeString可被回收,但smallString持有原100MB的char[]引用,该数组无法释放

内容的提问来源于stack exchange,提问作者Shubham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:52:38