java - Java中字符串的不可变性会导致内存不足吗

标签 java memory memory-management out-of-memory

我编写了一个简单的 Java 程序,它从数据库中读取一百万行并将它们写入文件。

本程序最大可使用内存为512M。

我经常注意到该程序运行超过 500K 行时内存不足。

由于该程序是一个非常简单的程序,因此很容易发现它没有内存泄漏。该程序的工作方式是从数据库中获取一千行,使用 Streams 将它们写入一个文件,然后继续获取下一千行。每行的大小各不相同,但没有一行很大。在程序运行时进行转储时,很容易在堆上看到较旧的字符串。堆中的这些字符串不可访问,这意味着它们正在等待收集垃圾。我还相信 GC 不一定会在该程序的执行期间运行,这会使 String 在堆中的停留时间比它们应有的时间长。

我认为解决方案是使用长字符数组(或字符串缓冲区)而不是使用字符串对象来存储数据库返回的行。假设我可以覆盖 Char 数组的内容,这意味着可以在多次迭代中使用同一个 Char 数组,而不必每次都分配新的空间。

伪代码:

  1. 使用 new char[1000][1000] 创建一个数组数组;
  2. 将 DB 中的千行填充到数组中。
  3. 将数组写入文件。
  4. 对接下来的一千行使用相同的数组

如果上面的伪代码解决了我的问题,那么实际上 String 类的不可变特性伤害了 Java 程序员,因为没有直接的方法来声明 String 使用的空间,即使 String 不再使用也是如此。

这个问题有没有更好的替代方案?

P.S : 我没有单独做静态分析。我使用 yourkit profiler 来测试堆转储。转储清楚地表明 96% 的字符串没有 GC 根,这意味着它们正在等待收集垃圾。此外,我不在我的代码中使用 Substring。

最佳答案

String 类的不变性与 OutOfMemoryError 完全无关。不变性意味着它永远不会改变,只能改变。

如果内存不足,那只是因为垃圾收集器无法找到任何垃圾收集

实际上,您可能在内存中持有对太多字符串的引用(例如,您是否有任何类型的集合持有字符串,如 List、Set、Map?)。您必须销毁这些引用以允许垃圾收集器完成其工作并释放一些内存。

关于java - Java中字符串的不可变性会导致内存不足吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12910414/

相关文章:

java - 尝试使用 thymeleaf 进行 Spring Boot 表单验证,但出现我无法弄清楚的错误

java - 由公共(public)方法初始化的私有(private)构造函数

java - Android Studio 表示未安装 JDK 7,而 JDK 8 甚至已安装

javascript - Memcache、Redis、Javascript 哈希对象

c++ - 在类(class)特定版本的 placement new 中做什么?

c# - 处理大量文本时防止内存问题

java - 在Java中显示±符号

c - 为什么要更改数组大小值来操作十进制字节?

c - C中的堆栈分配

c++ - 在 NULL 指针上调用 delete 或 delete[]