Question

Comment puis-je compiler du code Java à partir d'une chaîne arbitraire (en mémoire) dans Java 5 et Java 6, le charger et exécuter une méthode spécifique sur celle-ci (prédéfinie)?

Avant de flamber cela, j’ai examiné les implémentations existantes:

  • La plupart reposent sur l'API du compilateur Java 6.
  • Ceux qui ne le font pas, comptent sur des astuces.
  • Oui, j'ai vérifié commons-jci. Soit je suis trop dense pour comprendre comment ça marche, ou ça ne marche pas.
  • Je n'ai pas trouvé comment alimenter le compilateur avec mon chemin d'accès actuel (ce qui est assez énorme).
  • Sur l'implémentation qui a fonctionné (sous Java 6), je n'ai pas trouvé comment charger correctement les classes internes (ou les classes anonymes internes).
  • Je préférerais que tout soit en mémoire, car il fonctionne sur plusieurs environnements.

Je suis sûr que cela a déjà été résolu, mais je ne trouve rien sur Google qui ressemble à une qualité de demi-production (à l'exception de jci, que, comme je l'ai déjà dit, je n'ai pas réussi à l'utiliser). .

Modifier:

  • J'ai consulté JavaAssist. J'ai besoin de classes internes, de la prise en charge du niveau de langage Java 5.0 et de la compilation avec le chemin d'accès aux classes complet. Aussi, j'aimerais créer de nouvelles classes à la volée. je peut se tromper, mais je ne trouvais pas comment faire cela avec JavaAssit.
  • Je souhaite utiliser une solution basée sur un système de fichiers (appelant javac), mais je ne sais pas comment deviner le classpath, ni comment charger ultérieurement les fichiers (qui ne figurent pas dans mon classpath) avec un chargeur de classe spécial. qui peut être recyclé pour plusieurs invocations. Bien que je sache comment faire des recherches, je préférerais une solution toute prête.

Edit2: Pour le moment, je me contente de BeanShell "évaluer". Apparemment, il fait tout ce dont j'ai besoin (obtenir une chaîne, l’évaluer dans le contexte du chemin de classe "actuel". Il manque certaines fonctionnalités de Java 5, mais il peut utiliser des énumérations (non définies) et une compilation "générique" (effacé). ), cela devrait donc suffire à ce que je veux.

Je ne veux pas marquer la réponse comme acceptée pour le moment car j'espère qu'une meilleure solution se présentera.

Edit3: Acceptation de la suggestion de beanshell - cela fonctionne vraiment à merveille.

Était-ce utile?

La solution

Si vous n'êtes pas complètement lié à la compilation, des solutions telles que Beanshell, groovy et les autres langages de script sont facilement intégrées (en fait, Java prend en charge de manière intégrée la connexion à un langage de savoir dans quelle langue le script est écrit)

Beanshell devrait exécuter n'importe quel code IIRC à code java à 100%, et je pense que Groovy peut exécuter la plupart des codes java, voire tous.

Autres conseils

JCI a l’air bien. Cet extrait de code devrait être votre base:

JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse");

MemoryResourceReader mrr = new MemoryResourceReader();
mrr.add("resource name string", yourJavaSourceString.getBytes());

MemoryResourceStore mrs = new MemoryResourceStore();

CompilationResult result = compiler.compile(sources, mrr, mrs);

// don't need the result, unless you care for errors/warnings
// the class should have been compiled to your destination dir

Une raison pour que cela ne fonctionne pas?


Modifier: a ajouté un MemoryResourceStore pour envoyer la sortie de la classe compilée en mémoire, comme demandé.

Vous pouvez également définir les paramètres javac , comme classpath dans votre cas, via setCustomArguments (String [] pCustomArguments) dans JavacJavaCompilerSettings classe.

Vous pouvez également consulter Janino.

À partir de leur site Web:

Janino est un compilateur qui lit une expression JavaTM, un bloc, un corps de classe, un fichier source ou un ensemble de fichiers source, et génère un bytecode JavaTM chargé et exécuté directement. Janino n'est pas destiné à être un outil de développement, mais un compilateur intégré à des fins de compilation au moment de l'exécution, par exemple. évaluateurs d'expression ou "pages de serveur" des moteurs comme JSP.

http://www.janino.net/

Je l'utilise actuellement dans un assez gros projet critique et cela fonctionne très bien

Javassiste pourrait vous intéresser

Exécutez-vous dans un conteneur Web tel que Tomcat et générez d’abord une page JSP, puis appelez-la.

Cela vous permet également de vous débarrasser des anciennes définitions de classe en remplaçant simplement la page JSP au lieu de laisser votre chargeur de classe s'exécuter lentement.

Est-ce que le "en mémoire" est exigence en raison de la vitesse ou en raison de ne pas changer la base de code?

compilateur Java EJ Eclipse de la CJE

Eclipse fournit et utilise son propre compilateur qui n'est pas javac

  • Le compilateur Eclipse est utilisé dans l'IDE (Eclipse)
  • Le compilateur Eclipse peut également être utilisé comme compilateur par lots pur en dehors d’Eclipse

Compiler un fichier source

$ java -jar ecj-3.5.2.jar HelloWorld.java

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