2012-11-21 65 views
0

從JDK6移動到JDK7之後,接下來的代碼將失敗,ClassNotFoundException的CompilationTask.call()引入了ClassNotFoundException。曾在JDK6,而不是在JDK7

CompilationTask task = cSysCompiler.getTask(null, cFileManager, cDiagnosticCollector, null, null, cUnitsToCompile); 
boolean mSuccess = task.call(); 
Analyzer mAnalyzer = new Analyzer(); // Throws ClassNotFoundException 

解決方法:

ClassLoader mSystemClassLoader = ClassLoader.getSystemClassLoader(); 
mSystemClassLoader.loadClass("ft.jopc.com.JavaBytecodeObject"); 
mSystemClassLoader.loadClass("ft.jopc.com.analyzer.Analyzer"); 
mSystemClassLoader.loadClass("ft.jopc.opccl.ClassLoaderListener"); 
… 
ompilationTask task = cSysCompiler.getTask(null, cFileManager, cDiagnosticCollector, null, null, cUnitsToCompile); 
boolean mSuccess = task.call(); 
Analyzer mAnalyzer = new Analyzer(); // No ClassNotFoundException 

有誰知道爲什麼在調用後task.call()類無法找到?它看起來像編譯任務以某種方式改變了systemclassloader?

+0

你居然*編譯*您正在使用*在同一類*類?如果是這樣,那麼Java 7中的某些緩存行爲可能會發生變化,導致問題發生,並且它*不應該首先發揮作用。 –

+0

@Joachim classNotFoundException發生在編譯之前已經存在於類路徑中的類 – Houtman

回答

3

最近,我們面臨着JavaFileManager重新定義的定製實現(除其他事項外)

public ClassLoader getClassLoader(final Location location) 
{ 
    return getClass().getClassLoader(); 
} 

不知道爲什麼它這樣做的方式,但在你的情況,這在JDK6工作得很好類似的問題。我們將jdk7問題指向了這個函數,部分原因是它在單元測試(classloader爲Launcher $ AppClassLoader)時失敗,但在「生產模式」(類由自定義類加載器加載)中工作正常。更改此功能使用StandardFileManager版本,甚至只是封裝一個空的URLClassLoader內,如

return new URLClassLoader(new URL[]{}, getClass().getClassLoader()); 

固定的問題。

顯然,這是關係到引進URLClassLoader的,因而AppClassLoader,在JDK7是「可關閉」,因爲出現在:

Thread [main] (Suspended (breakpoint at line 282 in URLClassLoader))  
Launcher$AppClassLoader(URLClassLoader).close() line: 282 [local variables unavailable] 
JavacProcessingEnvironment.close() line: 1257 
JavaCompiler.initProcessAnnotations(Iterable<Processor>) line: 1004 
JavaCompiler.compile(List<JavaFileObject>, List<String>, Iterable<Processor>) line: 821 
Main.compile(String[], String[], Context, List<JavaFileObject>, Iterable<Processor>) line: 439 
JavacTaskImpl.call() line: 132 

然後,我必須承認,我沒有找到的Javadoc真正明確這一點,但看看jdk6的DefaultFileManager以及jdk7的BaseFileManager,似乎相當清楚,期望是提供一個臨時文件管理器(因此需要關閉「如果可能」)而不是「通用」。

(我會很樂意瞭解在任何情況下,主體提供額外的/最佳實踐參考)

相關問題