概述
想要弄明白sandbox如何实现字节码增强,我们首先得了解Instrumentation。
Instrumentation让我们有能力在jvm启动后进行Class的变型(java5以后)或者在jvm启动后,通过attach的方式加载jar包实现Class的变型(java6以后)。
sandbox-jvm便是根据此原理,实现一套框架,将不同的增强能力模块化管理,使用者只需要按照规范实现模块功能,即可被sandbox-jvm加载,实现字节码能力增强。
了解了上面的能力后,我们来看下sandbox-jvm的框架实现。
sandbox的代码主要分为几个过程:启动、模块加载、类增强实现
启动
上面我们提到,使用Instrumentation进行字节码增强有2种模式(attach模式和java-agent模式),sandbox-jvm的启动也是这2种,入口都在AgentLauncher中,分别对应着agentmain和premain,它们都调用了install方法,以agentmain为例:
public static void agentmain(String featureString, Instrumentation inst) {
LAUNCH_MODE = LAUNCH_MODE_ATTACH;
final Map<String, String> featureMap = toFeatureMap(featureString);
writeAttachResult(
getNamespace(featureMap),
getToken(featureMap),
install(featureMap, inst)
);
}
install函数的作用是在目标jvm上安装sandbox,创建独立的classloader,通过classloader加载JettyCoreServer.class,并且反射生成实例,建立httpserver监听请求
// CoreServer类定义
final Class<?> classOfProxyServer = sandboxClassLoader.loadClass(CLASS_OF_PROXY_CORE_SERVER);
// 获取CoreServer单例
final Object objectOfProxyServer = classOfProxyServer
.getMethod("getInstance")
.invoke(null);
// CoreServer.isBind()
final boolean isBind = (Boolean) classOfProxyServer.getMethod("isBind").invoke(objectOfProxyServer);
// 如果未绑定,则需要绑定一个地址
if (!isBind) {
try {
classOfProxyServer
.getMethod("bind", classOfConfigure, Instrumentation.class)
.invoke(objectOfProxyServer, objectOfCoreConfigure, inst);
} catch (Throwable t) {
classOfProxyServer.getMethod("destroy").invoke(objectOfProxyServer);
throw t;
}
}
启动jetty server,监听http请求,并且调用coreModuleManager.reset进行模块的加载,在下面一节介绍。
publi