El proxy de Clojure 1.2.1 / 1.3 / 1.4 'generado en el tiempo de ejecución de Grails 2.0.0 falla. 1.2.0 está bien

103

Estoy trabajando para extender el complemento Grails Clojure en Grails 2.0.0 (y 2.1.0-SNAPSHOT) y quería actualizarlo a Clojure 1.3.0 y agregar clojure.tools.logging .

Clojure lanza una excepción durante la compilación de un proxy de la función de flujo de registro de ByteArrayOutputStreamin clojure.tools.logging:

ClassCastException: clojure.asm.Type cannot be cast to clojure.lang.IFn

( https://gist.github.com/a6ae681c37091a3d2379 )

Fui, eliminé clojure.tools.loggingy escribí un proxy reducido de Object:

(proxy [java.lang.Object] [] (toString [] "proxy's toString"))

y también lanzó ese mismo ClassCastExceptionmensaje.

Intenté imprimir una macroexpand-1 del proxy y obtuve lo mismo.

Volví a Clojure 1.2.0 y el proxy funcionó bien nuevamente.

Probé varias encarnaciones de 1.4.0 y exhiben el mismo comportamiento que 1.3.0. 1.2.1 también arroja algún tipo de excepción, pero estoy tratando de llegar a 1.3.0, así que no pasé mucho tiempo con eso.

El seguimiento de la pila apunta a la función 'gen-method definida en una de las formas let de generate-proxyin core_proxy.clj.

Agregué un pequeño puñado de println's por ahí para ver si podía captar lo que estaba sucediendo. Tal vez esta próxima declaración traicione un gran malentendido por parte del lector de mi parte, pero simplemente agregar esos printlns cambió el comportamiento del tiempo de compilación de una manera que no esperaba. La ubicación de la excepción y el tipo de excepción cambiaron por completo, aunque todas las pruebas de Clojure mvn packagecontinúan pasando.

Por ejemplo, simplemente agregar un printlnmétodo único a gen justo antes de que comience a generar bytecode hizo que Clojure arrojara

ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.Class

( https://gist.github.com/5a7a40929a6c4a104bd5 )

He visto varios otros errores dependiendo de dónde coloque los errores, printlnpero este es el más frecuente.

Obviamente, algunos aspectos de Grails y Clojure no se combinan correctamente aquí, pero no veo la conexión. Al principio sospeché incompatibilidad con ASM, pero como Clojure tiene su propio espacio de nombres ASM, no veo que ese sea el problema. Pero tal vez me equivoque, he estado mirando clojure.lang.Compiler, proxy y generate-proxy durante días tratando de que esto funcione y prácticamente dejé de avanzar porque me quedé sin fuerza :(

Pido disculpas por la falta de enlaces. Puede copiar y pegar desde abajo:

Grails Clojure - github.com/grails-plugins/grails-clojure

Registro de herramientas de Clojure - github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging.clj línea 133 es el 'proxy

John Courtland
fuente
4
He hecho algunas pruebas más y estoy casi convencido de que hay algo en Grails 2.0 que está arruinando algo en lo que Clojure 1.3 se basa. Probé la muestra de código más simple que puedo concebir en Grails 1.3.7, Groovy 1.8.4 (que es lo que usa Grails 2.0) y Groovy 1.8.5 (el último) y todos funcionan.
John Courtland
3
¿Podría ser esto un problema de ClassLoader?
Jeremy

Respuestas:

4

He encontrado un problema denominado CLJ-944en clojure.org . Allí puede encontrar una solución para el ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.Classproblema

El problema es:

que el compilador inyecta una conversión incorrecta en clojure.lang.PersistentHashMap. En este caso, probablemente debería convertirse en un clojure.lang.Associative, la interfaz común más alta que tiene el método .containsKey.

Parche 1 - Parche 0001-Fix-for-CLJ-944.

Parche 2 - Parche 0002-Fix-for-CLJ-944.

Espero que ayude.

Sentencio
fuente