This commit is contained in:
Lana Steuck 2015-09-11 13:01:23 -07:00
commit b95f5342cf
23 changed files with 385 additions and 261 deletions

View File

@ -1436,6 +1436,7 @@ public class Resolve {
} }
Assert.check(!sym.kind.isResolutionError()); Assert.check(!sym.kind.isResolutionError());
try { try {
types.noWarnings.clear();
Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes, Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
allowBoxing, useVarargs, types.noWarnings); allowBoxing, useVarargs, types.noWarnings);
currentResolutionContext.addApplicableCandidate(sym, mt); currentResolutionContext.addApplicableCandidate(sym, mt);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,38 +23,40 @@
* questions. * questions.
*/ */
package com.sun.tools.sjavac.server; package com.sun.tools.sjavac;
import java.io.Serializable; import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
/** public class AutoFlushWriter extends FilterWriter {
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class CompilationResult implements Serializable {
static final long serialVersionUID = 46739181113L; public AutoFlushWriter(Writer out) {
super(out);
// Return code constants
public final static int ERROR_FATAL = -1;
public String stdout;
public String stderr;
public int returnCode;
public CompilationResult(int returnCode) {
this(returnCode, "", "");
} }
public CompilationResult(int returnCode, String stdout, String stderr) { @Override
this.returnCode = returnCode; public void write(int c) throws IOException {
this.stdout = stdout; super.write(c);
this.stderr = stderr; if (c == '\n' || c == '\r')
flush();
} }
public void setReturnCode(int returnCode) { @Override
this.returnCode = returnCode; public void write(String str, int off, int len) throws IOException {
super.write(str, off, len);
if (str.contains("\n") || str.contains("\r"))
flush();
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
super.write(cbuf, off, len);
for (char c : cbuf) {
if (c == '\n' || c == '\r') {
flush();
break;
}
}
} }
} }

View File

@ -31,7 +31,6 @@ import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer; import java.io.Writer;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
@ -78,8 +77,8 @@ public class CleanProperties implements Transformer {
int debugLevel, int debugLevel,
boolean incremental, boolean incremental,
int numCores, int numCores,
PrintStream out, Writer out,
PrintStream err) { Writer err) {
boolean rc = true; boolean rc = true;
for (String pkgName : pkgSrcs.keySet()) { for (String pkgName : pkgSrcs.keySet()) {
String pkgNameF = pkgName.replace('.',File.separatorChar); String pkgNameF = pkgName.replace('.',File.separatorChar);

View File

@ -26,14 +26,22 @@
package com.sun.tools.sjavac; package com.sun.tools.sjavac;
import java.io.File; import java.io.File;
import java.io.PrintStream; import java.io.IOException;
import java.io.Writer;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.comp.CompilationService;
import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.options.Options;
@ -83,8 +91,8 @@ public class CompileJavaPackages implements Transformer {
int debugLevel, int debugLevel,
boolean incremental, boolean incremental,
int numCores, int numCores,
final PrintStream out, final Writer out,
final PrintStream err) { final Writer err) {
Log.debug("Performing CompileJavaPackages transform..."); Log.debug("Performing CompileJavaPackages transform...");
@ -200,102 +208,83 @@ public class CompileJavaPackages implements Transformer {
} }
} }
// The return values for each chunked compile.
final CompilationSubResult[] rn = new CompilationSubResult[numCompiles];
// The requets, might or might not run as a background thread.
final Thread[] requests = new Thread[numCompiles];
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
for (int i=0; i<numCompiles; ++i) { // Prepare compilation calls
final int ii = i; List<Callable<CompilationSubResult>> compilationCalls = new ArrayList<>();
final CompileChunk cc = compileChunks[i]; final Object lock = new Object();
for (int i = 0; i < numCompiles; i++) {
CompileChunk cc = compileChunks[i];
if (cc.srcs.isEmpty()) {
continue;
}
// Pass the num_cores and the id (appended with the chunk number) to the server. String chunkId = id + "-" + String.valueOf(i);
Object lock = new Object(); compilationCalls.add(() -> {
requests[i] = new Thread() { CompilationSubResult result = sjavac.compile("n/a",
@Override chunkId,
public void run() { args.prepJavacArgs(),
rn[ii] = sjavac.compile("n/a", Collections.<File>emptyList(),
id + "-" + ii, cc.srcs,
args.prepJavacArgs(), visibleSources);
Collections.<File>emptyList(), synchronized (lock) {
cc.srcs, safeWrite(result.stdout, out);
visibleSources); safeWrite(result.stderr, err);
// In the code below we have to keep in mind that two
// different compilation results may include results for
// the same package.
synchronized (lock) {
for (String pkg : rn[ii].packageArtifacts.keySet()) {
Set<URI> pkgArtifacts = rn[ii].packageArtifacts.get(pkg);
packageArtifacts.merge(pkg, pkgArtifacts, Util::union);
}
for (String pkg : rn[ii].packageDependencies.keySet()) {
packageDependencies.putIfAbsent(pkg, new HashMap<>());
packageDependencies.get(pkg).putAll(rn[ii].packageDependencies.get(pkg));
}
for (String pkg : rn[ii].packageCpDependencies.keySet()) {
packageCpDependencies.putIfAbsent(pkg, new HashMap<>());
packageCpDependencies.get(pkg).putAll(rn[ii].packageCpDependencies.get(pkg));
}
for (String pkg : rn[ii].packagePubapis.keySet()) {
packagePubapis.merge(pkg, rn[ii].packagePubapis.get(pkg), PubApi::mergeTypes);
}
for (String pkg : rn[ii].dependencyPubapis.keySet()) {
dependencyPubapis.merge(pkg, rn[ii].dependencyPubapis.get(pkg), PubApi::mergeTypes);
}
}
} }
}; return result;
});
}
if (cc.srcs.size() > 0) { // Perform compilations and collect results
String numdeps = ""; List<CompilationSubResult> subResults = new ArrayList<>();
if (cc.numDependents > 0) numdeps = "(with "+cc.numDependents+" dependents) "; List<Future<CompilationSubResult>> futs = new ArrayList<>();
if (!incremental || cc.numPackages > 16) { ExecutorService exec = Executors.newFixedThreadPool(concurrentCompiles ? compilationCalls.size() : 1);
String info = "("+cc.pkgFromTos+")"; for (Callable<CompilationSubResult> compilationCall : compilationCalls) {
if (info.equals("( to )")) { futs.add(exec.submit(compilationCall));
info = ""; }
} for (Future<CompilationSubResult> fut : futs) {
Log.info("Compiling "+cc.srcs.size()+" files "+numdeps+"in "+cc.numPackages+" packages "+info); try {
} else { subResults.add(fut.get());
Log.info("Compiling "+cc.pkgNames+numdeps); } catch (ExecutionException ee) {
} Log.error("Compilation failed: " + ee.getMessage());
if (concurrentCompiles) { } catch (InterruptedException ee) {
requests[ii].start(); Log.error("Compilation interrupted: " + ee.getMessage());
} Thread.currentThread().interrupt();
else {
requests[ii].run();
// If there was an error, then stop early when running single threaded.
if (rn[i].returnCode != 0) {
Log.info(rn[i].stdout);
Log.error(rn[i].stderr);
return false;
}
}
} }
} }
if (concurrentCompiles) { exec.shutdownNow();
// If there are background threads for the concurrent compiles, then join them.
for (int i=0; i<numCompiles; ++i) { // Process each sub result
try { requests[i].join(); } catch (InterruptedException e) { } for (CompilationSubResult subResult : subResults) {
for (String pkg : subResult.packageArtifacts.keySet()) {
Set<URI> pkgArtifacts = subResult.packageArtifacts.get(pkg);
packageArtifacts.merge(pkg, pkgArtifacts, Util::union);
}
for (String pkg : subResult.packageDependencies.keySet()) {
packageDependencies.putIfAbsent(pkg, new HashMap<>());
packageDependencies.get(pkg).putAll(subResult.packageDependencies.get(pkg));
}
for (String pkg : subResult.packageCpDependencies.keySet()) {
packageCpDependencies.putIfAbsent(pkg, new HashMap<>());
packageCpDependencies.get(pkg).putAll(subResult.packageCpDependencies.get(pkg));
}
for (String pkg : subResult.packagePubapis.keySet()) {
packagePubapis.merge(pkg, subResult.packagePubapis.get(pkg), PubApi::mergeTypes);
}
for (String pkg : subResult.dependencyPubapis.keySet()) {
dependencyPubapis.merge(pkg, subResult.dependencyPubapis.get(pkg), PubApi::mergeTypes);
}
// Check the return values.
if (subResult.returnCode != 0) {
rc = false;
} }
} }
// Check the return values.
for (int i=0; i<numCompiles; ++i) {
if (compileChunks[i].srcs.size() > 0) {
if (rn[i].returnCode != 0) {
Log.info(rn[i].stdout);
Log.error(rn[i].stderr);
rc = false;
}
}
}
long duration = System.currentTimeMillis() - start; long duration = System.currentTimeMillis() - start;
long minutes = duration/60000; long minutes = duration/60000;
long seconds = (duration-minutes*60000)/1000; long seconds = (duration-minutes*60000)/1000;
@ -304,6 +293,16 @@ public class CompileJavaPackages implements Transformer {
return rc; return rc;
} }
private void safeWrite(String str, Writer w) {
if (str.length() > 0) {
try {
w.write(str);
} catch (IOException e) {
Log.error("Could not print compilation output.");
}
}
}
/** /**
* Split up the sources into compile chunks. If old package dependents information * Split up the sources into compile chunks. If old package dependents information
* is available, sort the order of the chunks into the most dependent first! * is available, sort the order of the chunks into the most dependent first!

View File

@ -85,8 +85,8 @@ public class CompileProperties implements Transformer {
int debugLevel, int debugLevel,
boolean incremental, boolean incremental,
int numCores, int numCores,
PrintStream out, Writer out,
PrintStream err) { Writer err) {
boolean rc = true; boolean rc = true;
for (String pkgName : pkgSrcs.keySet()) { for (String pkgName : pkgSrcs.keySet()) {
String pkgNameF = Util.toFileSystemPath(pkgName); String pkgNameF = Util.toFileSystemPath(pkgName);

View File

@ -31,7 +31,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PrintStream; import java.io.Writer;
import java.net.URI; import java.net.URI;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -72,8 +72,8 @@ public class CopyFile implements Transformer {
int debugLevel, int debugLevel,
boolean incremental, boolean incremental,
int numCores, int numCores,
PrintStream out, Writer out,
PrintStream err) Writer err)
{ {
boolean rc = true; boolean rc = true;
String dest_filename; String dest_filename;

View File

@ -31,7 +31,7 @@ import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.Writer;
import java.net.URI; import java.net.URI;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -131,12 +131,12 @@ public class JavacState {
private CompileJavaPackages compileJavaPackages = new CompileJavaPackages(); private CompileJavaPackages compileJavaPackages = new CompileJavaPackages();
// Where to send stdout and stderr. // Where to send stdout and stderr.
private PrintStream out, err; private Writer out, err;
// Command line options. // Command line options.
private Options options; private Options options;
JavacState(Options op, boolean removeJavacState, PrintStream o, PrintStream e) { JavacState(Options op, boolean removeJavacState, Writer o, Writer e) {
options = op; options = op;
out = o; out = o;
err = e; err = e;
@ -311,7 +311,7 @@ public class JavacState {
/** /**
* Load a javac_state file. * Load a javac_state file.
*/ */
public static JavacState load(Options options, PrintStream out, PrintStream err) { public static JavacState load(Options options, Writer out, Writer err) {
JavacState db = new JavacState(options, false, out, err); JavacState db = new JavacState(options, false, out, err);
Module lastModule = null; Module lastModule = null;
Package lastPackage = null; Package lastPackage = null;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,8 @@
package com.sun.tools.sjavac; package com.sun.tools.sjavac;
import java.io.PrintStream; import java.io.PrintWriter;
import java.io.Writer;
/** /**
* Utility class only for sjavac logging. * Utility class only for sjavac logging.
@ -37,7 +38,7 @@ import java.io.PrintStream;
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public class Log { public class Log {
private static PrintStream out, err; private static PrintWriter out, err;
public final static int WARN = 1; public final static int WARN = 1;
public final static int INFO = 2; public final static int INFO = 2;
@ -71,9 +72,9 @@ public class Log {
err.println(msg); err.println(msg);
} }
static public void initializeLog(PrintStream o, PrintStream e) { static public void initializeLog(Writer o, Writer e) {
out = o; out = new PrintWriter(o);
err = e; err = new PrintWriter(e);
} }
static public void setLogLevel(String l) { static public void setLogLevel(String l) {

View File

@ -25,7 +25,7 @@
package com.sun.tools.sjavac; package com.sun.tools.sjavac;
import java.io.PrintStream; import java.io.Writer;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -97,8 +97,8 @@ public interface Transformer {
int debugLevel, int debugLevel,
boolean incremental, boolean incremental,
int numCores, int numCores,
PrintStream out, Writer out,
PrintStream err); Writer err);
void setExtra(String e); void setExtra(String e);
void setExtra(Options args); void setExtra(Options args);

View File

@ -25,13 +25,14 @@
package com.sun.tools.sjavac.client; package com.sun.tools.sjavac.client;
import java.io.PrintStream; import java.io.OutputStreamWriter;
import java.io.Writer;
import com.sun.tools.sjavac.AutoFlushWriter;
import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.Util;
import com.sun.tools.sjavac.comp.SjavacImpl; import com.sun.tools.sjavac.comp.SjavacImpl;
import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Sjavac;
/** /**
@ -43,10 +44,12 @@ import com.sun.tools.sjavac.server.Sjavac;
public class ClientMain { public class ClientMain {
public static int run(String[] args) { public static int run(String[] args) {
return run(args, System.out, System.err); return run(args,
new AutoFlushWriter(new OutputStreamWriter(System.out)),
new AutoFlushWriter(new OutputStreamWriter(System.err)));
} }
public static int run(String[] args, PrintStream out, PrintStream err) { public static int run(String[] args, Writer out, Writer err) {
Log.initializeLog(out, err); Log.initializeLog(out, err);
@ -78,14 +81,11 @@ public class ClientMain {
sjavac = new SjavacImpl(); sjavac = new SjavacImpl();
} }
CompilationResult cr = sjavac.compile(args); int rc = sjavac.compile(args, out, err);
out.print(cr.stdout);
err.print(cr.stderr);
if (!background) if (!background)
sjavac.shutdown(); sjavac.shutdown();
return cr.returnCode; return rc;
} }
} }

View File

@ -25,11 +25,14 @@
package com.sun.tools.sjavac.client; package com.sun.tools.sjavac.client;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream; import java.io.InputStreamReader;
import java.io.ObjectOutputStream; import java.io.OutputStreamWriter;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
@ -43,7 +46,6 @@ import com.sun.tools.sjavac.Util;
import com.sun.tools.sjavac.options.OptionHelper; import com.sun.tools.sjavac.options.OptionHelper;
import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.server.CompilationSubResult; import com.sun.tools.sjavac.server.CompilationSubResult;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.PortFile; import com.sun.tools.sjavac.server.PortFile;
import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Sjavac;
import com.sun.tools.sjavac.server.SjavacServer; import com.sun.tools.sjavac.server.SjavacServer;
@ -119,29 +121,47 @@ public class SjavacClient implements Sjavac {
} }
@Override @Override
public CompilationResult compile(String[] args) { public int compile(String[] args, Writer stdout, Writer stderr) {
CompilationResult result; int result = -1;
try (Socket socket = tryConnect()) { try (Socket socket = tryConnect()) {
// The ObjectInputStream constructor will block until the PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
// corresponding ObjectOutputStream has written and flushed the BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// header, so it is important that the ObjectOutputStreams on server
// and client are opened before the ObjectInputStreams. // Send args array to server
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); out.println(args.length);
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); for (String arg : args)
oos.writeObject(id); out.println(arg);
oos.writeObject(SjavacServer.CMD_COMPILE); out.flush();
oos.writeObject(args);
oos.flush(); // Read server response line by line
result = (CompilationResult) ois.readObject(); String line;
} catch (IOException | ClassNotFoundException ex) { while (null != (line = in.readLine())) {
Log.error("[CLIENT] Exception caught: " + ex); String[] typeAndContent = line.split(":", 2);
result = new CompilationResult(CompilationSubResult.ERROR_FATAL); String type = typeAndContent[0];
result.stderr = Util.getStackTrace(ex); String content = typeAndContent[1];
switch (type) {
case SjavacServer.LINE_TYPE_STDOUT:
stdout.write(content);
stdout.write('\n');
break;
case SjavacServer.LINE_TYPE_STDERR:
stderr.write(content);
stderr.write('\n');
break;
case SjavacServer.LINE_TYPE_RC:
result = Integer.parseInt(content);
break;
}
}
} catch (IOException ioe) {
Log.error("[CLIENT] Exception caught: " + ioe);
result = CompilationSubResult.ERROR_FATAL;
ioe.printStackTrace(new PrintWriter(stderr));
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // Restore interrupt Thread.currentThread().interrupt(); // Restore interrupt
Log.error("[CLIENT] compile interrupted."); Log.error("[CLIENT] compile interrupted.");
result = new CompilationResult(CompilationSubResult.ERROR_FATAL); result = CompilationSubResult.ERROR_FATAL;
result.stderr = Util.getStackTrace(ie); ie.printStackTrace(new PrintWriter(stderr));
} }
return result; return result;
} }

View File

@ -24,13 +24,13 @@
*/ */
package com.sun.tools.sjavac.comp; package com.sun.tools.sjavac.comp;
import java.io.Writer;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Sjavac;
/** /**
@ -54,10 +54,10 @@ public class PooledSjavac implements Sjavac {
} }
@Override @Override
public CompilationResult compile(String[] args) { public int compile(String[] args, Writer out, Writer err) {
try { try {
return pool.submit(() -> { return pool.submit(() -> {
return delegate.compile(args); return delegate.compile(args, out, err);
}).get(); }).get();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -24,12 +24,9 @@
*/ */
package com.sun.tools.sjavac.comp; package com.sun.tools.sjavac.comp;
import static com.sun.tools.sjavac.server.CompilationResult.ERROR_FATAL;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintWriter;
import java.io.Writer;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
@ -49,7 +46,6 @@ import com.sun.tools.sjavac.Transformer;
import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.Util;
import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.options.SourceLocation; import com.sun.tools.sjavac.options.SourceLocation;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Sjavac;
/** /**
@ -64,39 +60,33 @@ import com.sun.tools.sjavac.server.Sjavac;
public class SjavacImpl implements Sjavac { public class SjavacImpl implements Sjavac {
@Override @Override
public CompilationResult compile(String[] args) { public int compile(String[] args, Writer out, Writer err) {
ByteArrayOutputStream outBaos = new ByteArrayOutputStream();
ByteArrayOutputStream errBaos = new ByteArrayOutputStream();
PrintStream out = new PrintStream(outBaos);
PrintStream err = new PrintStream(errBaos);
Options options; Options options;
try { try {
options = Options.parseArgs(args); options = Options.parseArgs(args);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.error(e.getMessage()); Log.error(e.getMessage());
return new CompilationResult(ERROR_FATAL); return RC_FATAL;
} }
Log.setLogLevel(options.getLogLevel()); Log.setLogLevel(options.getLogLevel());
if (!validateOptions(options)) if (!validateOptions(options))
return new CompilationResult(ERROR_FATAL); return RC_FATAL;
if (!createIfMissing(options.getDestDir())) if (!createIfMissing(options.getDestDir()))
return new CompilationResult(ERROR_FATAL); return RC_FATAL;
if (!createIfMissing(options.getStateDir())) if (!createIfMissing(options.getStateDir()))
return new CompilationResult(ERROR_FATAL); return RC_FATAL;
Path gensrc = options.getGenSrcDir(); Path gensrc = options.getGenSrcDir();
if (gensrc != null && !createIfMissing(gensrc)) if (gensrc != null && !createIfMissing(gensrc))
return new CompilationResult(ERROR_FATAL); return RC_FATAL;
Path hdrdir = options.getHeaderDir(); Path hdrdir = options.getHeaderDir();
if (hdrdir != null && !createIfMissing(hdrdir)) if (hdrdir != null && !createIfMissing(hdrdir))
return new CompilationResult(ERROR_FATAL); return RC_FATAL;
// Load the prev build state database. // Load the prev build state database.
JavacState javac_state = JavacState.load(options, out, err); JavacState javac_state = JavacState.load(options, out, err);
@ -132,9 +122,7 @@ public class SjavacImpl implements Sjavac {
if (sources.isEmpty()) { if (sources.isEmpty()) {
Log.error("Found nothing to compile!"); Log.error("Found nothing to compile!");
return new CompilationResult(CompilationResult.ERROR_FATAL, return RC_FATAL;
new String(outBaos.toByteArray(), UTF_8),
new String(errBaos.toByteArray(), UTF_8));
} }
@ -251,19 +239,13 @@ public class SjavacImpl implements Sjavac {
javac_state.removeSuperfluousArtifacts(recently_compiled); javac_state.removeSuperfluousArtifacts(recently_compiled);
} }
return new CompilationResult(rc[0] ? 0 : ERROR_FATAL, return rc[0] ? RC_OK : RC_FATAL;
new String(outBaos.toByteArray(), UTF_8),
new String(errBaos.toByteArray(), UTF_8));
} catch (ProblemException e) { } catch (ProblemException e) {
Log.error(e.getMessage()); Log.error(e.getMessage());
return new CompilationResult(ERROR_FATAL, return RC_FATAL;
new String(outBaos.toByteArray(), UTF_8),
new String(errBaos.toByteArray(), UTF_8));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(err); e.printStackTrace(new PrintWriter(err));
return new CompilationResult(ERROR_FATAL, return RC_FATAL;
new String(outBaos.toByteArray(), UTF_8),
new String(errBaos.toByteArray(), UTF_8));
} }
} }

View File

@ -24,6 +24,7 @@
*/ */
package com.sun.tools.sjavac.server; package com.sun.tools.sjavac.server;
import java.io.Writer;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -60,10 +61,10 @@ public class IdleResetSjavac implements Sjavac {
} }
@Override @Override
public CompilationResult compile(String[] args) { public int compile(String[] args, Writer out, Writer err) {
startCall(); startCall();
try { try {
return delegate.compile(args); return delegate.compile(args, out, err);
} finally { } finally {
endCall(); endCall();
} }

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.sjavac.server;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
/**
* Inserts {@literal prefix} in front of each line written.
*
* A line is considered to be terminated by any one of a line feed, a carriage
* return, or a carriage return followed immediately by a line feed.
*/
public class LinePrefixFilterWriter extends FilterWriter {
private final String prefix;
private boolean atBeginningOfLine = true;
private char lastChar = '\0';
protected LinePrefixFilterWriter(Writer out, String prefix) {
super(out);
this.prefix = prefix;
}
@Override
public void write(String str, int off, int len) throws IOException {
for (int i = 0; i < len; i++) {
write(str.charAt(off + i));
}
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
for (int i = 0; i < len; i++) {
write(cbuf[off + i]);
}
}
@Override
public void write(int c) throws IOException {
if (lastChar == '\r' && c == '\n') {
// Second character of CR+LF sequence.
// Do nothing. We already started a new line on last character.
} else {
if (atBeginningOfLine) {
super.write(prefix, 0, prefix.length());
}
super.write(c);
atBeginningOfLine = c == '\r' || c == '\n';
}
lastChar = (char) c;
}
}

View File

@ -24,15 +24,21 @@
*/ */
package com.sun.tools.sjavac.server; package com.sun.tools.sjavac.server;
import java.io.IOException; import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC;
import java.io.ObjectInputStream; import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDERR;
import java.io.ObjectOutputStream; import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDOUT;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer;
import java.net.Socket; import java.net.Socket;
import com.sun.tools.sjavac.AutoFlushWriter;
import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Log;
/** /**
* A RequestHandler handles requests performed over a socket. Specifically it * A RequestHandler handles requests performed over a socket. Specifically it
* - Reads the command string specifying which method is to be invoked * - Reads the command string specifying which method is to be invoked
@ -61,15 +67,26 @@ public class RequestHandler implements Runnable {
@Override @Override
public void run() { public void run() {
try (ObjectOutputStream oout = new ObjectOutputStream(socket.getOutputStream()); try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
ObjectInputStream oin = new ObjectInputStream(socket.getInputStream())) { PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String id = (String) oin.readObject();
String cmd = (String) oin.readObject(); // Read argument array
Log.info("Handling request, id: " + id + " cmd: " + cmd); int n = Integer.parseInt(in.readLine());
switch (cmd) { String[] args = new String[n];
case SjavacServer.CMD_COMPILE: handleCompileRequest(oin, oout); break; for (int i = 0; i < n; i++) {
default: Log.error("Unknown command: " + cmd); args[i] = in.readLine();
} }
// Perform compilation
Writer stdout = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDOUT + ":");
Writer stderr = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDERR + ":");
int rc = sjavac.compile(args, stdout, stderr);
stdout.flush();
stderr.flush();
// Send return code back to client
out.println(LINE_TYPE_RC + ":" + rc);
} catch (Exception ex) { } catch (Exception ex) {
// Not much to be done at this point. The client side request // Not much to be done at this point. The client side request
// code will most likely throw an IOException and the // code will most likely throw an IOException and the
@ -79,21 +96,4 @@ public class RequestHandler implements Runnable {
Log.error(sw.toString()); Log.error(sw.toString());
} }
} }
private void handleCompileRequest(ObjectInputStream oin,
ObjectOutputStream oout) throws IOException {
try {
// Read request arguments
String[] args = (String[]) oin.readObject();
// Perform compilation
CompilationResult cr = sjavac.compile(args);
// Write request response
oout.writeObject(cr);
oout.flush();
} catch (ClassNotFoundException cnfe) {
throw new IOException(cnfe);
}
}
} }

View File

@ -26,6 +26,7 @@
package com.sun.tools.sjavac.server; package com.sun.tools.sjavac.server;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter;
import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Log;
@ -38,7 +39,8 @@ import com.sun.tools.sjavac.Log;
public class ServerMain { public class ServerMain {
public static int run(String[] args) { public static int run(String[] args) {
Log.initializeLog(System.out, System.err); Log.initializeLog(new OutputStreamWriter(System.out),
new OutputStreamWriter(System.err));
// Any options other than --startserver? // Any options other than --startserver?
if (args.length > 1) { if (args.length > 1) {

View File

@ -24,6 +24,8 @@
*/ */
package com.sun.tools.sjavac.server; package com.sun.tools.sjavac.server;
import java.io.Writer;
/** /**
* Interface of the SjavacImpl, the sjavac client and all wrappers such as * Interface of the SjavacImpl, the sjavac client and all wrappers such as
@ -35,6 +37,10 @@ package com.sun.tools.sjavac.server;
* deletion without notice.</b> * deletion without notice.</b>
*/ */
public interface Sjavac { public interface Sjavac {
CompilationResult compile(String[] args);
final static int RC_FATAL = -1;
final static int RC_OK = 0;
int compile(String[] args, Writer stdout, Writer stderr);
void shutdown(); void shutdown();
} }

View File

@ -53,8 +53,10 @@ import com.sun.tools.sjavac.comp.SjavacImpl;
*/ */
public class SjavacServer implements Terminable { public class SjavacServer implements Terminable {
// Used in protocol to indicate which method to invoke // Used in protocol to tell the content of each line
public final static String CMD_COMPILE = "compile"; public final static String LINE_TYPE_RC = "RC";
public final static String LINE_TYPE_STDOUT = "STDOUT";
public final static String LINE_TYPE_STDERR = "STDERR";
final private String portfilename; final private String portfilename;
final private String logfile; final private String logfile;

View File

@ -31,8 +31,12 @@ import com.sun.source.util.TaskEvent.Kind;
import com.sun.source.util.TaskListener; import com.sun.source.util.TaskListener;
import com.sun.source.util.TreeScanner; import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.MultiTaskListener; import com.sun.tools.javac.api.MultiTaskListener;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.code.Types; import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.CompileStates; import com.sun.tools.javac.comp.CompileStates;
@ -93,23 +97,46 @@ class ReusableContext extends Context implements TaskListener {
//find if any of the roots have redefined java.* classes //find if any of the roots have redefined java.* classes
Symtab syms = Symtab.instance(this); Symtab syms = Symtab.instance(this);
new TreeScanner<Void, Void>() { pollutionScanner.scan(roots, syms);
@Override
public Void visitClass(ClassTree node, Void aVoid) {
Symbol sym = ((JCClassDecl)node).sym;
if (sym != null) {
syms.classes.remove(sym.flatName());
if (sym.flatName().toString().startsWith("java.")) {
polluted = true;
}
}
return super.visitClass(node, aVoid);
}
}.scan(roots, null);
roots.clear(); roots.clear();
} }
} }
/**
* This scanner detects as to whether the shared context has been polluted. This happens
* whenever a compiled program redefines a core class (in 'java.*' package) or when
* (typically because of cyclic inheritance) the symbol kind of a core class has been touched.
*/
TreeScanner<Void, Symtab> pollutionScanner = new TreeScanner<Void, Symtab>() {
@Override
public Void visitClass(ClassTree node, Symtab syms) {
Symbol sym = ((JCClassDecl)node).sym;
if (sym != null) {
syms.classes.remove(sym.flatName());
Type sup = supertype(sym);
if (isCoreClass(sym) ||
(sup != null && isCoreClass(sup.tsym) && sup.tsym.kind != Kinds.Kind.TYP)) {
polluted = true;
}
}
return super.visitClass(node, syms);
}
private boolean isCoreClass(Symbol s) {
return s.flatName().toString().startsWith("java.");
}
private Type supertype(Symbol s) {
if (s.type == null ||
!s.type.hasTag(TypeTag.CLASS)) {
return null;
} else {
ClassType ct = (ClassType)s.type;
return ct.supertype_field;
}
}
};
@Override @Override
public void finished(TaskEvent e) { public void finished(TaskEvent e) {
if (e.getKind() == Kind.PARSE) { if (e.getKind() == Kind.PARSE) {

View File

@ -56,6 +56,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.ServiceLoader;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
@ -76,6 +77,7 @@ import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement; import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeMirror;
import javax.tools.FileObject; import javax.tools.FileObject;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager; import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind; import javax.tools.JavaFileObject.Kind;
@ -88,7 +90,6 @@ import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.platform.PlatformProvider; import com.sun.tools.javac.platform.PlatformProvider;
import com.sun.tools.javac.util.ServiceLoader;
/**To generate the hash values for version N, invoke this class like: /**To generate the hash values for version N, invoke this class like:
* *
@ -243,7 +244,11 @@ public class ElementStructureTest {
} }
void run(Writer output, String version) throws Exception { void run(Writer output, String version) throws Exception {
JavacTaskImpl task = (JavacTaskImpl) ToolProvider.getSystemJavaCompiler().getTask(null, null, null, Arrays.asList("-release", version), null, Arrays.asList(new ToolBox.JavaSource("Test", ""))); List<String> options = Arrays.asList("-release", version, "-classpath", "");
List<ToolBox.JavaSource> files = Arrays.asList(new ToolBox.JavaSource("Test", ""));
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, null, options, null, files);
task.parse(); task.parse();
JavaFileManager fm = task.getContext().get(JavaFileManager.class); JavaFileManager fm = task.getContext().get(JavaFileManager.class);

View File

@ -29,9 +29,9 @@
* @build Wrapper * @build Wrapper
* @run main Wrapper IdleShutdown * @run main Wrapper IdleShutdown
*/ */
import java.io.Writer;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.IdleResetSjavac; import com.sun.tools.sjavac.server.IdleResetSjavac;
import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Sjavac;
import com.sun.tools.sjavac.server.Terminable; import com.sun.tools.sjavac.server.Terminable;
@ -65,11 +65,11 @@ public class IdleShutdown {
// Use Sjavac object and wait less than TIMEOUT_MS in between calls // Use Sjavac object and wait less than TIMEOUT_MS in between calls
Thread.sleep(TIMEOUT_MS - 1000); Thread.sleep(TIMEOUT_MS - 1000);
log("Compiling"); log("Compiling");
service.compile(new String[0]); service.compile(new String[0], null, null);
Thread.sleep(TIMEOUT_MS - 1000); Thread.sleep(TIMEOUT_MS - 1000);
log("Compiling"); log("Compiling");
service.compile(new String[0]); service.compile(new String[0], null, null);
if (timeoutTimestamp.get() != -1) if (timeoutTimestamp.get() != -1)
throw new AssertionError("Premature timeout detected."); throw new AssertionError("Premature timeout detected.");
@ -103,13 +103,13 @@ public class IdleShutdown {
public void shutdown() { public void shutdown() {
} }
@Override @Override
public CompilationResult compile(String[] args) { public int compile(String[] args, Writer out, Writer err) {
// Attempt to trigger idle timeout during a call by sleeping // Attempt to trigger idle timeout during a call by sleeping
try { try {
Thread.sleep(TIMEOUT_MS + 1000); Thread.sleep(TIMEOUT_MS + 1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
return null; return 0;
} }
} }
} }

View File

@ -30,11 +30,11 @@
* @build Wrapper * @build Wrapper
* @run main Wrapper PooledExecution * @run main Wrapper PooledExecution
*/ */
import java.io.Writer;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.comp.PooledSjavac;
import com.sun.tools.sjavac.server.CompilationResult;
import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Sjavac;
@ -67,7 +67,7 @@ public class PooledExecution {
for (int i = 0; i < NUM_REQUESTS; i++) { for (int i = 0; i < NUM_REQUESTS; i++) {
tasks[i] = new Thread() { tasks[i] = new Thread() {
public void run() { public void run() {
service.compile(new String[0]); service.compile(new String[0], null, null);
tasksFinished.incrementAndGet(); tasksFinished.incrementAndGet();
} }
}; };
@ -109,7 +109,7 @@ public class PooledExecution {
AtomicInteger activeRequests = new AtomicInteger(0); AtomicInteger activeRequests = new AtomicInteger(0);
@Override @Override
public CompilationResult compile(String[] args) { public int compile(String[] args, Writer out, Writer err) {
leftToStart.countDown(); leftToStart.countDown();
int numActiveRequests = activeRequests.incrementAndGet(); int numActiveRequests = activeRequests.incrementAndGet();
System.out.printf("Left to start: %2d / Currently active: %2d%n", System.out.printf("Left to start: %2d / Currently active: %2d%n",
@ -123,7 +123,7 @@ public class PooledExecution {
} }
activeRequests.decrementAndGet(); activeRequests.decrementAndGet();
System.out.println("Task completed"); System.out.println("Task completed");
return null; return 0;
} }
@Override @Override