我使用jdk10对我的库进行了测试,它们在50%的情况下随机失败。我提取了非常小的代码片段来重现该错误,并在计数失败的循环中运行它。对于100万次试用,失败次数通常约为100k-700k。
直到现在我发现的内容:
addressToBytes
方法更改第二行和第三行的顺序时,它会起作用SomeOutputStream
的方法时有效我使用scala 2.12.6和javac选项:-source 1.8和-target 1.8。 Windows和Linux上均会出现此问题。
基本问题是为什么addressToBytes
方法不能总是返回相同的结果?
有时而不是预期的数组:[4,10,10,10,10]地址的某些部分被替换为0。例如:[4,10,10,10,0]
以下是您可以用来重现该问题的代码:
import java.io.OutputStream
import java.net.InetSocketAddress
object RaceCondition {
class SomeOutputStream(val data: Array[Byte], var currentIndex: Int) extends OutputStream {
override def write(bytes: Array[Byte], off: Int, len: Int): Unit = {
System.arraycopy(bytes, off, data, currentIndex, len)
currentIndex += bytes.length
}
def write(b: Int): Unit = {
data.update(currentIndex, b.toByte)
currentIndex += 1
}
}
def addressToBytes(sAddress: InetSocketAddress): Array[Byte] = {
val result: Array[Byte] = new Array[Byte](sAddress.getAddress.getAddress.length + 1)
val writer = new SomeOutputStream(result, 0)
val addressBytes = sAddress.getAddress.getAddress
writer.write(addressBytes.length)
writer.write(addressBytes)
writer.data
}
def main(args: Array[String]): Unit = {
var i = 0
val expected = Array[Byte](4, 10, 10, 10, 10)
val address = new InetSocketAddress("10.10.10.10", 1234)
var count = 0
var lastOk = true
while (i < 1000000) {
i += 1
val data = addressToBytes(address)
if (!data.sameElements(expected)) {
count += 1
if(lastOk){
println(s"\n\nBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD $i\n\n")
}
lastOk = false
} else {
if(!lastOk){
println(s"\n\nGOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD $i\n\n")
}
lastOk = true
}
}
println(s"Failures: $count")
}
}