Pergunta

Como posso código de compilação java a partir de uma cadeia arbitrária (em memória) em Java 5 e Java 6, carregá-lo e executar um método específico sobre ele (pré-definido)?

Antes de chama isso, eu olhei para implementações existentes:

  • A maioria dependem de Java 6 Compiler API.
  • Aqueles que não o fazem, dependem de truques.
  • Sim, eu verifiquei commons-JCI. Ou eu sou muito denso para entender como ele funciona, ou ele simplesmente não faz.
  • Eu não poderia encontrar como alimentar o compilador meu caminho classe atual (que é bastante enorme).
  • Na implementação que trabalhou (em Java 6), eu não conseguia encontrar a forma de carregar corretamente classes internas (ou classes anônimas internas).
  • Eu tinha parecido com isso se a coisa toda era em memória, como a coisa funciona em vários ambientes.

Estou certo de que este tenha sido resolvido antes, mas eu não consigo encontrar nada que a qualidade aparência meia-produção, mesmo no google (exceto JCI, que, como eu disse antes, eu não conseguiram uso) .

Editar:

  • Olhei JavaAssist - Preciso classes internas, Java de suporte nível 5.0 linguagem e compilando com todo o classpath. Além disso, eu gostaria de criar novas classes na mosca. Eu pode estar enganado, mas eu não conseguia encontrar a forma de fazer isso com JavaAssit.
  • Eu estou disposto a usar uma solução baseada sistema de arquivos (chamando javac), mas eu não sei como adivinhar o classpath, nem como carregar mais tarde, os arquivos (que não estão no meu classpath) com um carregador de classe especial que pode ser reciclado para várias chamadas. Enquanto eu sei como pesquisá-lo, eu prefiro uma solução pronta.

Edit2: Por enquanto, estou contente com BeanShell "avaliar". Aparentemente, ele faz tudo o que eu preciso dele para (obter uma string, avaliá-lo no contexto do classpath 'atual'. Ele não perca alguns dos Java 5 características, mas pode usar enums (não definir) e compilados 'genérico' (apagado ) classes, por isso deve ser suficiente para o que eu quero.

Eu não quero para marcar a resposta ainda aceite uma vez que eu faço esperança para uma solução melhor para vir acima.

Edit3:. Aceite a sugestão beanshell - ele realmente funciona maravilhosamente

Foi útil?

Solução

Se você não está completamente ligada à compilação, soluções como Beanshell, groovy e as outras linguagens de script são facilmente incorporado (em verdade, Java tem suporte embutido para ligar uma linguagem de script para que o seu código não faz ainda sabe que língua o roteiro é escrito em)

Beanshell deve executar qualquer código java 100% IIRC, e eu acredito Groovy pode executar a maioria do código java -. Possivelmente todos

Outras dicas

JCI parece bem. Este trecho de código deve ser a sua 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

Você tem algum motivo isso não deve trabalhar?


Editar:. acrescentou um MemoryResourceStore para enviar a saída classe compilada para a memória, como solicitado

Além disso, definir configurações javac, como classpath no seu caso, pode ser feito através de setCustomArguments(String[] pCustomArguments) em JavacJavaCompilerSettings classe.

Você pode querer verificar para fora Janino também.

De seu site:

Janino é um compilador que lê uma expressão Java ™, bloco, corpo de classe, arquivo de origem ou um conjunto de arquivos de origem, e gera JavaTM bytecode que é carregado e executado diretamente. Janino não se destina a ser uma ferramenta de desenvolvimento, mas um compilador embutido para fins de compilação de tempo de execução, por exemplo, avaliadores de expressão ou "páginas de servidor" motores como JSP.

http://www.janino.net/

Im atualmente usá-lo em um projeto crítico muito grande missão e ele funciona muito bem

Javassist que você pode interessar

Executar dentro de um container web como o Tomcat e primeiro gerar uma página JSP, e, em seguida, invocá-lo.

Isso também permitirá que você se livrar das definições de classe de idade, simplesmente substituindo a página JSP em vez de ter o seu carregador de classe lentamente executar completo.

O requisito é "in-memory", devido à velocidade ou devido a não alterar a base de código?

TJCE Eclipse Java Compiler

Eclipse fornece e usa seu próprio compilador que não é javac

    compilador
  • A Eclipse é utilizado dentro do IDE (Eclipse)
  • compilador O Eclipse também pode ser usado como um compilador lote pura fora do Eclipse

Compilar um arquivo de origem

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top