1

我需要热交换各种类的方法实现(直到运行时的某个时候我才知道它的新实现,并且可能会再次改变)。

ByteBuddy可以很容易地做到这一点,但它(显然)除了拦截它之外对方法做不了太多,这就是它与 ASM 一起提供的原因。

基本用法是

    ByteBuddyAgent.install();
    byte[] bytes = transformFoo();

    ClassFileLocator classFileLocator = ClassFileLocator.Simple.of(Foo.class.getName(), bytes);
    new ByteBuddy()
            .redefine(Foo.class, classFileLocator)
            .make()
            .load(Foo.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());

在哪里

private static byte[] transformFoo() throws IOException {
    ClassReader classReader = new ClassReader(Foo.class.getResourceAsStream("Foo.class"));
    ClassWriter classWriter = new ClassWriter(classReader, 0);
    MyClassVisitor myClassVisitor = new MyClassVisitor(classWriter);
    classReader.accept(myClassVisitor, 0);

    return classWriter.toByteArray();
}

正在使用 ASM。

但是 ASM 很乏味,很难阅读和编写更复杂的代码。所以我更愿意使用 Jimple,因为它为 if-stmts 等提供了抽象。

因此,这个想法是从

Class<?> fooClass = Foo.class;

,以某种方式将其转换为

SootClass fooSootClass = ...

,在那里转换方法,并以某种方式将其编译回byte[]

byte[] ret = ...
return ret;

stByteBuddy可以重新加载类。

简而言之:

我想SootClass从 a创建一个可转换的Class<?>并将其编译为byte[]我可以传递的 a。

我怎么做?

更新

似乎暗示执行从SootClassto的转换很热byte[],但到目前为止,我还没有找到任何有助于从Classto转换的文档或示例SootClass。大多数示例似乎只在加载类之前对其进行一次检测。

4

1 回答 1

0

几年前我自己尝试过,但失败了。我会说这在理论上是可能的,但这绝非易事。

一个问题是,当您尝试动态检测类时,通常您希望在加载时使用 java.lang.instrument 执行此操作。这意味着您一次只能看到一个类,因为您实际上是在挂钩到类加载过程。然而,对于 Soot 所做的许多事情,它需要访问其他类。例如,它需要解析签名,有时还需要解析方法体。然后,这完全改变了加载的类集和加载它们的顺序。我记得这引起了很多问题。ASM 没有这样的解决方案。

于 2017-11-23T17:55:49.927 回答