¿Está bien usar la instancia de Gson como un campo estático en un bean modelo (reutilizar)?

5 minutos de lectura

avatar de usuario
felipe

Aquí está el modelo que implementé:

public class LoginSession {
    private static final Gson gson = new Gson();

    private String id;
    private String name;
    private long timestamp;

    public LoginSession(String id, String name) {
        this.id = id;
        this.name = name;
        this.timestamp = System.currentTimeMillis();
    }

    public String toJson() {
        return gson.toJson(this);
    }

    public static LoginSession fromJson(String json) {
        checkArgument(!isNullOrEmpty(json));
        return gson.fromJson(json, LoginSession.class);
    }
}

Pensé que era inútil crear una nueva instancia de Gson para cada instancia de LoginSession.

Pero lo que me preocupa son los problemas de seguridad de subprocesos. Se crearán aproximadamente más de 1000 instancias por segundo.

¿Está bien usar la instancia de Gson como campo estático?

Gracias por cualquier consejo/correcciones.

avatar de usuario
MByD

Me parece bien. No hay nada en la instancia de GSON que la relacione con una instancia específica de LoginSessionpor lo que debe ser estático.

Instancias GSON debe ser seguro para subprocesosy había un error con respecto a lo que estaba arreglado.

  • @slott, ¿cómo agrupan/reutilizan las instancias de Gson? ¿Crea una instancia cada vez que necesita serializar? ¿O usar un grupo threadlocal?

    – Dilum Ranatunga

    29/10/2013 a las 19:19

  • Usamos GSON junto con Google Volley y cuando analizamos los datos JSON al mismo tiempo, vemos este problema. Por lo que puedo ver, esto está relacionado con el hecho de que definimos una marca de tiempo para analizar los valores de fecha y hora.

    – ranura

    30/10/2013 a las 13:15

  • Datetime no es seguro para subprocesos, esa puede ser la causa, no es que GSON no sea seguro para subprocesos.

    – Andreas Mattison

    29 de noviembre de 2016 a las 10:55

avatar de usuario
empollón

El núcleo Gson la clase es segura para subprocesos. Acabo de encontrar un problema de seguridad de subprocesos que supuestamente estaba relacionado con GSON. El problema ocurrió al usar un personalizado JsonDeserializer y JsonSerializer por Date análisis y formateo. Al final resultó que, el problema de seguridad de subprocesos estaba relacionado con el uso de mi método de una estática SimpleDateFormat instancia que no es segura para subprocesos. Una vez que envolví la estática SimpleDateFormat en un ThreadLocal ejemplo, todo salió bien.

  • Una mejor opción puede ser usar Apache commons FastDateFormat (parte de commons-lang), que es explícitamente seguro para subprocesos. commons.apache.org/proper/commons-lang/apidocs/org/apache/…

    – Marceau

    3 de octubre de 2016 a las 8:51

  • Gracias @Zaan. ¡Gran consejo!

    – empollón

    3 oct 2016 a las 17:24

  • Estaba usando Gson y SimpleDateFormat y obtenía errores de hilo en Gson.fromJson. Resulta que la clase a la que me estaba convirtiendo tenía un HashMap no seguro para subprocesos. Lo cambié a ConcurrentHashMap y todo funciona perfectamente.

    – Gregory Alan Bolcer

    31 de diciembre de 2020 a las 20:22

avatar de usuario
christophe roussy

Según los comentarios, la prueba de unidad existente realmente no prueba mucho, tenga cuidado con todo lo relacionado con la seguridad de subprocesos…

Hay un prueba de unidad comprobando la seguridad del subproceso:

/**
 * Tests for ensuring Gson thread-safety.
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 */
public class ConcurrencyTest extends TestCase {
  private Gson gson;
  ...

Quizás se pregunte si esta prueba unitaria es suficiente para encontrar todos los problemas posibles en todas las configuraciones posibles de la máquina. ¿Algún comentario sobre esto?

También está esta frase en el documentos:

La instancia de Gson no mantiene ningún estado mientras invoca las operaciones de Json. Por lo tanto, puede reutilizar el mismo objeto para múltiples operaciones de serialización y deserialización de Json.

  • Hubiera dicho que esta prueba unitaria era lamentablemente inadecuada para detectar problemas de concurrencia. Primero, MyObject es una clase trivial sin colecciones complejas involucradas, por lo que no se prueba la deserialización simultánea de listas y mapas y otros objetos complejos. En segundo lugar, la serialización solo se itera 10 veces por cada uno de los 10 subprocesos, lo cual es inadecuado. En tercer lugar, las fallas de simultaneidad son notoriamente difíciles de probar porque las diferentes configuraciones de hardware tienen diferentes características de tiempo de ejecución, por lo que cualquier prueba solo sería válida si se garantiza que se ejecutará en todas las configuraciones.

    – Lawrence Dol

    04/12/2014 a las 20:40


  • Por ejemplo, es probable que esta prueba no encuentre ningún error de simultaneidad en una máquina de un solo núcleo, ya que cada subproceso probablemente se completará en un solo intervalo de tiempo y, por lo tanto, los subprocesos se ejecutarán consecutivamente, no simultáneamente.

    – Lawrence Dol

    04/12/2014 a las 20:41

  • No quiere decir que no sea seguro para subprocesos, solo que esta prueba no garantiza ni remotamente que lo sea.

    – Lawrence Dol

    04/12/2014 a las 20:43

  • La cuestión de “si esta prueba unitaria es suficiente para encontrar todos los posibles problemas en todas las configuraciones posibles de la máquina” es completamente irrelevante. Creo que cualquier conjunto de pruebas sería imposible encontrar todos los posibles problemas de concurrencia. Que tengan una prueba es un buen comienzo y luego se debe crear una nueva prueba para cada error de concurrencia que se solucione. Además, esto es de código abierto si quieres más pruebas, ve y escríbelas.

    – mjaggard

    11 de julio a las 10:45


Tuvimos problemas con la seguridad de subprocesos hace un tiempo y los resolvimos usando FastDateFormat en apache commons.

Acabo de crear una esencia Enlace para Gist alrededor de esto para ayudar a las personas que se preguntan si las instancias de Gson se pueden reutilizar. No tienen setters y todas las vars son privadas.

Entonces, aparte del problema de SimpleDateFormat, no los veo manteniendo el estado en ningún otro lugar.

verifique eso afuera. Esta es la primera vez que respondo a uno de estos. Feliz de devolver por una vez. 🙂

¿Ha sido útil esta solución?