2008-11-08 45 views
6

我的用例是使用JDK 6中提供的ToolProvider和JavaCompiler類從Java程序編譯生成的源文件。源文件包含上下文classloader中的類的引用(它運行在J2EE容器中),但不包含在系統中類加載器。我的理解是,默認情況下,ToolProvider將使用系統類加載器創建JavaCompiler實例。如何在上下文類加載器中使用JDK6 ToolProvider和JavaCompiler?

有沒有辦法指定JavaCompiler的類加載器使用?

我試過這種方法,從修改的東西在IBM developerWorks上:

FileManagerImpl fm = 
    new FileManagerImpl(compiler.getStandardFileManager(null, null, null);); 

與FileManagerImpl定義爲:

static final class FileManagerImpl 
    extends ForwardingJavaFileManager<JavaFileManager> { 

    public FileManagerImpl(JavaFileManager fileManager) { 
     super(fileManager); 
    } 

    @Override 
    public ClassLoader getClassLoader(JavaFileManager.Location location) { 
     new Exception().printStackTrace(); 
     return Thread.currentThread().getContextClassLoader(); 
    } 

} 

堆棧跟蹤表明它註釋處理過程中的唯一調用一次。我驗證了要編譯的源文件中引用的類不在系統類路徑中,但可從上下文類加載器中獲得。

回答

1

另一種選擇是使用Commons JCI

+0

JCI不允許您像JDK6支持允許的那樣僅在路徑中傳遞類加載器。 – Phil 2008-12-29 18:50:47

8

如果你知道類路徑中已知的contextclassloader的文件,你可以將它們傳遞到編譯器:

StandardJavaFileManager fileManager = compiler.getStandardFileManager(this /* diagnosticlistener */, null, null); 
// get compilationunits from somewhere, for instance via fileManager.getJavaFileObjectsFromFiles(List<file> files) 
List<String> options = new ArrayList<String>(); 
options.add("-classpath"); 
StringBuilder sb = new StringBuilder(); 
URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); 
for (URL url : urlClassLoader.getURLs()) 
    sb.append(url.getFile()).append(File.pathSeparator); 
options.add(sb.toString()); 
CompilationTask task = compiler.getTask(null, fileManager, this /* diagnosticlistener */, options, null, compilationUnits); 
task.call(); 

此示例假設您使用的是URLClassLoader的(它允許您檢索類路徑),但你可以插入你自己的類路徑,如果你想。

0

你在這裏問兩個單獨的問題。

一個是如何編譯在系統類路徑中找不到的類。通過將「-classpath」命令行參數傳遞給編譯器(首先由Leihca提到),可以很容易地解決這個問題。

第二個是如何在線程上下文類加載器上實例化ToolProvider和JavaCompiler。在撰寫本文時,這是一個未解決的問題:Using javax.tools.ToolProvider from a custom classloader?