使用jdk10在Scala中进行不确定的数组复制

时间:2018-09-18 11:17:42

标签: scala compiler-optimization

我使用jdk10对我的库进行了测试,它们在50%的情况下随机失败。我提取了非常小的代码片段来重现该错误,并在计数失败的循环中运行它。对于100万次试用,失败次数通常约为100k-700k。

直到现在我发现的内容:

  1. 代码在jdk8中工作,而在jdk9和jdk10中失败
  2. 当您通过addressToBytes方法更改第二行和第三行的顺序时,它会起作用
  3. 当内联SomeOutputStream的方法时有效
  4. 当您禁用Java优化的最后一级时:-XX:TieredStopAtLevel = 3,它将起作用
  5. 当您在调试模式下运行此代码时,它通常可以工作。

我使用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")
  }
}

0 个答案:

没有答案