es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Java Reflect newInstance() causando una ConcurrentModificationException (CME) que resulta en un fallo.

Para resumir mi proyecto, estoy tratando de hacer un procesador de eventos que ejecute métodos de una lista dada de métodos. Para invocar estos métodos, necesito pasar en la nueva instancia del método. El método se ejecuta correctamente, sin embargo, justo después de que todo el programa falla con una “ConcurrentModificationException”.

Uno de los métodos que deseo llamar es:

@EventAnnotation()
public void eventKeyInputeTest(EventKeyInput event)
{
    System.out.println("¡Prueba de EventKeyInput!");
}

Por favor, háganme saber si necesito proporcionar más código. ¡Gracias por cualquier ayuda!

Editar: añadí la clase donde cambio el método.

¿Hay alguna otra forma de abordar esto?

@EventHandler
private Listener<eventkeyinput> eventKeyInput = new Listener<>(event ->
{
    for(Method m : event.getMethods())
    {
        try {
            m.invoke(m.getDeclaringClass().newInstance(), event);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

});

“`
for(Method m : listenable.getClass().getMethods())
{
if(m.isAnnotationPresent(EventAnnotation.class))
{
Parameter[] params = m.getParameters();
if(params.length != 1)
{
System.out.println("¡Necesita 1 parámetro de evento!");
}

<pre><code> Class<?> eventType= params[0].getType();

try {
Object methods = eventType.getMethod("getMethods").invoke(eventType.newInstance(), null);
Method add = List.class.getDeclaredMethod("add", Object.class);
add.invoke(methods, m);
eventType.getMethod("setMethods", ArrayList.class).invoke(eventType.newInstance(), methods);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
</code></pre>

“`

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Posible solución para el error ConcurrentModificationException en Java

    El error ConcurrentModificationException ocurre generalmente cuando se modifica una colección mientras se está iterando a través de ella. En el código proporcionado, este error ocurre porque estamos iterando a través de una lista de métodos e invocándolos usando newInstance, lo cual crea una nueva instancia de la clase cada vez, mientras que la lista todavía puede ser modificada por otros hilos.

    Una solución a este problema es usar un bloque sincronizado para prevenir que múltiples hilos modifiquen la lista al mismo tiempo. Otra solución es crear una nueva lista de métodos antes de iterar a través de ella, usando:

    List<method> methods = new ArrayList<>(event.getMethods());
    for(Method m : methods)
    {
        // invocar método
    }
    

    Esto creará una nueva lista y eliminará la posibilidad de modificación durante la iteración.

    Adicionalmente, podemos usar la clase java.util.concurrent.CopyOnWriteArrayList, que provee una implementación segura para hilos de la interfaz List. Podemos reemplazar la lista existente con una CopyOnWriteArrayList modificando el código de la siguiente manera:

    for(Method m : event.getMethods())
    {
        try {
            m.invoke(m.getDeclaringClass().newInstance(), event);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    a

    CopyOnWriteArrayList<method> methods = new CopyOnWriteArrayList<>(event.getMethods());
    for(Method m : methods)
    {
        try {
            m.invoke(m.getDeclaringClass().newInstance(), event);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    Esto creará una lista segura para hilos y se asegurará de que no sea modificada mientras se itera a través de ella.

    En general, es importante sincronizar adecuadamente y manejar múltiples hilos para prevenir errores ConcurrentModificationException en Java.

Comments are closed.