创建大量 ByteBuddy 类 时,我是否需要获取任何类型的锁?

When creating lots of ByteBuddy classes, do I need to acquire locks of any kind?

我正在创建几个 ByteBuddy classes(使用 DynamicTypeBuilder)并加载它们。这些 classes 的创建和它们的加载发生在单个线程(主线程;我自己不生成任何线程,也不向 ExecutorService 提交任何内容)以相对简单的顺序.

我注意到 运行在单元测试中连续多次使用它会产生不同的结果。有时 classes 可以正常创建和加载。其他时候,当随后使用生成的字节码时,我会从中得到错误(通常在我使用 withArgumentArrayElements 的一般区域,如果它很重要;ArrayIndexOutOfBoundsErrors 等等;其他时候这一切都有效很好(使用相同的输入))。

这感觉像是一种竞争条件,但正如我所说,我没有生成任何线程。由于 I 没有使用线程,因此只有 ByteBuddy(或 JDK)可以。我不确定那会在哪里。在使用 DynamicTypeBuilder.make()getLoaded() 创建和加载 classes 时,我应该使用 ByteBuddy 同步机制吗?也许某种 class 的解决方案正在后台线程或 make() time, and I am accidentally somehow preventing it from completing? Maybe if I'm going to use these classes immediately (I am) I need to supply a different TypeResolutionStrategy 上发生(或没有发生!)?我很困惑,正如应该清楚的那样,我无法弄清楚为什么具有相同输入的单线程程序会生成与 运行 运行.[=22 行为不同的生成的 classes =]

我加载这些 classes 的模式是:

  1. 尝试使用 Class#forName(name, true, Thread.currentThread().getContextClassLoader()).
  2. 加载(通常不存在的)class
  3. 如果(当)失败,创建 ByteBuddy 生成的 class 并使用通常的 ByteBuddy 配方加载它。
  4. 如果失败,那只是因为其他线程可能已经创建了 class。在这个单元测试中,没有其他线程。无论如何,如果这里发生故障,我会重复第 1 步,然后在加载失败时抛出异常。

除此之外,我还应该采取任何特定于 ByteBuddy 的步骤吗?

呸!我想我可以将此归因于我的代码中的错误(谢天谢地)。简而言之,看起来像并发问题的是(很可能)意外共享类名和 HashMap 迭代顺序的问题:当一个特定子类是 created-and-then-loaded 时,另一个将被简单地加载(而不是创建),反之亦然反之亦然。净效果看起来像竞争条件的效果。

字节好友已完全 thread-safe。但它确实会在您每次调用 load 时尝试创建一个 class,这是一个相当昂贵的操作。为避免这种情况,Byte Buddy 提供了 TypeCache 机制,可让您实现高效缓存。

请注意,像 cglib 这样的库提供自动缓存。 Byte Buddy 不会这样做,因为缓存使用所有输入作为键并静态引用它们,这很容易造成内存泄漏。此外,密钥效率很低,这就是字节好友选择这种方法的原因。