2

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

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

这感觉像是一种竞争条件,但正如我所说,我没有产生任何线程。因为没有使用线程,所以只能使用 ByteBuddy(或 JDK)。我不确定那会在哪里。DynamicTypeBuilder.make()在使用 and 创建和加载类时,我应该使用 ByteBuddy 同步机制getLoaded()吗?也许某种类解析正在发生(或没有发生!)在后台线程或某事上make(),我不小心以某种方式阻止它完成?也许如果我要立即使用这些类(我是)我需要提供不同的TypeResolutionStrategy?我很困惑,应该很清楚,并且无法弄清楚为什么具有相同输入的单线程程序会生成在运行之间表现不同的生成类。

我加载这些类的模式是:

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

除了这些之外,我还应该采取哪些特定于 ByteBuddy 的步骤?

4

2 回答 2

0

呸!我想我可以把它归结为我的代码中的一个错误(谢天谢地)。简而言之,看起来并发问题(很可能)是意外共享类名和HashMap迭代顺序的问题:当一个特定的子类被创建然后加载时,另一个只会被加载(而不是创建),反之亦然。净效应是看起来像比赛条件的效应。

于 2020-09-11T04:14:24.593 回答
0

Byte Buddy 是完全线程安全的。但它确实会在您每次调用load相当昂贵的操作时尝试创建一个类。为避免这种情况,Byte Buddy 提供了TypeCache允许您实现高效缓存的机制。

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

于 2020-09-11T22:22:01.413 回答