上一篇博客
18. Gradle编译其他应用代码流程(六) - 执行Task过程
一. 守护进程的作用
守护进程就是一个用来构建的其他进程。
从前几篇文章我们知道gradle编译的时候会加载各种所需要的Jar,加载这些Jar是需要时间的。
如果我们之前有守护进程编译过其他程序,而这个进程没有被kill掉,那么是可以重用这个守护进程的。
二. 选择守护进程编译
选择守护进程编译的策略是
-
如果守护进程存在,那么就使用守护进程编译。
-
否则,如果可以在当前进程编译,那么就在当前进程编译。
-
否则,启动新的守护进程来编译。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
BuildActionsFactory
implements
CommandLineAction {
public
Runnable createAction(CommandLineParser parser, ParsedCommandLine commandLine) {
...
if
(parameters.getDaemonParameters().isEnabled()) {
return
runBuildWithDaemon(parameters.getStartParameter(), parameters.getDaemonParameters(), loggingServices);
}
if
(canUseCurrentProcess(parameters.getDaemonParameters())) {
return
runBuildInProcess(parameters.getStartParameter(), parameters.getDaemonParameters(), loggingServices);
}
return
runBuildInSingleUseDaemon(parameters.getStartParameter(), parameters.getDaemonParameters(), loggingServices);
}
}
|
三. 启动守护进程的入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
public
class
DefaultDaemonStarter
implements
DaemonStarter {
....
public
DaemonStartupInfo startDaemon() {
String daemonUid = UUID.randomUUID().toString();
GradleInstallation gradleInstallation = CurrentGradleInstallation.get();
ModuleRegistry registry =
new
DefaultModuleRegistry(gradleInstallation);
ClassPath classpath;
List<File> searchClassPath;
if
(gradleInstallation ==
null
) {
// When not running from a Gradle distro, need runtime impl for launcher plus the search path to look for other modules
classpath =
new
DefaultClassPath();
for
(Module module : registry.getModule(
"gradle-launcher"
).getAllRequiredModules()) {
classpath = classpath.plus(module.getClasspath());
}
searchClassPath = registry.getAdditionalClassPath().getAsFiles();
}
else
{
// When running from a Gradle distro, only need launcher jar. The daemon can find everything from there.
classpath = registry.getModule(
"gradle-launcher"
).getImplementationClasspath();
searchClassPath = Collections.emptyList();
}
if
(classpath.isEmpty()) {
throw
new
IllegalStateException(
"Unable to construct a bootstrap classpath when starting the daemon"
);
}
versionValidator.validate(daemonParameters);
List<String> daemonArgs =
new
ArrayList<String>();
daemonArgs.add(daemonParameters.getEffectiveJvm().getJavaExecutable().getAbsolutePath());
List<String> daemonOpts = daemonParameters.getEffectiveJvmArgs();
daemonArgs.addAll(daemonOpts);
daemonArgs.add(
"-cp"
);
daemonArgs.add(CollectionUtils.join(File.pathSeparator, classpath.getAsFiles()));
if
(Boolean.getBoolean(
"org.gradle.daemon.debug"
)) {
daemonArgs.add(
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
);
}
daemonArgs.add(GradleDaemon.
class
.getName());
// Version isn't used, except by a human looking at the output of jps.
daemonArgs.add(GradleVersion.current().getVersion());
// Serialize configuration to daemon via the process' stdin
ByteArrayOutputStream serializedConfig =
new
ByteArrayOutputStream();
FlushableEncoder encoder =
new
KryoBackedEncoder(
new
EncodedStream.EncodedOutput(serializedConfig));
try
{
encoder.writeString(daemonParameters.getGradleUserHomeDir().getAbsolutePath());
encoder.writeString(daemonDir.getBaseDir().getAbsolutePath());
encoder.writeSmallInt(daemonParameters.getIdleTimeout());
encoder.writeSmallInt(daemonParameters.getPeriodicCheckInterval());
encoder.writeString(daemonUid);
encoder.writeSmallInt(daemonOpts.size());
for
(String daemonOpt : daemonOpts) {
encoder.writeString(daemonOpt);
}
encoder.writeSmallInt(searchClassPath.size());
for
(File file : searchClassPath) {
encoder.writeString(file.getAbsolutePath());
}
encoder.flush();
}
catch
(IOException e) {
throw
new
UncheckedIOException(e);
}
ByteArrayInputStream stdInput =
new
ByteArrayInputStream(serializedConfig.toByteArray());
return
startProcess(daemonArgs, daemonDir.getVersionedDir(), stdInput);
}
|
四. 守护进程执行入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
public
class
GradleDaemon {
public
static
void
main(String[] args) {
new
ProcessBootstrap().run(
"org.gradle.launcher.daemon.bootstrap.DaemonMain"
, args);
}
}
public
class
DaemonMain
extends
EntryPoint {
private
static
final
Logger LOGGER = Logging.getLogger(DaemonMain.
class
);
private
PrintStream originalOut;
private
PrintStream originalErr;
@Override
protected
void
doAction(String[] args, ExecutionListener listener) {
...
KryoBackedDecoder decoder =
new
KryoBackedDecoder(
new
EncodedStream.EncodedInput(System.in));
try
{
gradleHomeDir =
new
File(decoder.readString());
daemonBaseDir =
new
File(decoder.readString());
idleTimeoutMs = decoder.readSmallInt();
periodicCheckIntervalMs = decoder.readSmallInt();
daemonUid = decoder.readString();
int
argCount = decoder.readSmallInt();
startupOpts =
new
ArrayList<String>(argCount);
for
(
int
i =
0
; i < argCount; i++) {
startupOpts.add(decoder.readString());
}
int
additionalClassPathLength = decoder.readSmallInt();
additionalClassPath =
new
ArrayList<File>(additionalClassPathLength);
for
(
int
i =
0
; i < additionalClassPathLength; i++) {
additionalClassPath.add(
new
File(decoder.readString()));
}
}
catch
(EOFException e) {
System.out.println(
"DaemonMain doAction 4"
);
throw
new
UncheckedIOException(e);
}
NativeServices.initialize(gradleHomeDir);
DaemonServerConfiguration parameters =
new
DefaultDaemonServerConfiguration(daemonUid, daemonBaseDir, idleTimeoutMs, periodicCheckIntervalMs, startupOpts);
LoggingServiceRegistry loggingRegistry = LoggingServiceRegistry.newCommandLineProcessLogging();
LoggingManagerInternal loggingManager = loggingRegistry.newInstance(LoggingManagerInternal.
class
);
TrueTimeProvider timeProvider =
new
TrueTimeProvider();
DaemonServices daemonServices =
new
DaemonServices(parameters, loggingRegistry, loggingManager,
new
DefaultClassPath(additionalClassPath), timeProvider.getCurrentTime());
File daemonLog = daemonServices.getDaemonLogFile();
// Any logging prior to this point will not end up in the daemon log file.
initialiseLogging(loggingManager, daemonLog);
LOGGER.debug(
"Assuming the daemon was started with following jvm opts: {}"
, startupOpts);
Daemon daemon = daemonServices.get(Daemon.
class
);
daemon.start();
try
{
DaemonContext daemonContext = daemonServices.get(DaemonContext.
class
);
Long pid = daemonContext.getPid();
daemonStarted(pid, daemon.getUid(), daemon.getAddress(), daemonLog);
DaemonExpirationStrategy expirationStrategy = daemonServices.get(MasterExpirationStrategy.
class
);
daemon.stopOnExpiration(expirationStrategy, parameters.getPeriodicCheckIntervalMs());
}
finally
{
daemon.stop();
}
}
}
|
五. 守护进程的日志
守护进程的日志没有打印在控制台,而是打印在文件中,通过下面这行代码,进行了日志输出流转向。
1
2
|
// Any logging prior to this point will not end up in the daemon log file.
initialiseLogging(loggingManager, daemonLog);
|
日志保存的位置在 GRADLE_USER_HOME/daemon/版本号/daemon-进程号.out.log
如果没有配置GRADLE_USER_HOME,那就在根目录。windows的话在'c:\Users\rongwei.huang\.gradle\'
我自己的日志目录是:"d:\gradle_jar_cache\daemon\3.1-snapshot-1\daemon-10972.out.log"
最后附加自己编译的gradle3.1源代码和编译生成文件
本文转自rongwei84n 51CTO博客,原文链接:http://blog.51cto.com/483181/1931190,如需转载请自行联系原作者