Reproduce and fix ByteString initialization issue (#29244)
* Reproduce ByteString initialization issue * scalafmt * make test reliably fail * core: fix initialization of `ByteString.empty` Refs #29263 Co-authored-by: Johannes Rudolph <johannes.rudolph@gmail.com>
This commit is contained in:
parent
193f4ad704
commit
7f22b9648c
2 changed files with 53 additions and 1 deletions
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Lightbend Inc. <https://www.lightbend.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package akka.util
|
||||||
|
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
import org.scalatest.matchers.should.Matchers
|
||||||
|
import org.scalatest.wordspec.AnyWordSpec
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
import scala.collection.mutable.ArrayBuilder
|
||||||
|
|
||||||
|
class ByteStringInitializationSpec extends AnyWordSpec with Matchers {
|
||||||
|
"ByteString intialization" should {
|
||||||
|
"not get confused by initializing CompactByteString before ByteString" in {
|
||||||
|
// a classloader that creates a new universe of classes for everything beneath akka
|
||||||
|
// that prevents that this test interacts with any tests
|
||||||
|
val cleanCl = new ClassLoader(null) {
|
||||||
|
val outerCl = ByteStringInitializationSpec.this.getClass.getClassLoader
|
||||||
|
val buffer = new Array[Byte](1000000)
|
||||||
|
override def loadClass(name: String): Class[_] =
|
||||||
|
if (!name.startsWith("akka")) outerCl.loadClass(name)
|
||||||
|
else {
|
||||||
|
val classFile = name.replace(".", "/") + ".class"
|
||||||
|
val is = outerCl.getResourceAsStream(classFile)
|
||||||
|
val res = slurp(is, new mutable.ArrayBuilder.ofByte)
|
||||||
|
defineClass(name, res, 0, res.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
def slurp(is: InputStream, res: ArrayBuilder[Byte]): Array[Byte] = {
|
||||||
|
val read = is.read(buffer)
|
||||||
|
if (read == 0) throw new IllegalStateException
|
||||||
|
else if (read > 0) slurp(is, res ++= buffer.take(read))
|
||||||
|
else res.result()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import scala.language.reflectiveCalls
|
||||||
|
type WithRun = { def run(): Unit }
|
||||||
|
cleanCl.loadClass("akka.util.ByteStringInitTest").newInstance().asInstanceOf[WithRun].run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ByteStringInitTest {
|
||||||
|
def run(): Unit = {
|
||||||
|
require(CompactByteString.empty ne null)
|
||||||
|
require(ByteString.empty ne null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -747,7 +747,7 @@ sealed abstract class ByteString
|
||||||
|
|
||||||
override protected def fromSpecific(coll: IterableOnce[Byte]): ByteString = ByteString(coll)
|
override protected def fromSpecific(coll: IterableOnce[Byte]): ByteString = ByteString(coll)
|
||||||
override protected def newSpecificBuilder: mutable.Builder[Byte, ByteString] = ByteString.newBuilder
|
override protected def newSpecificBuilder: mutable.Builder[Byte, ByteString] = ByteString.newBuilder
|
||||||
override val empty: ByteString = ByteString.empty
|
override def empty: ByteString = ByteString.empty
|
||||||
|
|
||||||
def apply(idx: Int): Byte
|
def apply(idx: Int): Byte
|
||||||
private[akka] def byteStringCompanion: ByteString.Companion
|
private[akka] def byteStringCompanion: ByteString.Companion
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue