The following Code on Scala outputs return java 11 instance
.
I'm using openjdk-11 and sbt 1.8.0.
# Main.scala
import breeze.linalg.{DenseMatrix, DenseVector}
object Main extends App {
val X = DenseMatrix((1.0, 0.0), (1.0, 1.0), (1.0, 2.0), (1.0, 3.0))
val Y = DenseVector(0.0, 1.0)
X * Y
}
# build.sbt
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.13.10"
libraryDependencies ++= Seq(
"org.scalanlp" %% "breeze" % "2.1.0"
)
What is the reason for this output and how can I avoid this in my projects with Breeze?
Moreover this problem reproduces with other versions of jdk, this code always prints java version from which it was built.
The thing is that for multiplication of dense matrices Breeze uses https://github.com/luhenry/netlib with logger dev.ludovic.netlib.blas.InstanceBuilder
private static JavaBLAS initializeJava() {
String[] fullVersion = System.getProperty("java.version").split("[+.\\-]+", 2);
int major = Integer.parseInt(fullVersion[0]);
if (major >= 16) {
try {
System.out.println("trying to return java 16 instance");
return VectorBLAS.getInstance();
} catch (Throwable t) {
log.warning("Failed to load implementation from:" + VectorBLAS.class.getName());
}
}
if (major >= 11) {
System.out.println("return java 11 instance");
return Java11BLAS.getInstance();
} else {
System.out.println("return java 8 instance");
return Java8BLAS.getInstance();
}
}
All other logging can be switched off with setLevel
import java.util.logging.{Level, Logger}
val logger = Logger.getLogger("dev.ludovic.netlib.blas.InstanceBuilder")
logger.log(Level.SEVERE, "AAAA!!!") // prints
logger.setLevel(Level.OFF)
logger.log(Level.SEVERE, "BBBB!!!") // doesn't print
Is there a way to disable java.util.logging and enable it back later?
Why are the Level.FINE logging messages not showing?
But return java...
messages are printed not with log
/doLog
but directly with System.out.println
in the static initializing block of class InstanceBuilder
, so this is executed during initialization of the class InstanceBuilder
.
Static initializing block can be modified only with bytecode manipulation (Javassist, Byte Buddy)
Over riding the static block of a class in java
So the easiest is just to modify a print stream
System.setOut(new java.io.PrintStream(System.out) {
override def println(s: String): Unit =
if (Seq("trying to return java", "return java").forall(!s.startsWith(_)))
super.println(s)
})
https://scastie.scala-lang.org/DmytroMitin/gk52bU4iSEebHAZPZKhaDw/5