7026509: Cannot use JavaCompiler to create multiple CompilationTasks for partial compilations

Reviewed-by: mcimadamore
This commit is contained in:
Jonathan Gibbons 2011-03-14 11:48:41 -07:00
parent 593927cf2d
commit 8f64aeabe2
5 changed files with 379 additions and 52 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -129,19 +129,11 @@ public class JavacTaskImpl extends JavacTask {
public Boolean call() {
if (!used.getAndSet(true)) {
beginContext();
initContext();
notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>();
try {
compilerMain.setFatalErrors(true);
result = compilerMain.compile(args, context, fileObjects, processors);
} finally {
endContext();
}
compilerMain = null;
args = null;
context = null;
fileObjects = null;
notYetEntered = null;
compilerMain.setFatalErrors(true);
result = compilerMain.compile(args, context, fileObjects, processors);
cleanup();
return result == 0;
} else {
throw new IllegalStateException("multiple calls to method 'call'");
@ -163,8 +155,11 @@ public class JavacTaskImpl extends JavacTask {
}
private void prepareCompiler() throws IOException {
if (!used.getAndSet(true)) {
beginContext();
if (used.getAndSet(true)) {
if (compiler == null)
throw new IllegalStateException();
} else {
initContext();
compilerMain.setOptions(Options.instance(context));
compilerMain.filenames = new ListBuffer<File>();
List<File> filenames = compilerMain.processArgs(CommandLine.parse(args));
@ -185,13 +180,12 @@ public class JavacTaskImpl extends JavacTask {
}
}
private void beginContext() {
private void initContext() {
context.put(JavacTaskImpl.class, this);
if (context.get(TaskListener.class) != null)
context.put(TaskListener.class, (TaskListener)null);
if (taskListener != null)
context.put(TaskListener.class, wrap(taskListener));
tool.beginContext(context);
//initialize compiler's default locale
JavacMessages.instance(context).setCurrentLocale(locale);
}
@ -218,8 +212,15 @@ public class JavacTaskImpl extends JavacTask {
};
}
private void endContext() {
tool.endContext();
void cleanup() {
if (compiler != null)
compiler.close();
compiler = null;
compilerMain = null;
args = null;
context = null;
fileObjects = null;
notYetEntered = null;
}
/**
@ -446,12 +447,12 @@ public class JavacTaskImpl extends JavacTask {
}
if (genList.isEmpty()) {
compiler.reportDeferredDiagnostics();
compiler.log.flush();
endContext();
cleanup();
}
}
finally {
compiler.log.flush();
if (compiler != null)
compiler.log.flush();
}
return results;
}

View File

@ -152,36 +152,6 @@ public final class JavacTool implements JavaCompiler {
return new JavacFileManager(context, true, charset);
}
private boolean compilationInProgress = false;
/**
* Register that a compilation is about to start.
*/
void beginContext(Context context) {
if (compilationInProgress)
throw new IllegalStateException("Compilation in progress");
compilationInProgress = true;
final JavaFileManager givenFileManager = context.get(JavaFileManager.class);
context.put(JavaFileManager.class, (JavaFileManager)null);
context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
public JavaFileManager make(Context c) {
if (givenFileManager != null) {
c.put(JavaFileManager.class, givenFileManager);
return givenFileManager;
} else {
return new JavacFileManager(c, true, null);
}
}
});
}
/**
* Register that a compilation is completed.
*/
void endContext() {
compilationInProgress = false;
}
public JavacTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7026509
* @summary Cannot use JavaCompiler to create multiple CompilationTasks for partial compilations
*/
import java.io.*;
import java.util.*;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import com.sun.source.util.*;
public class TestJavacTask_Lock {
public static void main(String... args) throws Exception {
new TestJavacTask_Lock().run();
}
enum MethodKind {
CALL {
int test(CompilationTask t) {
boolean ok = t.call();
if (!ok)
throw new Error("compilation failed");
return 1;
}
},
PARSE {
int test(CompilationTask t) {
try {
((JavacTask) t).parse();
return 1;
} catch (IOException ex) {
throw new Error(ex);
}
}
};
abstract int test(CompilationTask t);
}
JavaCompiler comp;
StandardJavaFileManager fm;
void run() throws Exception {
comp = ToolProvider.getSystemJavaCompiler();
fm = comp.getStandardFileManager(null, null, null);
for (MethodKind first: MethodKind.values()) {
for (MethodKind second: MethodKind.values()) {
test(first, second);
}
}
if (errors > 0)
throw new Exception(errors + " errors found");
}
void test(MethodKind first, MethodKind second) {
System.err.println("test: " + first + ", " + second);
File testSrc = new File(System.getProperty("test.src"));
String thisClassName = TestJavacTask_Lock.class.getName();
Iterable<? extends JavaFileObject> files =
fm.getJavaFileObjects(new File(testSrc, thisClassName + ".java"));
File tmpDir = new File(first + "_" + second);
tmpDir.mkdirs();
List<String> options = Arrays.asList( "-d", tmpDir.getPath() );
CompilationTask t = comp.getTask(null, fm, null, options, null, files);
try {
first.test(t);
second.test(t);
error("No exception thrown");
} catch (IllegalStateException e) {
System.err.println("Expected exception caught: " + e);
} catch (Exception e) {
error("Unexpected exception caught: " + e);
e.printStackTrace(System.err);
}
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
int errors;
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7026509
* @summary Cannot use JavaCompiler to create multiple CompilationTasks for partial compilations
*/
import java.io.*;
import java.util.*;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import com.sun.source.util.*;
public class TestJavacTask_Multiple {
public static void main(String... args) throws Exception {
new TestJavacTask_Multiple().run();
}
final int MAX_TASKS = 3;
enum TestKind {
CALL {
int test(CompilationTask t) {
boolean ok = t.call();
if (!ok)
throw new Error("compilation failed");
return 1;
}
},
PARSE {
int test(CompilationTask t) {
try {
((JavacTask) t).parse();
return 1;
} catch (IOException ex) {
throw new Error(ex);
}
}
};
abstract int test(CompilationTask t);
}
int count;
void run() throws Exception {
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (TestKind tk: TestKind.values()) {
test(comp, fm, tk);
}
int expect = TestKind.values().length * MAX_TASKS;
if (count != expect) {
throw new Exception("Unexpected number of tests completed: " + count
+ ", expected: " + expect);
}
}
void test(JavaCompiler comp, StandardJavaFileManager fm, TestKind tk) {
System.err.println("test " + tk);
File testSrc = new File(System.getProperty("test.src"));
String thisClassName = TestJavacTask_Multiple.class.getName();
Iterable<? extends JavaFileObject> files =
fm.getJavaFileObjects(new File(testSrc, thisClassName + ".java"));
List<CompilationTask> tasks = new ArrayList<CompilationTask>();
for (int i = 1; i <= MAX_TASKS; i++) {
File tmpDir = new File(tk + "_" + i);
tmpDir.mkdirs();
List<String> options = Arrays.asList( "-d", tmpDir.getPath() );
CompilationTask t = comp.getTask(null, fm, null, options, null, files);
((JavacTask) t).setTaskListener(createTaskListener(tk, i));
tasks.add(t);
}
for (CompilationTask t: tasks)
count += tk.test(t);
System.err.println();
}
TaskListener createTaskListener(final TestKind tk, final int i) {
return new TaskListener() {
public void started(TaskEvent e) {
System.err.println(tk + "." + i + ": " + e + " started");
}
public void finished(TaskEvent e) {
System.err.println(tk + "." + i + ": " + e + " finished");
}
};
}
}

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7026509
* @summary Cannot use JavaCompiler to create multiple CompilationTasks for partial compilations
*/
import java.io.*;
import java.util.*;
import javax.lang.model.element.*;
import javax.tools.*;
import com.sun.source.tree.*;
import com.sun.source.util.*;
public class TestJavacTask_ParseAttrGen {
public static void main(String... args) throws Exception {
new TestJavacTask_ParseAttrGen().run();
}
JavaCompiler comp;
StandardJavaFileManager fm;
void run() throws Exception {
comp = ToolProvider.getSystemJavaCompiler();
fm = comp.getStandardFileManager(null, null, null);
final boolean[] booleanValues = { false, true };
for (boolean pk: booleanValues) {
for (boolean ak: booleanValues) {
for (boolean gk: booleanValues) {
test(pk, ak, gk);
}
}
}
}
void test(boolean pk, boolean ak, boolean gk) throws Exception {
if (!pk && !ak && !gk) // nothing to do
return;
System.err.println("test: pk:" + pk + ", ak:" + ak + ", gk: " + gk);
File testSrc = new File(System.getProperty("test.src"));
String thisClassName = TestJavacTask_ParseAttrGen.class.getName();
Iterable<? extends JavaFileObject> files =
fm.getJavaFileObjects(new File(testSrc, thisClassName + ".java"));
File tmpDir = new File((pk ? "p" : "") + (ak ? "a" : "") + (gk ? "g" : ""));
tmpDir.mkdirs();
fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tmpDir));
JavacTask t = (JavacTask) comp.getTask(null, fm, null, null, null, files);
//t.setTaskListener(createTaskListener());
try {
if (pk) {
Iterable<? extends CompilationUnitTree> trees = t.parse();
System.err.println(count(trees) + " trees parsed");
}
if (ak) {
Iterable<? extends Element> elems = t.analyze();
System.err.println(count(elems) + " elements analyzed");
}
if (gk) {
Iterable<? extends JavaFileObject> classfiles = t.generate();
System.err.println(count(classfiles) + " class files generated");
}
} catch (IOException e) {
error("unexpected exception caught: " + e);
}
File[] genFiles = tmpDir.listFiles();
int expect = (gk ? 2 : 0); // main class and anon class for TaskListener
if (genFiles.length != expect)
error("unexpected number of files generated: " + genFiles.length
+ ", expected: " + expect);
System.err.println();
}
TaskListener createTaskListener() {
return new TaskListener() {
public void started(TaskEvent e) {
System.err.println(e + " started");
}
public void finished(TaskEvent e) {
System.err.println(e + " finished");
}
};
}
<T> int count(Iterable<T> items) {
int count = 0;
for (T item: items)
count++;
return count;
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
int errors;
}