publicclassProcessBootstrap { /** * Sets up the ClassLoader structure for the given class, creates an instance and invokes {@link EntryPoint#run(String[])} on it. */ publicstaticvoidrun(String mainClassName, String[] args) { try { runNoExit(mainClassName, args); System.exit(0); } catch (Throwable throwable) { throwable.printStackTrace(); System.exit(1); } }
publicinterfaceModule { /** * Returns the classpath for the module implementation. This is the classpath of the module itself. Does not include any dependencies. */ ClassPath getImplementationClasspath();
/** * Returns the classpath containing the runtime dependencies of the module. Does not include any other modules. */ ClassPath getRuntimeClasspath();
/** * Returns the modules required by this module. */ Set<Module> getRequiredModules();
/** * Returns the transitive closure of all modules required by this module, including the module itself. */ Set<Module> getAllRequiredModules();
/** * Returns the implementation + runtime classpath of the transitive closure of all modules required by this module, including the module itself. */ ClassPath getAllRequiredModulesClasspath(); }
publicinterfaceModuleRegistry { /** * Locates an external module by name. An external module is one for which there is no meta-data available. Assumed to be packaged as a single jar file, and to have no runtime dependencies. * * @return the module. Does not return null. */ Module getExternalModule(String name)throws UnknownModuleException;
/** * Locates a module by name. * * @return the module. Does not return null. */ Module getModule(String name)throws UnknownModuleException;
/** * Tries to locate a module by name. * * @return the optional module, or {@literal null} if it cannot be found * @throws UnknownModuleException if the requested module is found but one of its dependencies is not */ @Nullable Module findModule(String name)throws UnknownModuleException;
/** * Returns the classpath used to search for modules, in addition to default locations in the Gradle distribution (if available). May be empty. */ ClassPath getAdditionalClassPath(); }
ClassPathProvider
依据模块name获取模块运行时所需的所有classpath
1 2 3 4 5 6 7
publicinterfaceClassPathProvider { /** * Returns the files for the given classpath, if known. Returns null for unknown classpath. */ @Nullable ClassPath findClassPath(String name); }
publicinterfaceClassLoaderFactory { /** * Returns the ClassLoader that will be used as the parent for all isolated ClassLoaders. */ ClassLoader getIsolatedSystemClassLoader();
/** * Creates a ClassLoader implementation which has only the classes from the specified URIs and the Java API visible. */ ClassLoader createIsolatedClassLoader(String name, ClassPath classPath);
/** * Creates a ClassLoader implementation which has, by default, only the classes from the Java API visible, but which can allow access to selected classes from the given parent ClassLoader. * * @param parent the parent ClassLoader * @param spec the filtering spec for the classloader * @return The ClassLoader */ ClassLoader createFilteringClassLoader(ClassLoader parent, FilteringClassLoader.Spec spec); }
// Calculate the logging configuration loggingBuildOptions.convert(parsedCommandLine, properties, loggingConfiguration);
// Get configuration for showing the welcome message welcomeMessageConverter.convert(parsedCommandLine, properties, welcomeMessageConfiguration); } catch (CommandLineArgumentException e) { // Ignore, deal with this problem later }
publicvoidexecute(ExecutionListener executionListener) { // This must be added only during execute, because the actual constructor is called by various tests and this will not succeed if called then // 在actionFactory集合里添加一个BuildActionsFactory // actionCreators.add(new BuildActionsFactory(loggingServices)); createBuildActionFactoryActionCreator(loggingServices, actionCreators); //配置parser用于解析commandLine参数 configureCreators();
publicstatic <T> Action<T> toAction(@Nullable Runnable runnable) { //TODO SF this method accepts Closure instance as parameter but does not work correctly for it if (runnable == null) { return Actions.doNothing(); } else { returnnewRunnableActionAdapter<T>(runnable); } }
// Create a client that will match based on the daemon startup parameters. // 创建service ServiceRegistryclientSharedServices= createGlobalClientServices(true); ServiceRegistryclientServices= clientSharedServices.get(DaemonClientFactory.class).createBuildClientServices(loggingServices.get(OutputEventListener.class), daemonParameters, System.in); //获取DaemonClient DaemonClientclient= clientServices.get(DaemonClient.class); //创建runnable return runBuildAndCloseServices(startParameter, daemonParameters, client, clientSharedServices, clientServices);
publicvoidrun() { try { //DaemonClient.execute BuildActionResultresult= executer.execute( newExecuteBuildAction(startParameter), buildActionParameters, newDefaultBuildRequestContext(newDefaultBuildRequestMetaData(clientMetaData, startTime, sharedServices.get(ConsoleDetector.class).isConsoleInput()), newDefaultBuildCancellationToken(), newNoOpBuildEventConsumer()) ); //拿最后的执行结果 //异常处理 if (result.hasFailure()) { // Don't need to unpack the serialized failure. It will already have been reported and is not used by anything downstream of this action. thrownewReportedException(); } } finally { //关闭服务 if (stoppable != null) { stoppable.stop(); } } }
LOGGER.debug("Executing build {} in daemon client {pid={}}", buildId, processEnvironment.maybeGetPid()); // 尝试最多尝试连接99次 // Attempt to connect to an existing idle and compatible daemon intsaneNumberOfAttempts=100; //is it sane enough? for (inti=1; i < saneNumberOfAttempts; i++) { //连接server finalDaemonClientConnectionconnection= connector.connect(compatibilitySpec); // No existing, compatible daemon is available to try // 连接不上说明client和server不兼容,退出。 if (connection == null) { break; } // Compatible daemon was found, try it // 连接上了直接构建一个bean try { Buildbuild=newBuild(buildId, connection.getDaemon().getToken(), action, requestContext.getClient(), requestContext.getStartTime(), requestContext.isInteractive(), parameters); //执行构建 return executeBuild(build, connection, requestContext.getCancellationToken(), requestContext.getEventConsumer()); } catch (DaemonInitialConnectException e) { // this exception means that we want to try again. LOGGER.debug("{}, Trying a different daemon...", e.getMessage()); accumulatedExceptions.add(e); } finally { connection.stop(); } }
// No existing daemon was usable, so start a new one and try it once // 没有连接上,创建一个daemon finalDaemonClientConnectionconnection= connector.startDaemon(compatibilitySpec); try { // 构建一个build Buildbuild=newBuild(buildId, connection.getDaemon().getToken(), action, requestContext.getClient(), requestContext.getStartTime(), requestContext.isInteractive(), parameters); // 运行构建 return executeBuild(build, connection, requestContext.getCancellationToken(), requestContext.getEventConsumer()); } catch (DaemonInitialConnectException e) { // This means we could not connect to the daemon we just started. fail and don't try again thrownewNoUsableDaemonFoundException("A new daemon was started but could not be connected to: " + "pid=" + connection.getDaemon() + ", address= " + connection.getDaemon().getAddress() + ". " + Documentation.userManual("troubleshooting", "network_connection").consultDocumentationMessage(), accumulatedExceptions); } finally { connection.stop(); } }
protected BuildActionResult executeBuild(Build build, DaemonClientConnection connection, BuildCancellationToken cancellationToken, BuildEventConsumer buildEventConsumer)throws DaemonInitialConnectException { Object result; try { //日志 LOGGER.debug("Connected to daemon {}. Dispatching request {}.", connection.getDaemon(), build); //发送构建请求 connection.dispatch(build); //接受响应 result = connection.receive(); } catch (StaleDaemonAddressException e) { LOGGER.debug("Connected to a stale daemon address.", e); // We might fail hard here on the assumption that something weird happened to the daemon. // However, since we haven't yet started running the build, we can recover by just trying again. thrownewDaemonInitialConnectException("Connected to a stale daemon address.", e); } // 首次响应异常响应异常异常 if (result == null) { // If the response from the daemon is unintelligible, mark the daemon as unavailable so other // clients won't try to communicate with it. We'll attempt to recovery by trying again. connector.markDaemonAsUnavailable(connection.getDaemon()); thrownewDaemonInitialConnectException("The first result from the daemon was empty. The daemon process may have died or a non-daemon process is reusing the same port."); }
LOGGER.debug("Received result {} from daemon {} (build should be starting).", result, connection.getDaemon());