Home > Blockchain >  Matrix-vector multiplication prints java version in stdout
Matrix-vector multiplication prints java version in stdout

Time:11-24

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

https://github.com/luhenry/netlib/blob/master/blas/src/main/java/dev/ludovic/netlib/blas/InstanceBuilder.java

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

  • Related