StackOverflow ao chamar `Convert.toString` em ambiente de CI
Em ambiente de CI (imagem do Docker maven:3-jdk-8), alguma coisa estranha aconteceu e passou a ocorrer um erro de StackOverflow. Não consegui identificar qual foi a minha chamada ao TotalCross que gerou essa encrenca (nas 1024 linhas impressas no Throwable.printStackTrace() não foi possível averiguar onde estava o problema no meu código), mas ele apresentou a seguinte repetição:
at totalcross.sys.Convert.toString(totalcross-sdk-4.3.8:601)
at totalcross.sys.Convert.toString(totalcross-sdk-4.3.8:641)
at totalcross.sys.Convert.toString(totalcross-sdk-4.3.8:601)
at totalcross.sys.Convert.toString(totalcross-sdk-4.3.8:641)
Estou usando a dependência com.totalcross:totalcross-sdk:4.3.8. Analisando o source distribuído, o bug realmente é esperado de acontecer.
Olhe a função Convert.toString(long), linhas 599-602 copiadas para cá:
@ReplacedByNativeOnDeploy
public static String toString(long l) {
return toString(l, 10);
}
Olhe a função Convert.toString(long, int), que é chamada pela Convert.toString(long) (linhas 633-659 copiadas):
public static String toString(long i, int radix) {
if (radix < 2 || radix > 16) {
throw new java.lang.IllegalArgumentException("Invalid value for argument 'radix'");
}
if (i == 0) {
return "0";
}
if (radix == 10 && useNative) {
return toString(i);
}
char[] buf = new char[radix >= 8 ? 23 : 65];
int pos = buf.length;
boolean negative = (i < 0);
if (!negative) {
i = -i;
}
while (i <= -radix) {
buf[--pos] = forDigit((int) (-(i % radix)), radix);
i /= radix;
}
buf[--pos] = forDigit((int) (-i), radix);
if (negative && radix == 10) {
buf[--pos] = '-';
}
// reverse and return the string
return new String(buf, pos, buf.length - pos);
}
Tem a condição na linha 640 que é a seguinte: se radix (o parâmetro inteiro) for 10, então (linha 641) chame Convert.toString(long). Por sua vez, Convert.toString(long) chama trivialmente Convert.toString(long, int) passando o parâmetro recebido e radix == 10.
Esse erro não acontece no nativo já que Convert.toString(long) está anotada com @ReplacedByNativeOnDeploy. Na 5.1.1 não foi corrigido.
Também não sei o que aconteceu para passar a disparar esse, mas aparentemente foi algo relacionado a usar o totalcross.util.BigDecimal no lugar de java.math.BigDecimal na minha classe wrapper de BigDecimal a nível de execução Java.