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.
CodePudding user response:
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