2010-12-16 145 views
8

有沒有一種運行Java程序來編譯Java源代碼(以字符串形式傳遞)的方法?從字符串編譯Java源代碼?

Class newClass = Compiler.compile ("class ABC { void xyz {etc. etc. } }"); 

理想情況下,傳入的源代碼所引用的任何類都將被程序的類加載器解析。

是否有這樣的事情存在?

+0

我發現這個例子中,這正是我需要的。 http://www.ibm.com/developerworks/java/library/j-jcomp/index.html – user566822 2012-10-24 23:48:18

回答

9

當然。查看JavaCompiler類和javax.tools包中的其他類。

自Java 1.6以來,它們一直存在。

Here is some example code.

(正如在評論中指出的@Sergey Tachenov,它需要JDK安裝爲必要的tools.jar文件帶有JDK而不是JRE)

+4

我認爲值得注意的是,它僅適用於Sun的JRE,它需要根據需要安裝JDK tools.jar文件附帶JDK,但不附帶JRE。 – 2010-12-16 17:34:34

+0

我試過這個例子,我在'Class clazz = Class.forName(「Test」)上有'java.lang.ClassNotFoundException:Test';'! – bachr 2014-01-21 10:17:04

+0

是類路徑上編譯的輸出目錄嗎? – aioobe 2014-01-21 12:02:55

3

取決於你想做。 如果你只是想運行一些代碼,你可以使用BeanShell。這不是一個Java編譯類,但是非常有用,使靈活的東西

1

你可以嘗試我的本質jcf庫這樣做。在調試中運行時,可以將源代碼寫入文件,以便您可以進入代碼。否則,它會在內存中執行所有操作。它將JavaCompiler包裝在tools.jar中

它接受一個字符串,編譯並將其加載到當前類加載器中並返回該類。它處理嵌套/內部類。

http://vanillajava.blogspot.com/2010/11/more-uses-for-dynamic-code-in-java.html

注:我還沒有在OSGi的這個工作。 ;)

1

Javassist可以在運行時從源代碼的字符串生成和加載類和方法。 如果需要,也可以在文件系統中轉儲生成的類。

當前,您可以在這些字符串中傳遞的代碼存在較小的限制,例如,它不能包含泛型,枚舉或自動裝箱和收件箱原語。 點擊此處瞭解詳情:

http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/

4

你需要的是一個擴展JavaFileObject中

import java.net.URI; 

import javax.tools.SimpleJavaFileObject; 

public class JavaSourceFromString extends SimpleJavaFileObject { 
    final String code; 

    public JavaSourceFromString(String name, String code) { 
     super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE); 
     this.code = code; 
    } 

    @Override 
    public CharSequence getCharContent(boolean ignoreEncodingErrors) { 
     return code; 
    } 
} 

這可以如下的一類:

JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 
if(jc == null) throw new Exception("Compiler unavailable"); 

String code = "public class CustomProcessor { /*custom stuff*/ }"; 
JavaSourceFromString jsfs = new JavaSourceFromString("CustomProcessor", code); 

Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(jsfs); 

List<String> options = new ArrayList<String>(); 
options.add("-d"); 
options.add(compilationPath); 
options.add("-classpath"); 
URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader(); 
StringBuilder sb = new StringBuilder(); 
for (URL url : urlClassLoader.getURLs()) { 
    sb.append(url.getFile()).append(File.pathSeparator); 
} 
sb.append(compilationPath); 
options.add(sb.toString()); 

StringWriter output = new StringWriter(); 
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call(); 
if(success) { 
    logger.info(LOG_PREFIX + "Class has been successfully compiled"); 
} else { 
    throw new Exception("Compilation failed :" + output); 
} 
+0

你在哪裏聲明瞭'compilationPath'變量? – bachr 2014-01-21 09:48:23

+0

它在代碼中更高,只是一個字符串 – MonoThreaded 2014-01-24 14:36:25