频繁的Integer.toString()转换导致内存问题

时间:2013-03-02 17:03:58

标签: java android string performance

我目前正在将使用C#(适用于Windows Phone)开发的游戏移植到Java(Android)。

我们在Java版本中遇到内存问题,在分析之后,似乎来自内存中的大量String个对象,显然是由于String的不可变性质。现在,我已经设法将其追溯到将玩家得分呈现给屏幕的方法,其中每次得分改变时使用Integer.toString()(每秒多次)。我不能真正使用StringBuilder(这是我们在C#版本中所拥有的)因为我们使用的框架的文本呈现方法只接受String作为参数,因此转换无论如何都会发生。

这是Java中的常见问题吗?任何人都可以推荐一个解决方案(除了联系框架开发人员要求他们修改他们的方法!)?

更新

游戏节奏非常快,得分部分取决于自当前“舞台”开始以来经过的时间。它每秒更新15次。

我们没有保留对字符串的引用,但我想也许框架正在泄漏或复制这些字符串,所以我试图调查它(它不是一个公共框架,据我所知它没有'已经用于这种快节奏的游戏了。)

汇集是一个很好的建议,我想到了尝试,但是必须修改评分系统才能拥有一组固定的值。

2 个答案:

答案 0 :(得分:2)

我不确定它是否对您的特定情况有帮助,但一般情况下,当您使用某些固定集字符串值时,添加所有字符串值是有意义的字符串池。在这种情况下,您可以强制JVM不为每个新字符串在堆上创建对象,而是使用字符串池。

您必须更改代码才能从池中返回字符串,例如:

return String.valueOf(123).intern();

来自javadoc的一些额外解释:

  

当调用intern方法时,如果池已经包含一个等于此String对象的字符串(由equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。

答案 1 :(得分:0)

我们最终通过创建我们自己的可修改字符串类来解决问题,该类由固定长度的char数组支持,并在初始化后编写我们自己的文本呈现方法,零分配。

在此之后,一切都运行得更顺利,但我们仍然有一些由GC引起的“冻结”。在分析之后,事实证明这是由于在主游戏循环期间在循环中创建的大量迭代器。然后我们编写了一个使用迭代器池的自定义数组类,现在一切运行都很棒!