如何使用字符串有效地管理内存?

2022-09-01 19:47:57

考虑一段示例代码。

public void testString()
{     
    int i = 0;
    while(i < 100000000)
    {
        String s ="Hi hello bye" +i;
        i++;          
    }
}

在每次迭代中,都会创建一个新的 String,并且下一次迭代不再需要其值。我尝试打印此 testString() 功能之前和之后消耗的内存。以下是它们的值。

Before invoking testString():

Total Memory: 91684864 (87.4375 MB)
Max Memory:   1360855040 (1297.8125 MB)
Free Memory:  72163552 (68.82052612304688 MB)

After invoking testString():
Total Memory: 424280064 (404.625 MB)
Max Memory:   1360855040 (1297.8125 MB)
Free Memory:  171766816 (163.80960083007812 MB).

我看到大量内存被使用,并且由于当前处理字符串的方式,我担心JVM堆可能会越界。迭代 2 中不再需要为迭代 1 生成的字符串,并且可以释放其存储空间。我认为,这里没有发生这种情况。

我尝试使用StringBuffer和StringBuilder对象,内存使用率似乎有很小的改善。

请帮助我一个更好和最好的方法。


答案 1

迭代 2 中不再需要为迭代 1 生成的字符串,并且可以释放其存储空间。我认为,这里没有发生这种情况。

它肯定正在发生

您正在创建 1 亿个字符串,每个字符串至少为 13 个字符,其中大部分约为 20 个字符。每个字符串由一个对象(具有开销)和一个 - 组成,因此我猜想对于一个20个字符的字符串,它需要大约60个字节。char[]

如果垃圾回收没有效果,那么1亿个对象需要60个字节,每个需要60个字节 - 而你看到的总内存只比开始时大300MB左右。

字符串正在被收集 - 只是不是立即收集。

你还没有告诉我们你需要如何处理你实际代码中的字符串(我假设这有一个真正的动机) - 假设你真的需要在循环的每次迭代中都有一个字符串,我不认为使用会帮助你。如果你只需要一个数据,那么你可以让它更有效率,但你很少创建一个,但不调用它。StringBuilderStringBuilderStringBuildertoString


答案 2

第一次运行时会发生什么

JVM 运行代码,生成字符串,并在特定时间间隔内释放已用内存。除了一些浪费的执行时间外,程序将正常运行。

如果频繁调用该函数会发生什么情况

JVM将开始优化循环,意识到这些字符串不会执行任何操作,并将整个函数标记为死代码。最终调用该函数实际上将不执行任何操作,因为JVM将内容转换为简单的return

请帮助我一个更好和最好的方法。

由于即使是JVM也不知道您的代码应该做什么...你想做什么?对于您手头的实际问题,可能有一个最佳解决方案,与您最初发布的代码示例非常不同。