在创建许多ByteBuddy类时,我需要获取任何类型的锁吗?

问题描述

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

我注意到,在单元测试中连续运行几次会产生不同的结果。有时会创建类并很好地加载它们。有时我会在随后使用生成的字节码时收到错误消息(通常在我使用withArgumentArrayElements的常规区域中,如果有关系的话; ArrayIndexOutOfBoundsErrors之类;同样,这一切都可行罚款(使用相同的输入)。

这感觉就像是在竞争,但正如我所说,我没有产生任何线程。由于 I 不使用线程,因此只能使用ByteBuddy(或JDK)。我不确定那会在哪里。使用DynamicTypeBuilder.make()getLoaded()创建和加载类时,应该使用ByteBuddy同步机制吗?也许某个类解析在make()时在后台线程上发生(或没有发生!),而我无意中以某种方式阻止了它的完成?也许如果我要立即使用这些类(我是),我需要提供其他TypeResolutionStrategy吗?应当清楚,我感到困惑,并且无法弄清楚为什么具有相同输入的单线程程序应该生成生成的类,它们的行为在每次运行时都不同。

我加载这些类的模式是:

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

除了或代替这些,我还应该执行某些特定于ByteBuddy的步骤吗?

解决方法

Ph!我想我可以将其归结为代码中的错误(谢谢)。简而言之,看起来并发问题是(很可能是)类名意外共享和HashMap迭代顺序的问题:创建并随后加载一个特定的子类时,将简单地加载另一个(不创建)反之亦然。最终效果是看起来像种族条件的效果。

,

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

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