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

Vig*_*esh 24 java string performance jvm memory-leaks

考虑一段示例代码.

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

在每次迭代中,都会创建一个新的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).
Run Code Online (Sandbox Code Playgroud)

我看到使用了大量内存,并且由于当前处理字符串的方式,我担心JVM堆可能会超出范围.在迭代2中不再需要为迭代1生成的字符串,并且可以释放其存储空间.我相信这不会发生在这里.

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

请帮助我更好,更好的方法.

Jon*_*eet 50

在迭代2中不再需要为迭代1生成的字符串,并且可以释放其存储空间.我相信这不会发生在这里.

它肯定正在发生.

您正在创建1亿个字符串,每个字符串至少包含13个字符 - 其中大多数字符串大约为20个字符.每个字符串都包含一个对象(有开销)和一个char[]- 所以我猜它会占用大约60个字节的20个字符的字符串.

如果垃圾收集无效,那么每个需要60个字节的1亿个对象需要6GB - 而你看到的总内存只比开始时大约300MB.

该字符串收集-只是没有马上.

您还没有告诉我们您需要对实际代码中的字符串做什么(我假设有一个真正的动机) - 假设您在循环的每次迭代中实际上需要一个字符串,我不认为使用StringBuilder会帮助你.如果您需要数据,StringBuilder那么您可以提高效率,但很少创建StringBuilder但不要调用toString它.

  • @Vignesh有JVM选项来记录GC操作 (2认同)

Two*_*The 7

第一次运行会发生什么

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

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

JVM将开始优化循环,意识到没有对这些字符串做任何事情,并将整个函数标记为死代码.最终调用该函数几乎没有任何意义,因为JVM将内容转换为简单内容return

请帮助我更好,更好的方法.

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

  • 不要动态生成选择查询.永远.http://en.wikipedia.org/wiki/SQL_injection (3认同)
  • @James_pic完全可能动态生成参数化查询. (2认同)