2

I am reading source code about the java.sql.DriverManager,and found something confusing.Here is the code:

static {
    loadInitialDrivers();
    println("JDBC DriverManager initialized");
}
......
public static void println(String message) {
    synchronized (logSync) {
        if (logWriter != null) {
            logWriter.println(message);

            // automatic flushing is never enabled, so we must do it ourselves
            logWriter.flush();
        }
    }
}

The logWriter have not been set when class initialize,but was called by its static block.So I can't see any log info about this. How can I set field value before class initialization?

Jack Zhou
  • 21
  • 2

2 Answers2

0

The only way is to set the logWriter in a Driver implementation.

public class MyDriver implements Driver {

  static {
    // DriverManager will use ServiceLoader to load this class
    DriverManager.setLogWriter(new PrintWriter(System.out));
  }

  ... all methods in Driver
}

Then you will get the log

DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized

EDIT

For @moilejter's question, here give a simple sample of how two classes call each other even they are both not ready.

public class JustTest {
  public static void main(String[] args) throws java.lang.Exception {
    A.i = 2;
  }
}

class A {
  static int i = 1;
  static {
    System.out.println("a block start");
    B.print();
  }

  public static void print() {
    System.out.println("a print: " + B.i);
  }
}

class B {
  static int i = 1;
  static {
    System.out.println("b block start");
    A.print();
  }

  public static void print() {
    System.out.println("b print: " + A.i);
  }
}
Dean Xu
  • 4,438
  • 1
  • 17
  • 44
  • Hmm - I would not have expected this to work, since I thought the reference to DriverManager in the call to setLogWriter() would force Java to load that class before it could call setLogWriter(), and static initializer blocks would run when the class was loaded - so again, before you could call setLogWriter... – moilejter Jul 26 '18 at 08:02
  • @moilejter No, you are wrong. Class loading is different with Class initlization. When `DriverManager`'s static block running, that means `DriverManager` has been loaded since not everything ready. Other class can access all things that has been initlized. That is why the static block is defined under `logWriter`'s definition. After all, is easy to do a test yourself. – Dean Xu Jul 26 '18 at 08:06
  • @moilejter I have updated my answer to give you a simple sample. Play it! – Dean Xu Jul 26 '18 at 08:11
  • Sorry , could you give a full solution? I still don't know how to do.I just write a new class and make it implement java.sql.Driver,and then what should I do?@Dean Xu – Jack Zhou Jul 26 '18 at 08:22
  • @JackZhou I think you should learn `java spi` first. Then provide the `MyDriver` by SPI way. I will provide a minmize code in gist. – Dean Xu Jul 26 '18 at 08:25
  • @Dean Xu Thank you. – Jack Zhou Jul 26 '18 at 08:30
  • @JackZhou See [this gist](https://gist.github.com/XDean/05bb12fae9f6e70266017ef7112488c1). Follow my comment under this gist. – Dean Xu Jul 26 '18 at 08:37
-1

You can use this code if u use Console:

DriverManager.setLogWriter(new PrintWriter(System.out));  
anothernode
  • 5,100
  • 13
  • 43
  • 62
kira
  • 15
  • 1