parsear example converting convert java jvm java-8 jvm-hotspot

example - string to int java 6



¿Cómo es posible ArrayOutOfBoundsException en String.valueOf(int)? (3)

Este es un error del compilador JIT que se ha introducido en JDK 8u20 como un efecto secundario de otra solución:
JDK-8042786

El problema está relacionado con la optimización de eliminación automática de boxeo.
La -XX:-EliminateAutoBox consiste en desactivar la optimización mediante -XX:-EliminateAutoBox indicador JVM

Parece que el problema también existe en la base de origen JDK 9 más reciente.
He enviado el informe de error: https://bugs.openjdk.java.net/browse/JDK-8058847 con un caso de prueba mínimo reproducible al 100% incluido.

¿Por qué este código a veces produce ArrayOutOfBoundsException? ¿Cómo es eso posible para String.valueOf(int) ?

public static String ipToString(ByteString bs) { if (bs == null || bs.isEmpty()) { return null; } else { StringBuilder sb = new StringBuilder(); boolean started = false; for (Byte byt : bs) { if (started) { sb.append("."); } sb.append(String.valueOf(byt & 0xFF)); started = true; } return sb.toString(); } } java.lang.ArrayIndexOutOfBoundsException: -81914 at java.lang.Integer.getChars(Integer.java:458) at java.lang.Integer.toString(Integer.java:402) at java.lang.String.valueOf(String.java:3086) at com.mystuff.mypackage.ipToString(MyCode.java:1325) ... at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

Actualizaciones

No sé el valor del byte cuando esto ocurre, pero parece que no debería ser posible para cualquier valor posible de byte.

Una vez que sucede una vez, cada invocación se produce un error con la misma excepción.

Ambiente:

java version "1.8.0_20" Java(TM) SE Runtime Environment (build 1.8.0_20-b26) Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)


Estoy dejando el fragmento de código aquí, ya que aún debería ejecutarse más rápido que el código original, a un costo de memoria, pero tenga en cuenta que en realidad no soluciona el problema.

private static final String[] STRING_CACHE = new String[256]; static { for(int i = 0; i <= 255; i++) { STRING_CACHE[i] = String.valueOf(i); } } public static String ipToString(ByteString bs) { if (bs == null || bs.isEmpty()) { return null; } else { StringBuilder sb = new StringBuilder(); boolean started = false; for (Byte byt : bs) { if (started) { sb.append("."); } sb.append(STRING_CACHE[byt & 0xFF]); started = true; } return sb.toString(); } }


Puedo reproducir de forma confiable su problema con este código:

public class Main { public static StringBuilder intToString(byte[] bs) { final StringBuilder sb = new StringBuilder(); boolean started = false; for (Byte byt : bs) { if (started) sb.append("."); sb.append(String.valueOf(byt & 0xFF)); started = true; } return sb; } public static void main(String[] args) { final byte[] bs = {-2, -1, 0, 1, 2}; while (true) intToString(bs); } }

Es casi seguro que el problema se debe a un error del compilador JIT. Su observación de que, una vez que sucede la primera vez, ocurre de manera confiable en cada llamada subsiguiente, apunta limpiamente a un evento de compilación JIT que introduce el código con errores en la ruta de código.

Si está disponible para usted, puede activar las opciones de diagnóstico de JVM que imprimirán todos los eventos de compilación ( -XX:PrintCompilation ). Entonces podrá correlacionar un evento de este tipo con el momento en que comienza a aparecer la excepción.