Question

Juste par curiosité, sont-il des (stables) des projets open source pour la génération de code Java Runtime autre que cglib? Et pourquoi devrais-je les utiliser?

Était-ce utile?

La solution

ASM java-asm

CGLIB et presque toutes les autres bibliothèques sont construites sur le dessus de l'ASM qui agit elle-même sur un très bas niveau. Ceci est un show-bouchon pour la plupart des gens que vous devez comprendre le code d'octets et un peu de JVMs pour l'utiliser correctement. Mais la maîtrise de l'ASM est certainement très intéressant. A noter cependant que si il y a un grand ASM 4 Guide , dans une partie de l'API la documentation javadoc peut être très concise si elle est présente à tous, mais il est en cours d'amélioration. Il suit de près les versions de JVM pour supporter de nouvelles fonctionnalités.

Cependant, si vous avez besoin de contrôle complet, ASM est votre arme de choix.

Ce projet voit des mises à jour régulières; au moment de cette édition la version 5.0.4 a été publié le 15 mai à 2015.

octets amis

Byte Buddy est une bibliothèque plutôt nouvelle mais offre une fonctionnalité qui CGLIB ou Javassist fournit et bien plus encore. Byte d'amis peut être entièrement personnalisé vers le bas au niveau du code octet et est livré avec un langage spécifique de domaine expressif qui permet un code très lisible.

  • Il prend en charge toutes les versions de bytecode JVM, y compris Java 8 changements sémantiques de certains opcodes concernant les méthodes par défaut.
  • ByteBuddy ne semblent pas souffrir des inconvénients d'autres bibliothèques ont
  • hautement configurable
  • assez rapide ( référence Code )
  • Type sécurité API couramment
  • Type callbacks sécurité

      

    conseils Javassist ou le code d'instrumentation personnalisé est basé sur le code dans une String plaine de type ainsi vérifier et le débogage est impossible dans ce code, alors que ByteBuddy permet d'écrire les avec Java pur fait appliquer donc de type contrôles et permet le débogage.

  • Annotation entraîné (flexible)

      

    Les callbacks utilisateur peuvent être configurés avec des annotations permettant de recevoir les paramètres désirés dans le rappel.

  • Disponible en tant qu'agent

      

    Le générateur astucieux d'agent permet ByteBuddy à être utilisé comme agent pur ou en tant qu'agent de fixation. Il permet différents types

  • Très bien documenté
  • Beaucoup d'exemple
  • Un code propre, ~ 94% de couverture de test
  • Support Android DEX

Le principal inconvénient peut-être, serait l'API est un peu bavard pour un débutant, mais il est conçu comme un opt-in API en forme de DSL de génération de proxy; il n'y a pas de magie ou par défaut douteux. Lors de la manipulation du byte code, il est probablement le plus sûr et le choix le plus raisonnable. En outre avec plusieurs exemples et un grand tutoriel ce n'est pas un vrai problème.

En Octobre 2015 projets ont reçu le prix du choix d'Oracle Duke . A ce moment, il vient d'atteindre le rel="noreferrer"> étape 1.0.0 , ce qui est tout un exploit.

Notez que a remplacé CGLIB par octet dans la version copain 2.1.0.

Javassist

Le javadoc de Javassist est bien meilleure que celle de CGLIB. L'API d'ingénierie de classe est OK, mais Javassist est pas parfait non plus. En particulier, le ProxyFactory qui est l'équivalent de Enhancer du CGLIB souffrent de quelques inconvénients aussi, juste pour citer quelques-uns:

  • Méthode de pont ne sont pas entièrement pris en charge (par exemple celui qui sont générés pour les types de retour covariantes)
  • ClassloaderProvider est un champ statique au lieu, il applique à toutes les instances dans le même classloader
  • dénomination personnalisée aurait été la bienvenue (avec des chèques pour les pots signés)
  • Il n'y a pas de point d'extension et presque toutes les méthodes d'intérêt sont privées, ce qui est lourd si nous voulons changer un comportement
  • Alors que le soutien de l'offre Javassist pour l'annotation des attributs dans les classes, ils ne sont pas pris en charge dans ProxyFactory.

Du côté orienté aspect, on peut injecter du code dans un proxy, mais cette approche dans Javassist est limitée et sujette à erreur binaire:

  • code aspect est écrit dans une plaine String Java qui est compilé dans opcodes
  • aucune vérification de type
  • pas de génériques
  • pas lambda
  • pas automatique (non) la boxe

En outre Javassist est reconnu pour être plus lent que Cglib. Ceci est principalement dû à son approche des fichiers de classe de lecture au lieu des classes chargées de lecture comme comme le fait CGLIB. Et la mise en œuvre rel="noreferrer"> lui-même est difficile à lire pour être juste; si on a besoin de faire des changements dans le code Javassist il y a beaucoup de chances de casser quelque chose.

Javassist a souffert d'inactivité, ainsi, leur déménagement github vers 2013 semble avoir prouvé leur utilité, car il montre commits réguliers et tirer les demandes de la communauté.

Ces limites sont encore debout dans la version 3.17.1. Version a été heurté à la version 3.20.0, mais il semble Javassist peut encore avoir des problèmes avec le support de Java 8.

JiteScript

JiteScript ne semble comme un nouveau morceau de mise en forme bien en DSL pour l'ASM, cela est basé sur la dernière version de l'ASM (4.0). Le code a l'air propre.

Mais le projet est encore à son jeune âge peut changer si API / comportement, ainsi que la documentation est désastreuse. Et les mises à jour rares sinon abandonnés.

Proxetta Jodd

Ceci est un outil assez nouveau, mais il offre de loin le meilleur humain API. Il permet de différents types de procurations tels que les proxies sous-classe (approche cglib) ou le tissage ou la délégation.

Bien que, celui-ci est assez rare, aucune information existe si elle fonctionne bien. Il y a tellement de cas d'angle pour traiter lorsqu'ils traitent avec bytecode.

AspectJ

AspectJ est un outil très puissant pour programmation orientée aspect (uniquement). AspectJ manipule bytecode pour atteindre ses objectifs tels que vous pourriez être en mesure d'atteindre vos objectifs avec elle. Cependant, cela nécessite une manipulation à la compilation; Offre de printemps tissage au moment de la charge par l'intermédiaire d'un agent depuis la version 2.5 , 4.1.x .

CGLIB

Un mot sur CGLIB qui a été mis à jour depuis cette question a été posée.

CGLIB est assez rapide, il est l'une des principales raisons pour lesquelles il est toujours là, de même que le fait que CGLIB a travaillé presque mieux que toutes les alternatives jusqu'à présent (2014-2015).

D'une manière générale des bibliothèques qui permettent la réécriture des classes au moment de l'exécution doivent éviter de charger tous les types avant la classe correspondante est réécrite. Par conséquent, ils ne peuvent pas utiliser l'API de réflexion Java qui exige que tout type utilisé dans la réflexion est chargé. Ils ont plutôt de lire les fichiers de classe via IO (qui est un briseur de performance). Cela rend par exemple Javassist ou Proxetta significativement plus lent que Cglib qui lit simplement les méthodes via l'API de réflexion et les remplace.

Cependant, CGLIB n'est plus en cours de développement. Il y avait des versions récentes, mais ces changements ont été considérés comme insignifiants par beaucoup et la plupart des gens ne jamais mettre à jour à la version 3 depuis CGLIB introduit certains bogues sévères dans les dernières versions ce qui ne construisent pas vraiment confiance. Version 3.1 fixe beaucoup des malheurs de la version 3.0 (depuis la version 4.0.3 framework Spring reconditionne version 3.1 )

En outre, le code source CGLIB est plutôt mauvaise qualité telle que nous ne voyons pas de nouveaux développeurs participant au projet CGLIB. Pour une impression de activeness de CGLIB, consultez leur rel="noreferrer"> mailing liste.

Notez que la suite d'un , CGLIB est maintenant disponible sur github pour permettre la communauté pour mieux aider le projet, il semble fonctionner (plusieurs commits et demandes, tirer ci, Maven mis à jour), mais la plupart des inquiétudes subsistent encore.

A ce moment là travaillent sur la version 3.2.0, et ils se concentrent sur les efforts Java 8, mais les utilisateurs qui veulent à ce jour que le support de Java 8 doivent utiliser des tours au moment de la construction. Mais les progrès sont très lents.

Et CGLIB est encore connu pour être en proie à des fuites de mémoire PermGen. Mais d'autres projets peuvent ne pas avoir été bataille testé depuis tant d'années.

compilation Traitement des annotations de temps

Celui-ci n'est pas l'exécution bien sûr, mais est une partie importante de l'écosystème, et l'utilisation plus de génération de code ne pas besoin de création d'exécution.

Cela a commencé avec Java 5 qui est venu avec l'outil de ligne de commande séparée pour traiter les annotations:. apt, et à partir de traitement d'annotation Java 6 est intégré dans le compilateur Java

À un moment donné vous devez passer explicitement le processeur, maintenant avec l'approche ServiceLoader (il suffit d'ajouter ce fichier META-INF/services/javax.annotation.processing.Processor dans le pot), le compilateur peut détecter automatiquement le processeur d'annotation.

Cette approche à la génération de code a aussi des inconvénients, il nécessitent beaucoup de travail et de la compréhension du langage Java ne bytecode. Cette API est un peu lourd, et comme un plug-in est dans le compilateur il faut prendre soin de rendre ce code le message d'erreur la plus résiliente et facile à utiliser.

Le plus grand avantage est que cela évite une dépendance à l'exécution, vous pouvez éviter PermGen fuite de mémoire. Et on a le plein contrôle sur le code généré.

Conclusion

2002 CGLIB a défini une nouvelle norme pour manipuler bytecode avec facilité. De nombreux outils et méthodologie (CI, couverture, TDD, etc.), nous avons de nos jours ne sont pas disponibles ou non viennent à échéance à ce moment-là. CGLIB a réussi à être pertinent pour plus d'une décennie; c'est une réalisation assez décent. Il était rapide et avec une API facile à utiliser que de manipuler directement opcodes.

Il a défini une nouvelle norme en ce qui concerne la génération de code, mais aujourd'hui il est plus maintenant parce que l'environnement et les besoins ont changé, ont les normes et les objectifs.

La machine virtuelle Java a changé et va changer dans l'avenir récente et Java (7/8/9/10) (versions invokedynamic, les méthodes par défaut, les types de valeurs, etc.). ASM mis à jour son API et de suivre régulièrement internals ces changements, mais CGLIB et d'autres ont encore de les utiliser.

Alors que le traitement d'annotation devient la traction, il est pas aussi flexible que la génération d'exécution.

En 2015, Byte amis - tout plutôt nouvelle sur la scène - offrir les plus convaincants la vente points pour la génération d'exécution. Un taux de mise à jour décent, et l'auteur a une connaissance intime du byte code Java internes.

Autres conseils

Javassist .

Si vous avez besoin de faire des procurations, jetez un oeil à commons-proxy - il utilise à la fois CGLIB et Javassit.

Je préfère ASM , que je crois est utilisé par cglib de toute façon. Il est faible, mais la documentation est brillant , et une fois que vous y habituer, vous volerez.

Pour répondre à votre deuxième question, vous devez utiliser la génération de code lorsque votre réflexion et proxies dynamiques commencent à se sentir un peu bricolée et vous avez besoin d'une solution solide de roche. Dans le passé, je l'ai même ajouté une étape de génération de code dans le processus de construction dans Eclipse, me donnant effectivement compilera les données concernant le temps de tout et tout.

Je pense qu'il est plus judicieux d'utiliser Javassist au lieu de cglib. Par exemple. javasist fonctionne parfaitement avec des pots signés contrairement cglib. D'ailleurs, si grand que le projet Hibernate a décidé de cesser d'utiliser cglib en faveur de Javassist.

CGLIB a été conçu et mis en œuvre il y a plus de dix ans dans l'ère de l'AOP et ORM. À l'heure actuelle, je ne vois aucune raison de l'utiliser et je ne prétends pas plus cette bibliothèque (à l'exception des corrections de bugs pour mes applications existantes). En fait, tous CGLIB des cas d'utilisation j'ai jamais vu sont des modèles dans les programmes anti-moderne. Il devrait être trivial à mettre en œuvre les mêmes fonctionnalités via un langage de script machine virtuelle Java par exemple groovy.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top