我试图在运行时用新版本重新定义代码中的现有类(称为模块)。新版本以已编译的类文件的形式保存在某些目录中。我可以用ByteBuddy做到这一点吗?
我尝试使用ByteArrayClassLoader从类文件中定义一个类。定义的类似乎具有更新的方法。我已经通过检查定义的类的方法并调用它们(即process
方法,该方法返回一些String)来进行检查。但是,当我尝试使用ByteBuddy.redefine(...)时,出现错误“无法为some.package.Module找到类文件”,我尝试传入用于查找新版本的类文件的ClassFileLocator但我仍然收到此错误。
public void redefine() throws Exception {
String path = System.getProperty("user.dir")+"/someDir";
Map<String, byte[]> map = new HashMap<>();
ClassFileLocator cfl = new ForFolder(new File(path));
byte[] clazzBytes = cfl.locate("Module").resolve();
map.put(clazz.getName(), clazzBytes);
ByteArrayClassLoader bac = new ByteArrayClassLoader(ClassLoadingStrategy.BOOTSTRAP_LOADER, false, map);
Class<?> replacementClass = bac.defineClass(clazz.getName(), clazzBytes);
for (Method m : replacementClass.getMethods()) {
if (m.getName().equals("process")) {
System.out.println((String) m.invoke(replacementClass.newInstance(), "invoked from new instance"));
}
}
AgentBuilder agentBuilder = new AgentBuilder.Default()
.with(new Listener.Filtering(
new StringMatcher("bytebuddy_instrumentation.Module", Mode.CONTAINS),
Listener.StreamWriting.toSystemOut()
))
.with(RedefinitionStrategy.REDEFINITION)
.with(Default.REDEFINE)
.disableClassFormatChanges()
.type(ElementMatchers.is(clazz))
.transform((builder, typeDescription, classLoader, module) ->
new ByteBuddy()
.redefine(replacementClass, cfl)
.name(clazz.getName()));
this.resetter = agentBuilder.installOnByteBuddyAgent();
}
由于java.lang.IllegalStateException: Could not locate class file for some.package.Module
,
答案 0 :(得分:0)
如果您只是想用另一个字节码表示形式替换另一个类,为什么要使用字节伙伴?
您可以使用Instrumentation
用redefineClass
API替换类,在其中您可以直接传递替换内容。
该错误可能是由于您使用REDEFINE
策略所致,其中Byte Buddy需要定位所有类的类文件。使用RETRANSFORM
可能会更好。但是,没有堆栈跟踪就无法确定。