EmbedVersion
我们往 Presto 提交 SQL 查询以及 TaskExecutor 启动 TaskRunner 执行 Task 的时候都会使用到 EmbedVersion 类里面的 embedVersion 方法。embedVersion 方法其实就是初始化一个 Runnable 实例,比如启动 TaskRunner 的代码片段如下:
executor.execute(embedVersion.embedVersion(new TaskRunner()));
其中 TaskRunner 就是实现 Runnable 接口的。EmbedVersion 的 embedVersion 方法实现如下:
public Runnable embedVersion(Runnable runnable)
{
requireNonNull(runnable, "runnable is null");
try {
return (Runnable) runnableConstructor.invoke(runnable);
}
catch (Throwable throwable) {
throwIfUnchecked(throwable);
throw new RuntimeException(throwable);
}
}
其中 runnableConstructor 就是使用 ASM 进行代码生成的类,实现如下:
// 这里定义了一个类,类名大概为 Presto_null__testversion____20211011_105831_1,
// 它的父类是 Object,并实现了 Runnable 接口。
ClassDefinition classDefinition = new ClassDefinition(
a(PUBLIC, FINAL),
makeClassName(baseClassName(serverConfig)),
type(Object.class),
type(Runnable.class));
// 定义了一个名为 runnable 的局部变量,类型为 Runnable
FieldDefinition field = classDefinition.declareField(a(PRIVATE), "runnable", Runnable.class);
Parameter parameter = arg("runnable", type(Runnable.class));
// 定义了这个类的构造函数,参数为 runnable,参数类型为 Runnable
MethodDefinition constructor = classDefinition.declareConstructor(a(PUBLIC), parameter);
// 构造方法里面其实就是把参数 runnable 的值赋值给局部变量 runnable
constructor.getBody()
.comment("super(runnable);")
.append(cons