Я использовал официальный пример сервера Socket , чтобы запустить сервер Socket для подключения к моему jacocoagent.jar. Я запускаю свой целевой jar следующим образом:
java -javaagent:jacocoagent.jar=dumponexit=false,output=tcpclient,address=localhost,port=6300 -jar demo-0.0.1-SNAPSHOT.jar
Я изменил код сервера, чтобы добавить метод для захвата дампа. Ниже приведен полный код:
public class JacocoSocketServer {
private static final String DESTFILE = "jacoco-server.exec";
private static final String ADDRESS = "localhost";
private static final int PORT = 6300;
private static final Logger LOGGER = Logger.getLogger(JacocoSocketServer.class.getName());
/**
* Start the server as a standalone program.
*
* @param args
* @throws IOException
*/
public static void main(final String[] args) throws IOException {
LOGGER.log(Level.INFO, "Output file is " + new File(DESTFILE).getAbsolutePath());
final RemoteControlWriter fileWriter = new RemoteControlWriter(new FileOutputStream(DESTFILE));
LOGGER.log(Level.INFO, "Starting TCP server on: " + ADDRESS + ":" + PORT);
final ServerSocket server = new ServerSocket(PORT, 0, InetAddress.getByName(ADDRESS));
final List<Handler> listHandler = new ArrayList<>();
Runnable runDumpTimer = () -> {
while (true) {
Iterator<Handler> it = listHandler.iterator();
while (it.hasNext()) {
Handler handler = it.next();
boolean toRemove = false;
String id = handler.getId();
try {
if (!handler.isAlive()) {
LOGGER.log(Level.INFO, String.format("Socket closed, removing handler: %s", id));
toRemove = true;
} else {
handler.captureDump(true, true);
}
} catch (IOException e) {
LOGGER.log(Level.INFO, "Socket error: " + e.getMessage() + ", removing handler: " + id);
toRemove = true;
} finally {
if (toRemove) {
it.remove();
}
}
}
}
};
Thread threadDumpTimer = new Thread(runDumpTimer, "threadDumpTimer");
threadDumpTimer.start();
while (true) {
Socket socket = server.accept();
System.out.println("Remote connection detected, openning socket on local port: "
+ socket.getLocalPort());
final Handler handler = new Handler(socket, fileWriter);
listHandler.add(handler);
new Thread(handler).start();
}
}
private static class Handler
implements
Runnable,
ISessionInfoVisitor,
IExecutionDataVisitor {
private final Socket socket;
private final RemoteControlReader reader;
private final RemoteControlWriter fileWriter;
private final RemoteControlWriter remoteWriter;
private String id;
public String getId() {
return id;
}
Handler(final Socket socket, final RemoteControlWriter fileWriter) throws IOException {
this.socket = socket;
this.fileWriter = fileWriter;
// Just send a valid header:
remoteWriter = new RemoteControlWriter(socket.getOutputStream());
reader = new RemoteControlReader(socket.getInputStream());
reader.setSessionInfoVisitor(this);
reader.setExecutionDataVisitor(this);
}
public void run() {
try {
while (reader.read()) {
}
socket.close();
synchronized (fileWriter) {
fileWriter.flush();
}
} catch (final IOException e) {
e.printStackTrace();
}
}
public void visitSessionInfo(final SessionInfo info) {
id = info.getId();
LOGGER.log(Level.INFO, String.format("Retrieving execution Data for session: %s", info.getId()));
synchronized (fileWriter) {
fileWriter.visitSessionInfo(info);
}
}
public void visitClassExecution(final ExecutionData data) {
synchronized (fileWriter) {
fileWriter.visitClassExecution(data);
}
}
void captureDump(boolean dump, boolean reset) throws IOException {
remoteWriter.visitDumpCommand(dump, reset);
}
boolean isAlive() {
return socket != null
&& socket.isConnected();
}
}
}
Приведенный выше код будет бесконечно продолжать записывать дампы в указанный файл, что, очевидно, не является ожидаемым результатом.
Как только я запускаю сервер, Затем я запускаю целевой jar, и я выполню несколько функциональных тестовых случаев на jar. После завершения этих тестовых случаев я хочу запустить дамп данных выполнения и сбросить хранилище, чтобы в следующий раз, когда я запустил дамп, в нем были только данные о соответствующем сеансе.
PS: я использовал для запуска сервер периодически принимает дампы через определенные промежутки времени (отсюда и некоторые имена переменных), но это больше не нужно.
PPS: я прочитал следующие вопросы, у всех из которых были схожие требования к моим , но я не смог найти способ удаленного сброса данных по команде:
https://groups.google.com/forum/#! msg / jacoco / MUTIM5yS6ZQ / KSA5Og4xBgAJ
https://sourceforge.net/p/eclemma/discussion/614870/thread/083acdaa/
https://groups.google.com/forum/#! Topic / jacoco / QAmXUZjviPk
https://groups.google.com/forum/#! Msg / jacoco / V7Bmz5r0P24 / PdCC5apIoqgJ