Le proxy Clojure 1.2.1 / 1.3 / 1.4 'généré dans le runtime Grails 2.0.0 échoue. 1.2.0 c'est bien

103

Je travaille sur l'extension du plugin Grails Clojure dans Grails 2.0.0 (et 2.1.0-SNAPSHOT) et je voulais le mettre à jour vers Clojure 1.3.0 et ajouter clojure.tools.logging .

Clojure lève une exception lors de la compilation d'un proxy de la fonction log-stream d'un ByteArrayOutputStreamin clojure.tools.logging:

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

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

Je suis allé et enlevé clojure.tools.logginget ai écrit un proxy dépouillé de Object:

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

et il a également jeté ce même ClassCastExceptionmessage.

J'ai essayé d'imprimer une macroexpand-1 du proxy et j'ai obtenu la même chose.

Je suis revenu à Clojure 1.2.0 et le proxy fonctionnait à nouveau correctement.

J'ai essayé un certain nombre d'incarnations de 1.4.0 et elles présentent le même comportement que 1.3.0. 1.2.1 lève également une sorte d'exception, mais j'essaie d'atteindre 1.3.0, donc je n'ai pas passé beaucoup de temps avec ça.

La trace de pile pointe vers la fonction 'gen-method définie dans l'une des formes let de generate-proxyin core_proxy.clj.

J'ai ajouté une petite poignée de println's autour de là pour voir si je pouvais comprendre ce qui se passait. Peut-être que cette prochaine déclaration trahira un énorme malentendu du lecteur de ma part, mais le simple fait d'ajouter ceux-ci a printlnchangé le comportement au moment de la compilation d'une manière à laquelle je ne m'attendais absolument pas. L'emplacement et le type d'exception ont complètement changé, même si tous les tests Clojure mvn packagecontinuent de réussir.

Par exemple, le simple fait d'ajouter un seul printlnà la méthode gen juste avant de commencer à générer le bytecode a provoqué le lancement de Clojure

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

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

J'ai vu diverses autres erreurs selon l'endroit où je place le println(s) mais c'est la plus répandue.

De toute évidence, certains aspects de Grails et Clojure ne sont pas correctement maillés ici, mais je ne vois pas la connexion. Au début, je soupçonnais une incompatibilité ASM, mais comme Clojure a son propre espace de noms ASM, je ne vois pas que ce soit le problème. Mais peut-être que je me trompe, je regarde clojure.lang.Compiler, proxy et generate-proxy depuis des jours maintenant pour essayer de faire fonctionner cela et j'ai quasiment arrêté d'avancer parce que je suis à bout de souffle :(

Je m'excuse pour le manque de liens. Vous pouvez copier et coller ci-dessous:

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

Clojure Tools Logging - github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging.clj line 133 est le 'proxy

John Courtland
la source
4
J'ai fait quelques tests supplémentaires et je suis presque convaincu que c'est quelque chose dans Grails 2.0 qui détruit quelque chose sur lequel Clojure 1.3 s'appuie. J'ai testé l'exemple de code le plus simple que je puisse concevoir dans Grails 1.3.7, Groovy 1.8.4 (qui est ce que Grails 2.0 utilise) et Groovy 1.8.5 (le dernier) et tout cela fonctionne.
John Courtland
3
Cela pourrait-il être un problème de ClassLoader?
Jeremy

Réponses:

4

J'ai trouvé un problème appelé CLJ-944sur clojure.org . Là, vous pouvez trouver un correctif pour le ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.Classproblème

Le problème est:

que le compilateur injecte un cast incorrect dans clojure.lang.PersistentHashMap. Dans ce cas, il devrait probablement être converti en clojure.lang.Associative, l'interface commune la plus élevée ayant la méthode .containsKey.

Patch 1 - 0001-Correctif pour CLJ-944.patch

Patch 2 - 0002-Correctif pour CLJ-944.patch

J'espère que cela aide.

Sentencio
la source