(Class) classLoader.loadClass(qualifiedClassName); return newClass; } catch (Exception exception) { throw new JavaDinamicoException(exception, diagnostics); } } }Classe responsavel pela compilacaoO processo de compilacao envolve dois tipos de arquivos: os codigos-fonte escritos em Java e os arquivos compilados (bytecodes). Na Compiler API estes arquivos sao representados por objetos de uma unica interface, chamada JavaFileObject. Felizmente a API disponibiliza uma classe que implementa esta interface, chamada SimpleJavaFileObject e, na escrita de codigo de compilacao dinamica, deve-se criar uma subclasse de SimpleJavaFileObject e sobrescrever os metodos necessarios.public class JavaDinamicoBean extends SimpleJavaFileObject { private String source; private ByteArrayOutputStream byteCode = new ByteArrayOutputStream(); public JavaDinamicoBean(String baseName, String source) { super(JavaDinamicoUtils.INSTANCE.createURI(JavaDinamicoUtils.INSTANCE.getClassNameWithExt(baseName)), Kind.SOURCE); this.source = source; } public JavaDinamicoBean(String name) { super(JavaDinamicoUtils.INSTANCE.createURI(name), Kind.CLASS); } @Override public String getCharContent(boolean ignoreEncodingErrors) { return source; } @Override public OutputStream openOutputStream() { return byteCode; } public byte[] getBytes() { return byteCode.toByteArray(); } }Estrutura de dados que contem o codigo fonte e a classe compiladaPara representar os arquivos envolvidos sera utilizado o ForwardingJavaFileManager que implementa a interface JavaFileManager.public class JavaDinamicoManager extends ForwardingJavaFileManager { private JavaDinamicoClassLoader classLoader; private JavaDinamicoBean codigoFonte; private JavaDinamicoBean arquivoCompilado; public JavaDinamicoManager(JavaFileManager fileManager, JavaDinamicoClassLoader classLoader) { super(fileManager); this.classLoader = classLoader; } public void setSources(JavaDinamicoBean sourceObject, JavaDinamicoBean compiledObject) { this.codigoFonte = sourceObject; this.arquivoCompilado = compiledObject; this.classLoader.addClass(compiledObject); } @Override public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { return codigoFonte; } @Override public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, Kind kind, FileObject outputFile) throws IOException { return arquivoCompilado; } @Override public ClassLoader getClassLoader(Location location) { return classLoader; } }Classe responsavel por gerenciar as classes compiladas e nao compiladasPara que ela possa ser utilizada, a JVM deve ser capaz de reconhece-la como uma classe da aplicacao, a fim de que possa carrega-la quando chegar o momento. O componente responsavel pelo carregamento das classes das aplicacoes Java durante a execucao e o Class Loader.Portanto, para que a JVM saiba da existencia das novas classes compiladas, e necessario implementar um class loader customizado, que fica atrelado ao gerenciador de arquivos.Ele deve estender a classe ClassLoader (do pacote java.lang) e tem a responsabilidade de carregar as classes recem-criadas.Com isso foi discutido um pouco sobre a compilacao dinamica do Java no Java, objetivo aqui foi apenas de demonstrar o seu funcionamento basico alem de uma pequena explicacao do uso da API. Pela sua complexidade o ideal e que ela esteja encapsulado a ponto de ser utilizadas varias vezes em diversos projetos. O objetivo aqui nao foi desmerecer em nenhum momento as outras linguagens de programacao rodando ou nao em cima da JVM, afinal todas elas tem sua importancia. O objetivo foi demonstrar que nao existe a necessidade de mudar de linguagem caso seu problema seja ter um codigo que seja compilado dinamicamente.Referencias:https://www.jcp.org/en/jsr/detail?id=199Carlos Eduardo Gusso Tosin, Compilacao Dinamica no Java 6 - Revista Java Magazine 94Codigo: https://github.com/otaviojava/java_dinamico