4

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

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

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

更新:

游戏节奏非常快,分数部分基于从当前“阶段”开始所经过的时间。它每秒更新 15 次。

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

池化是一个很好的建议,我想尝试一下,但是必须修改评分系统才能获得一组固定的值。

4

2 回答 2

2

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

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

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

javadoc的一些额外解释:

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

于 2013-03-02T17:11:23.833 回答
0

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

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

于 2013-03-05T13:56:36.200 回答