Groovy AbstractConcurrentMap中的Bug?

Groovy AbstractConcurrentMap中的Bug?,groovy,Groovy,是Groovy中的核心类,用于存储运行时添加到Groovy类中的动态属性。我在Groovy 1.8.8中使用Grails 2.1.2,但我认为所有Groovy版本都存在这个问题(链接的源代码是针对Groovy 2.4.3版的) 问题发生在内部类段的方法中(第105行): 当当前计数大于贴图的阈值时,将发生。现在棘手的部分是,地图保存对对象的软引用并验证这些引用。因此,当GC丢弃软引用时,生成的段不会展开(正如方法中假定的那样) 在中,Segmen的内部计数器被更新count=newCount(

是Groovy中的核心类,用于存储运行时添加到Groovy类中的动态属性。我在Groovy 1.8.8中使用Grails 2.1.2,但我认为所有Groovy版本都存在这个问题(链接的源代码是针对Groovy 2.4.3版的)

问题发生在内部类段的方法中(第105行):

  • 当当前计数大于贴图的阈值时,将发生。现在棘手的部分是,地图保存对对象的软引用并验证这些引用。因此,当GC丢弃软引用时,生成的段不会展开(正如方法中假定的那样)

  • 在中,Segmen的内部计数器被更新
    count=newCount
    (这是“活动”未分类引用的数量,可以小于前面所述的计数)

  • 完成后,该方法继续,但问题在于,它忽略了内部计数的先前设置,并在每一行上设置了先前的计数+1值,并且

因此,以下步骤正在发生:

  • 映射状态:
    threshold=786432;计数=786432
  • 将新元素插入到映射中:
    count=786433;阈值=786432
  • 因为新计数将大于阈值,所以会发生
  • rehash()发现,大多数对象都是垃圾收集的,因此它不会增加段的大小,但无论如何,它会将所有对象从一个表复制到另一个表(System.arrayCopy())
  • rehash()将内部计数设置为较小的新值,因为许多对象是垃圾收集的(软引用),比如:
    count=486000
  • 继续,忽略计数=486000并将计数设置为
    count=786433
  • 插入另一个元素,但是在此状态下,计数仍然大于阈值,因此再次发生刷新
  • 从现在起,添加到map中的每个元素都将触发一个错误,这将对性能产生巨大影响
  • 在多线程环境中发生这种情况时,所有其他线程都在等待(停驻)lock(),直到rehash()和put()完成(然后下一个线程再次执行rehash()。您可以想象这对性能有什么影响

    我不明白这个bug怎么能在这么多版本中存活下来,而没有人注意到,尽管这个类被广泛使用。也许我错过了什么

    建议的解决方案:

    在重新刷新后更新c变量。 在第105行和第106行之间添加:

    c = count + 1
    

    Groovy JIRA上报告了该错误,现在已修复

    Fix Version/s:
    2.4.4, 2.5.0-beta-1
    

    您应该在上报告此问题,并将建议的修复作为一个diff/pull请求进行报告,可能还需要一些测试来显示问题。至少你会瞄准groovy方面的专家。因此,对于潜在的语言错误,这几乎不是一个同行评审页面。Thx作为回复,我提交了以下问题: