繁体   English   中英

什么情况下toSet可以抛出java.lang.IllegalArgumentException?

[英]Under which circumstances can toSet throw an java.lang.IllegalArgumentException?

根据我们的 Crashlytics 日志,我们似乎不时遇到以下异常:

Fatal Exception: java.lang.IllegalArgumentException
Illegal initial capacity: -1
...
java.util.HashMap.<init> (HashMap.java:448)
java.util.LinkedHashMap.<init> (LinkedHashMap.java:371)
java.util.HashSet.<init> (HashSet.java:161)
java.util.LinkedHashSet.<init> (LinkedHashSet.java:146) 
kotlin.collections.CollectionsKt___CollectionsKt.toSet (CollectionsKt___CollectionsKt.java:1316) 

但我们不确定何时可能真正抛出此异常。 该语句的相关代码如下所示:

private val markersMap = mutableMapOf<Any, Marker>()
...
synchronized(markersMap) {
    val currentMarkers = markersMap.values.toSet() //it crashes here
    // performing some operation on the markers
}

现在我们怀疑多线程会导致这个问题,因为在多个地方修改了markersMap映射,但是由于映射已经默认初始化,我们不确定它如何最终达到小于空的状态。 我们还查看了toSet实现:

if (this is Collection) {
    return when (size) {
        0 -> emptySet()
        1 -> setOf(if (this is List) this[0] else iterator().next())
        else -> toCollection(LinkedHashSet<T>(mapCapacity(size)))
    }
}

基于此,我们假设mapCapacity(size)返回-1 ,但我们无法找到mapCapacity的实际实现来验证何时会发生这种情况。

有人知道这里什么时候返回-1 ,这又会导致构造函数失败吗?

Java 集合不是synchronized ,如果您需要从多个线程访问Map或任何集合,则需要处理同步。 LinkedHashMap标题中所述

注意这个实现不是同步的。如果多个线程同时访问一个链接的哈希映射,并且至少有一个线程在结构上修改了映射,它必须在外部同步。

我的猜测是您可能在没有同步的情况下在Map上执行结构修改( putremove混合),这可能会导致此问题。 例如

fun main(){
    val markersMap = mutableMapOf<Any, Any>()
    (1..1000).forEach { markersMap.put(it, "$it") }
    val t1 = Thread{
        (1..1000).forEach { markersMap.remove(it)
            if(markersMap.size < 0){
                print("SIZE IS ${markersMap.size}")
            }
        }
    }

    val t2 = Thread{
        (1..1000).forEach {
            markersMap.remove(it)
            if(markersMap.size < 0){
               print("SIZE IS ${markersMap.size}")
            }
        }
    }
    t1.start()
    t2.start()
}

在我的机器上,此代码打印SIZE IS -128SIZE IS -127以及许多其他负值,当我在其中一个 if 块中添加markersMap.values.toSet() ,发生了这种情况

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM