首先看sonar后台的启动进程:

[root@uranuspreweb34 logs]# ps -ef | grep java
root      3169  3167  0 Apr19 ?        00:06:04 java -Dsonar.wrapped=true -Djava.awt.headless=true -Xms8m -Xmx8m -Djava.library.path=./lib -classpath ../../lib/jsw/wrapper-3.2.3.jar:../../lib/sonar-application-6.2.jar -Dwrapper.key=t7uBnfyOYRRUy2un -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=3167 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp org.sonar.application.App
root      3200  3169  4 Apr19 ?        06:33:32 /usr/java/jdk1.8.0_51/jre/bin/java -Djava.awt.headless=true -Xms4G -Xmx8G -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=7094 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.37.124.178 -Djava.io.tmpdir=/opt/CI/sonarqube-6.2/temp -javaagent:/usr/java/jdk1.8.0_51/jre/lib/management-agent.jar -cp ./lib/common/*:./lib/search/* org.sonar.search.SearchServer /opt/CI/sonarqube-6.2/temp/sq-process1495333341950424468properties
root      3351  3169  3 Apr19 ?        05:25:40 /usr/java/jdk1.8.0_51/jre/bin/java -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djruby.management.enabled=false -Djruby.compile.invokedynamic=false -Xms4g -Xmx4g -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=7095 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.37.124.178 -Djava.io.tmpdir=/opt/CI/sonarqube-6.2/temp -javaagent:/usr/java/jdk1.8.0_51/jre/lib/management-agent.jar -cp ./lib/common/*:./lib/server/*:/opt/CI/sonarqube-6.2/lib/jdbc/mysql/mysql-connector-java-5.1.39.jar org.sonar.server.app.WebServer /opt/CI/sonarqube-6.2/temp/sq-process368230285702864980properties
root      3540  3169 41 Apr19 ?        2-10:22:17 /usr/java/jdk1.8.0_51/jre/bin/java -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Xmx8G -Xms4G -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=7093 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=10.37.124.178 -Djava.io.tmpdir=/opt/CI/sonarqube-6.2/temp -javaagent:/usr/java/jdk1.8.0_51/jre/lib/management-agent.jar -cp ./lib/common/*:./lib/server/*:./lib/ce/*:/opt/CI/sonarqube-6.2/lib/jdbc/mysql/mysql-connector-java-5.1.39.jar org.sonar.ce.app.CeServer /opt/CI/sonarqube-6.2/temp/sq-process599434287403847159properties

从进程的启动逻辑看是 WrapperSimpleApp 进程拉起来的 web, search, ce进程

WrapperSimpleApp 对应的是sonar-qube6.2源码包中的sonar-application这个子工程,这个下面就有

main 入口是App:

/** SonarQube* Copyright (C) 2009-2016 SonarSource SA* mailto:contact AT sonarsource DOT com** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 3 of the License, or (at your option) any later version.** This program 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* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public License* along with this program; if not, write to the Free Software Foundation,* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
package org.sonar.application;import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.process.Lifecycle;
import org.sonar.process.ProcessId;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
import org.sonar.process.Stoppable;
import org.sonar.process.monitor.JavaCommand;
import org.sonar.process.monitor.Monitor;import static org.sonar.process.Lifecycle.State;
import static org.sonar.process.ProcessId.APP;
import static org.sonar.process.ProcessProperties.HTTPS_PROXY_HOST;
import static org.sonar.process.ProcessProperties.HTTPS_PROXY_PORT;
import static org.sonar.process.ProcessProperties.HTTP_PROXY_HOST;
import static org.sonar.process.ProcessProperties.HTTP_PROXY_PORT;/*** Entry-point of process that starts and monitors ElasticSearch, the Web Server and the Compute Engine.*/
public class App implements Stoppable {/*** Properties about proxy that must be set as system properties*/private static final String[] PROXY_PROPERTY_KEYS = new String[] {HTTP_PROXY_HOST,HTTP_PROXY_PORT,"http.nonProxyHosts",HTTPS_PROXY_HOST,HTTPS_PROXY_PORT,"http.auth.ntlm.domain","socksProxyHost","socksProxyPort"};private final Monitor monitor;public App(AppFileSystem appFileSystem, boolean watchForHardStop) {this(Monitor.create(APP.getIpcIndex(), appFileSystem, watchForHardStop, new AppLifecycleListener()));}App(Monitor monitor) {this.monitor = monitor;}public void start(Props props) throws InterruptedException {monitor.start(createCommands(props));monitor.awaitTermination();}private static List<JavaCommand> createCommands(Props props) {File homeDir = props.nonNullValueAsFile(ProcessProperties.PATH_HOME);List<JavaCommand> commands = new ArrayList<>(3);if (isProcessEnabled(props, ProcessProperties.CLUSTER_SEARCH_DISABLED)) {commands.add(createESCommand(props, homeDir));}if (isProcessEnabled(props, ProcessProperties.CLUSTER_WEB_DISABLED)) {commands.add(createWebServerCommand(props, homeDir));}if (isProcessEnabled(props, ProcessProperties.CLUSTER_CE_DISABLED)) {commands.add(createCeServerCommand(props, homeDir));}return commands;}private static boolean isProcessEnabled(Props props, String disabledPropertyKey) {return !props.valueAsBoolean(ProcessProperties.CLUSTER_ENABLED) ||!props.valueAsBoolean(disabledPropertyKey);}private static JavaCommand createESCommand(Props props, File homeDir) {return newJavaCommand(ProcessId.ELASTICSEARCH, props, homeDir).addJavaOptions("-Djava.awt.headless=true").addJavaOptions(props.nonNullValue(ProcessProperties.SEARCH_JAVA_OPTS)).addJavaOptions(props.nonNullValue(ProcessProperties.SEARCH_JAVA_ADDITIONAL_OPTS)).setClassName("org.sonar.search.SearchServer").addClasspath("./lib/common/*").addClasspath("./lib/search/*");}private static JavaCommand createWebServerCommand(Props props, File homeDir) {JavaCommand command = newJavaCommand(ProcessId.WEB_SERVER, props, homeDir).addJavaOptions(ProcessProperties.WEB_ENFORCED_JVM_ARGS).addJavaOptions(props.nonNullValue(ProcessProperties.WEB_JAVA_OPTS)).addJavaOptions(props.nonNullValue(ProcessProperties.WEB_JAVA_ADDITIONAL_OPTS))// required for logback tomcat valve.setEnvVariable(ProcessProperties.PATH_LOGS, props.nonNullValue(ProcessProperties.PATH_LOGS))// ensure JRuby uses SQ's temp directory as temp directory (eg. for temp files used during HTTP uploads).setEnvVariable("TMPDIR", props.nonNullValue(ProcessProperties.PATH_TEMP)).setClassName("org.sonar.server.app.WebServer").addClasspath("./lib/common/*").addClasspath("./lib/server/*");String driverPath = props.value(ProcessProperties.JDBC_DRIVER_PATH);if (driverPath != null) {command.addClasspath(driverPath);}return command;}private static JavaCommand createCeServerCommand(Props props, File homeDir) {JavaCommand command = newJavaCommand(ProcessId.COMPUTE_ENGINE, props, homeDir).addJavaOptions(ProcessProperties.CE_ENFORCED_JVM_ARGS).addJavaOptions(props.nonNullValue(ProcessProperties.CE_JAVA_OPTS)).addJavaOptions(props.nonNullValue(ProcessProperties.CE_JAVA_ADDITIONAL_OPTS)).setClassName("org.sonar.ce.app.CeServer").addClasspath("./lib/common/*").addClasspath("./lib/server/*").addClasspath("./lib/ce/*");String driverPath = props.value(ProcessProperties.JDBC_DRIVER_PATH);if (driverPath != null) {command.addClasspath(driverPath);}return command;}private static JavaCommand newJavaCommand(ProcessId id, Props props, File homeDir) {JavaCommand command = new JavaCommand(id).setWorkDir(homeDir).setArguments(props.rawProperties());for (String key : PROXY_PROPERTY_KEYS) {if (props.contains(key)) {command.addJavaOption("-D" + key + "=" + props.value(key));}}// defaults of HTTPS are the same than HTTP defaultssetSystemPropertyToDefaultIfNotSet(command, props, HTTPS_PROXY_HOST, HTTP_PROXY_HOST);setSystemPropertyToDefaultIfNotSet(command, props, HTTPS_PROXY_PORT, HTTP_PROXY_PORT);return command;}private static void setSystemPropertyToDefaultIfNotSet(JavaCommand command, Props props, String httpsProperty, String httpProperty) {if (!props.contains(httpsProperty) && props.contains(httpProperty)) {command.addJavaOption("-D" + httpsProperty + "=" + props.value(httpProperty));}}static String starPath(File homeDir, String relativePath) {File dir = new File(homeDir, relativePath);return FilenameUtils.concat(dir.getAbsolutePath(), "*");}public static void main(String[] args) throws InterruptedException {CommandLineParser cli = new CommandLineParser();Properties rawProperties = cli.parseArguments(args);Props props = new PropsBuilder(rawProperties, new JdbcSettings()).build();AppFileSystem appFileSystem = new AppFileSystem(props);appFileSystem.verifyProps();AppLogging logging = new AppLogging();logging.configure(props);// used by orchestratorboolean watchForHardStop = props.valueAsBoolean(ProcessProperties.ENABLE_STOP_COMMAND, false);App app = new App(appFileSystem, watchForHardStop);app.start(props);}@Overridepublic void stopAsync() {monitor.stop();}private static class AppLifecycleListener implements Lifecycle.LifecycleListener {private static final Logger LOGGER = LoggerFactory.getLogger(App.class);@Overridepublic void successfulTransition(State from, State to) {if (to == State.STARTED) {LOGGER.info("SonarQube is up");}}}
}

main方法中加载properties文件然后调用start方法,(创建ce,es,web进程)然后再次根据properties创建command去启动jvm,然后再调用minor中start方法。

minor类:minor类是sonar-process-monitor模块中的类

/** SonarQube* Copyright (C) 2009-2016 SonarSource SA* mailto:contact AT sonarsource DOT com** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 3 of the License, or (at your option) any later version.** This program 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* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public License* along with this program; if not, write to the Free Software Foundation,* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
package org.sonar.process.monitor;import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.CheckForNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.process.DefaultProcessCommands;
import org.sonar.process.Lifecycle;
import org.sonar.process.Lifecycle.State;
import org.sonar.process.ProcessId;
import org.sonar.process.ProcessUtils;
import org.sonar.process.SystemExit;import static org.sonar.process.DefaultProcessCommands.reset;public class Monitor {private static final Logger LOG = LoggerFactory.getLogger(Monitor.class);private static final Timeouts TIMEOUTS = new Timeouts();private static final long WATCH_DELAY_MS = 500L;private static int restartorInstanceCounter = 0;private final int processNumber;private final FileSystem fileSystem;private final SystemExit systemExit;private final boolean watchForHardStop;private final Thread shutdownHook = new Thread(new MonitorShutdownHook(), "Monitor Shutdown Hook");private final List<WatcherThread> watcherThreads = new CopyOnWriteArrayList<>();private final Lifecycle lifecycle;private final TerminatorThread terminator = new TerminatorThread();private final RestartRequestWatcherThread restartWatcher = new RestartRequestWatcherThread();@CheckForNullprivate List<JavaCommand> javaCommands;@CheckForNullprivate JavaProcessLauncher launcher;@CheckForNullprivate RestartorThread restartor;@CheckForNullHardStopWatcherThread hardStopWatcher;Monitor(int processNumber, FileSystem fileSystem, SystemExit exit, boolean watchForHardStop, Lifecycle.LifecycleListener... listeners) {this.processNumber = processNumber;this.fileSystem = fileSystem;this.systemExit = exit;this.watchForHardStop = watchForHardStop;this.lifecycle = new Lifecycle(listeners);}public static Monitor create(int processNumber, FileSystem fileSystem, boolean watchForHardStop) {return new Monitor(processNumber, fileSystem, new SystemExit(), watchForHardStop);}public static Monitor create(int processNumber, FileSystem fileSystem, boolean watchForHardStop, Lifecycle.LifecycleListener listener) {return new Monitor(processNumber, fileSystem, new SystemExit(), watchForHardStop, Objects.requireNonNull(listener));}/*** Starts commands and blocks current thread until all processes are in state {@link State#STARTED}.* @throws java.lang.IllegalArgumentException if commands list is empty* @throws java.lang.IllegalStateException if already started or if at least one process failed to start. In this case*   all processes are terminated. No need to execute {@link #stop()}*/public void start(List<JavaCommand> commands) throws InterruptedException {if (commands.isEmpty()) {throw new IllegalArgumentException("At least one command is required");}if (lifecycle.getState() != State.INIT) {throw new IllegalStateException("Can not start multiple times");}// intercepts CTRL-CRuntime.getRuntime().addShutdownHook(shutdownHook);// start watching for restart requested by child processrestartWatcher.start();javaCommands = commands;startProcesses();}private void startProcesses() throws InterruptedException {// do no start any child process if not in state INIT or RESTARTING (a stop could be in progress too)if (lifecycle.tryToMoveTo(State.STARTING)) {resetFileSystem();// start watching for stop requested by other process (eg. orchestrator) if enabled and not started yetif (watchForHardStop && hardStopWatcher == null) {hardStopWatcher = new HardStopWatcherThread();hardStopWatcher.start();}startAndMonitorProcesses();stopIfAnyProcessDidNotStart();}}private void resetFileSystem() {// since JavaLauncher depends on temp directory, which is reset below, we need to close it firstcloseJavaLauncher();try {fileSystem.reset();} catch (IOException e) {// failed to reset FileSystemthrow new RuntimeException("Failed to reset file system", e);}// reset sharedmemory of Appreset(fileSystem.getTempDir(), ProcessId.APP.getIpcIndex());}private void closeJavaLauncher() {if (this.launcher != null) {this.launcher.close();this.launcher = null;}}private void startAndMonitorProcesses() throws InterruptedException{File tempDir = fileSystem.getTempDir();this.launcher = new JavaProcessLauncher(TIMEOUTS, tempDir);for (JavaCommand command : javaCommands) {ProcessRef processRef = null;try {processRef = launcher.launch(command);monitor(processRef);} catch (InterruptedException | RuntimeException e) {if (processRef != null) {LOG.error("{} failed to start", processRef);}// fail to start or to monitorstop();throw e;}}}private void monitor(ProcessRef processRef) throws InterruptedException {// physically watch if process is aliveWatcherThread watcherThread = new WatcherThread(processRef, this);watcherThread.start();watcherThreads.add(watcherThread);// wait for process to be ready (accept requests or so on)processRef.waitForUp();LOG.info("{} is up", processRef);}private void stopIfAnyProcessDidNotStart() {if (!lifecycle.tryToMoveTo(State.STARTED)) {// stopping or stopped during startup, for instance :// 1. A is started// 2. B starts// 3. A crashes while B is starting// 4. if B was not monitored during Terminator execution, then it's an alive orphanstop();throw new IllegalStateException("Stopped during startup");}}/*** Blocks until all processes are terminated*/public void awaitTermination() {while (awaitChildProcessesTermination()) {trace("await termination of restartor...");ProcessUtils.awaitTermination(restartor);}cleanAfterTermination();}boolean waitForOneRestart() {boolean restartRequested = awaitChildProcessesTermination();trace("finished waiting, restartRequested={}", restartRequested);if (restartRequested) {trace("awaitTermination restartor={}", restartor);ProcessUtils.awaitTermination(restartor);}return restartRequested;}private boolean awaitChildProcessesTermination() {trace("await termination of child processes...");List<WatcherThread> watcherThreadsCopy = new ArrayList<>(this.watcherThreads);for (WatcherThread watcherThread : watcherThreadsCopy) {ProcessUtils.awaitTermination(watcherThread);}trace("all child processes done");return hasRestartBeenRequested(watcherThreadsCopy);}private static boolean hasRestartBeenRequested(List<WatcherThread> watcherThreads) {for (WatcherThread watcherThread : watcherThreads) {if (watcherThread.isAskedForRestart()) {trace("one child process requested restart");return true;}}trace("no child process requested restart");return false;}/*** Blocks until all processes are terminated.*/public void stop() {trace("start hard stop async...");stopAsync(State.HARD_STOPPING);trace("await termination of terminator...");ProcessUtils.awaitTermination(terminator);cleanAfterTermination();trace("exit...");systemExit.exit(0);}private void cleanAfterTermination() {trace("go to STOPPED...");if (lifecycle.tryToMoveTo(State.STOPPED)) {trace("await termination of restartWatcher and hardStopWatcher...");// wait for restartWatcher and hardStopWatcher to cleanly stopProcessUtils.awaitTermination(restartWatcher, hardStopWatcher);trace("restartWatcher done");// removing shutdown hook to avoid called stop() unnecessarily unless already in shutdownHookif (!systemExit.isInShutdownHook()) {trace("removing shutdown hook...");Runtime.getRuntime().removeShutdownHook(shutdownHook);}// cleanly close JavaLaunchercloseJavaLauncher();}}/*** Asks for processes termination and returns without blocking until termination.* However, if a termination request is already under way (it's not supposed to happen, but, technically, it can occur),* this call will be blocking until the previous request finishes.*/public void stopAsync() {stopAsync(State.STOPPING);}private void stopAsync(State stoppingState) {assert stoppingState == State.STOPPING || stoppingState == State.HARD_STOPPING;if (lifecycle.tryToMoveTo(stoppingState)) {terminator.start();}}public void restartAsync() {if (lifecycle.tryToMoveTo(State.RESTARTING)) {restartor = new RestartorThread();restartor.start();}}/*** Runs every time a restart request is detected.*/private class RestartorThread extends Thread {private RestartorThread() {super("Restartor " + (restartorInstanceCounter++));}@Overridepublic void run() {stopProcesses();try {startProcesses();} catch (InterruptedException e) {// Startup was interrupted. Processes are being stopped asynchronously.// Restoring the interruption state.Thread.currentThread().interrupt();}}}/*** Runs only once*/private class TerminatorThread extends Thread {private TerminatorThread() {super("Terminator");}@Overridepublic void run() {stopProcesses();}}/*** Watches for any child process requesting a restart of all children processes.* It runs once and as long as {@link #lifecycle} hasn't reached {@link Lifecycle.State#STOPPED} and holds its checks* when {@link #lifecycle} is not in state {@link Lifecycle.State#STARTED} to avoid taking the same request into account* twice.*/public class RestartRequestWatcherThread extends Thread {public RestartRequestWatcherThread() {super("Restart watcher");}@Overridepublic void run() {while (lifecycle.getState() != Lifecycle.State.STOPPED) {if (lifecycle.getState() == Lifecycle.State.STARTED && didAnyProcessRequestRestart()) {restartAsync();}try {Thread.sleep(WATCH_DELAY_MS);} catch (InterruptedException ignored) {// keep watching}}}private boolean didAnyProcessRequestRestart() {for (WatcherThread watcherThread : watcherThreads) {ProcessRef processRef = watcherThread.getProcessRef();if (processRef.getCommands().askedForRestart()) {LOG.info("Process [{}] requested restart", processRef.getKey());return true;}}return false;}}public class HardStopWatcherThread extends Thread {public HardStopWatcherThread() {super("Hard stop watcher");}@Overridepublic void run() {while (lifecycle.getState() != Lifecycle.State.STOPPED) {if (askedForStop()) {trace("Stopping process");Monitor.this.stop();} else {delay();}}}private boolean askedForStop() {File tempDir = fileSystem.getTempDir();try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(tempDir, processNumber)) {if (processCommands.askedForStop()) {return true;}}return false;}private void delay() {try {Thread.sleep(WATCH_DELAY_MS);} catch (InterruptedException ignored) {// keep watching}}}private void stopProcesses() {List<WatcherThread> watcherThreadsCopy = new ArrayList<>(this.watcherThreads);// create a copy and reverse it to terminate in reverse order of startup (dependency order)Collections.reverse(watcherThreadsCopy);for (WatcherThread watcherThread : watcherThreadsCopy) {ProcessRef ref = watcherThread.getProcessRef();if (!ref.isStopped()) {LOG.info("{} is stopping", ref);ref.askForGracefulAsyncStop();long killAt = System.currentTimeMillis() + TIMEOUTS.getTerminationTimeout();while (!ref.isStopped() && System.currentTimeMillis() < killAt) {try {Thread.sleep(10L);} catch (InterruptedException e) {// stop asking for graceful stops, Monitor will hardly kill all processesbreak;}}if (!ref.isStopped()) {LOG.info("{} failed to stop in a timely fashion. Killing it.", ref);}ref.stop();LOG.info("{} is stopped", ref);}}// all processes are stopped, no need to keep references to these WatcherThread anymoretrace("all processes stopped, clean list of watcherThreads...");this.watcherThreads.clear();}public State getState() {return lifecycle.getState();}Thread getShutdownHook() {return shutdownHook;}private class MonitorShutdownHook implements Runnable {@Overridepublic void run() {systemExit.setInShutdownHook();trace("calling stop from MonitorShutdownHook...");// blocks until everything is corrected terminatedstop();}}private static void trace(String s) {LOG.trace(s);}private static void trace(String s, Object args) {LOG.trace(s, args);}}

这个类中最为关键的就是startAndMonitorProcesses方法,然后调用JavaProcessLauncher lauccher方法,同时将对应的command转换ProcessRef bean对象。

 private void startAndMonitorProcesses() throws InterruptedException{File tempDir = fileSystem.getTempDir();this.launcher = new JavaProcessLauncher(TIMEOUTS, tempDir);for (JavaCommand command : javaCommands) {ProcessRef processRef = null;try {processRef = launcher.launch(command);monitor(processRef);} catch (InterruptedException | RuntimeException e) {if (processRef != null) {LOG.error("{} failed to start", processRef);}// fail to start or to monitorstop();throw e;}}}
/** SonarQube* Copyright (C) 2009-2016 SonarSource SA* mailto:contact AT sonarsource DOT com** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 3 of the License, or (at your option) any later version.** This program 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* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public License* along with this program; if not, write to the Free Software Foundation,* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
package org.sonar.process.monitor;import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import org.slf4j.LoggerFactory;
import org.sonar.process.AllProcessesCommands;
import org.sonar.process.ProcessCommands;
import org.sonar.process.ProcessEntryPoint;
import org.sonar.process.ProcessUtils;import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_KEY;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT;class JavaProcessLauncher {private final Timeouts timeouts;private final File tempDir;private final AllProcessesCommands allProcessesCommands;JavaProcessLauncher(Timeouts timeouts, File tempDir) {this.timeouts = timeouts;this.tempDir = tempDir;this.allProcessesCommands = new AllProcessesCommands(tempDir);}public void close() {allProcessesCommands.close();}ProcessRef launch(JavaCommand command) {Process process = null;try {ProcessCommands commands = allProcessesCommands.createAfterClean(command.getProcessId().getIpcIndex());ProcessBuilder processBuilder = create(command);LoggerFactory.getLogger(getClass()).info("Launch process[{}]: {}",command.getProcessId().getKey(), StringUtils.join(processBuilder.command(), " "));process = processBuilder.start();StreamGobbler inputGobbler = new StreamGobbler(process.getInputStream(), command.getProcessId().getKey());inputGobbler.start();return new ProcessRef(command.getProcessId().getKey(), commands, process, inputGobbler);} catch (Exception e) {// just in caseProcessUtils.sendKillSignal(process);throw new IllegalStateException("Fail to launch [" + command.getProcessId().getKey() + "]", e);}}private ProcessBuilder create(JavaCommand javaCommand) {List<String> commands = new ArrayList<>();commands.add(buildJavaPath());commands.addAll(javaCommand.getJavaOptions());// TODO warning - does it work if temp dir contains a whitespace ?commands.add(String.format("-Djava.io.tmpdir=%s", tempDir.getAbsolutePath()));commands.add(getJmxAgentCommand());commands.addAll(buildClasspath(javaCommand));commands.add(javaCommand.getClassName());commands.add(buildPropertiesFile(javaCommand).getAbsolutePath());ProcessBuilder processBuilder = new ProcessBuilder();processBuilder.command(commands);processBuilder.directory(javaCommand.getWorkDir());processBuilder.environment().putAll(javaCommand.getEnvVariables());processBuilder.redirectErrorStream(true);return processBuilder;}/*** JVM option to enable the agent that allows inter-process communication through JMX without* opening new ports. The agent is available in JRE of OpenJDK/OracleJDK only.* @see ProcessEntryPoint*/private static String getJmxAgentCommand() {return "-javaagent:" + System.getProperty("java.home") + File.separator + "lib" + File.separator + "management-agent.jar";}private String buildJavaPath() {String separator = System.getProperty("file.separator");return new File(new File(System.getProperty("java.home")), "bin" + separator + "java").getAbsolutePath();}private List<String> buildClasspath(JavaCommand javaCommand) {return Arrays.asList("-cp", StringUtils.join(javaCommand.getClasspath(), System.getProperty("path.separator")));}private File buildPropertiesFile(JavaCommand javaCommand) {File propertiesFile = null;try {propertiesFile = File.createTempFile("sq-process", "properties", tempDir);Properties props = new Properties();props.putAll(javaCommand.getArguments());props.setProperty(PROPERTY_PROCESS_KEY, javaCommand.getProcessId().getKey());props.setProperty(PROPERTY_PROCESS_INDEX, Integer.toString(javaCommand.getProcessId().getIpcIndex()));props.setProperty(PROPERTY_TERMINATION_TIMEOUT, String.valueOf(timeouts.getTerminationTimeout()));props.setProperty(PROPERTY_SHARED_PATH, tempDir.getAbsolutePath());try (OutputStream out = new FileOutputStream(propertiesFile)) {props.store(out, String.format("Temporary properties file for command [%s]", javaCommand.getProcessId().getKey()));}return propertiesFile;} catch (Exception e) {throw new IllegalStateException("Cannot write temporary settings to " + propertiesFile, e);}}
}

这个类调用jdk中ProcessBuilder拉起的jvm进程。

SonarQube6.2源码解析(一)相关推荐

  1. SonarQube6.2源码解析(四)

    sonar ce 的启动过程 /** SonarQube* Copyright (C) 2009-2016 SonarSource SA* mailto:contact AT sonarsource ...

  2. SonarQube6.2源码解析(三)

    sonar web 启动过程,sonar-web 下面含有的代码了还是很大的,主main入口是webserver: webserver类代码: /** SonarQube* Copyright (C) ...

  3. SonarQube6.2源码解析(二)

    分别看下 es(elasticSearch),ce,web 进程入口. es: main入口类 SearchServer: /** SonarQube* Copyright (C) 2009-2016 ...

  4. 谷歌BERT预训练源码解析(二):模型构建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_39470744/arti ...

  5. 谷歌BERT预训练源码解析(三):训练过程

    目录 前言 源码解析 主函数 自定义模型 遮蔽词预测 下一句预测 规范化数据集 前言 本部分介绍BERT训练过程,BERT模型训练过程是在自己的TPU上进行的,这部分我没做过研究所以不做深入探讨.BE ...

  6. 谷歌BERT预训练源码解析(一):训练数据生成

    目录 预训练源码结构简介 输入输出 源码解析 参数 主函数 创建训练实例 下一句预测&实例生成 随机遮蔽 输出 结果一览 预训练源码结构简介 关于BERT,简单来说,它是一个基于Transfo ...

  7. Gin源码解析和例子——中间件(middleware)

    在<Gin源码解析和例子--路由>一文中,我们已经初识中间件.本文将继续探讨这个技术.(转载请指明出于breaksoftware的csdn博客) Gin的中间件,本质是一个匿名回调函数.这 ...

  8. Colly源码解析——结合例子分析底层实现

    通过<Colly源码解析--框架>分析,我们可以知道Colly执行的主要流程.本文将结合http://go-colly.org上的例子分析一些高级设置的底层实现.(转载请指明出于break ...

  9. libev源码解析——定时器监视器和组织形式

    我们先看下定时器监视器的数据结构.(转载请指明出于breaksoftware的csdn博客) /* invoked after a specific time, repeatable (based o ...

最新文章

  1. 【VB】学生信息管理系统1——系统设计怎样开始?
  2. Android开发究竟该如何学习,含泪整理面经
  3. 2016秋季阅读计划
  4. Spring WebApplicationContext
  5. ERROR: cannot launch node of type [turtlebot_teleop/turtlebot_teleop_key] 问题解决
  6. java多线程之wait和notify协作,生产者和消费者
  7. 30 万奖金等你来!第三届 Apache Flink 极客挑战赛暨 AAIG CUP 报名开始
  8. Java8 实战系列-03-lambda 表达式实战
  9. 百度之星1000——A+B问题
  10. IBM携手百洋医药 将沃森超级电脑带给中国肿瘤科医师
  11. 【西北师大-2108Java】第二次作业成绩汇总
  12. Spring boot项目启动报无法加载主类
  13. BufferedImage 图片背景色黑色问题
  14. ScanContext 论文详解 - 用途:Lidar SLAM 回环检测、空间描述符
  15. 解决 IE下ajaxfileupload不兼容的问题
  16. 轨迹规划 trajectory planning
  17. 算法分析与设计第五章作业
  18. 虚拟内存,物理内存,页面文件,还有任务管理器
  19. jsp使用URLRewrite实现url地址伪静态化
  20. Vant-area数据

热门文章

  1. Learning representations by back-propagating errors原文解读
  2. ubuntu突然连不上-调试方式
  3. 云主机上mysql密码重置
  4. service不是内部或者外部命令
  5. Machine Learning之Python篇(一)
  6. 深度学习(十)——花式卷积(2)
  7. python打印楼梯和笑脸_Python实现打印楼梯形状图形
  8. java性能调优工具--笔记
  9. 字符流---IO学习笔记(三)
  10. iOS10 CallKit简单开发