Problemas de memoria con frecuentes conversiones de Integer.toString ()

Actualmente estoy en el proceso de portar un juego desarrollado en C # (para Windows Phone) a Java (Android).

Estamos teniendo problemas de memoria en la versión de Java que, después de perfilar, parecen venir de un gran número de objetos String en la memoria, evidentemente debido a la naturaleza inmutable de String 's. Ahora, he conseguido rastrear esto hasta el método que hace la puntuación del jugador a la pantalla, donde un Integer.toString() se utiliza cada vez que la puntuación cambia (muchas veces por segundo). Realmente no puedo usar un StringBuilder (esto es lo que tenemos en la versión C #) porque los métodos de renderización de texto del framework que estamos usando sólo aceptan String como argumentos, por lo tanto una conversión se produce de todos modos.

¿Es este un problema común en Java? ¿Alguien puede recomendar una solución (aparte de contactar con el framework devs para pedirles que modifiquen sus métodos)?

Actualizar:

El juego es muy rápido y la puntuación se basa en parte en el tiempo transcurrido desde el inicio de la actual "etapa". Se actualiza 15 veces por segundo.

No guardamos una referencia a la cadena, pero estoy pensando que tal vez el marco está filtrando o duplicando estas cadenas por lo que estoy tratando de mirar en eso (no es un marco público y que yo sepa que no se ha utilizado Para este tipo de juego de ritmo rápido todavía).

La agrupación es una buena sugerencia y pensé en intentarlo pero el sistema de puntuación tendría que ser modificado para tener un conjunto fijo de valores.

No estoy seguro de si ayuda en su caso particular, pero en general, cuando tiene un conjunto fijo de valores de cadena con los que está operando, tiene sentido añadir todos ellos a la agrupación de cadenas. En este caso, puede forzar a JVM a no crear objetos en el montón para cada nueva cadena, sino que utiliza el grupo de cadenas.

Tendrás que cambiar tu código para devolver cadenas de la agrupación, como por ejemplo:

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

Alguna explicación adicional de javadoc:

Cuando se invoca el método interno, si el grupo ya contiene una cadena igual a este objeto String determinado por el método equal (Object), se devuelve la cadena del conjunto. De lo contrario, este objeto String se agrega al grupo y se devuelve una referencia a este objeto String.

Terminamos resolviendo el problema creando nuestra propia clase de cadena modificable respaldada por una matriz de longitud fija y escribiendo nuestros propios métodos de renderización de texto con asignación cero una vez inicializada.

Después de esto, todo funcionó mucho más suavemente pero todavía teníamos algunas "heladas" causadas por GC. Después del perfilado, resultó que esto se debía a la gran cantidad de iteradores creados en bucles durante el bucle del juego principal. A continuación, escribió una clase de matriz personalizada que utiliza un grupo de iteradores, y ahora todo funciona muy bien!

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.