A brief analysis of using JDBC to operate MySQL requires adding Class.forName("com.mysql.jdbc.Driver")

A brief analysis of using JDBC to operate MySQL requires adding Class.forName("com.mysql.jdbc.Driver")

introduction

If you are familiar with using JDBC to connect to the database, you must know that the code for connecting to the database must be based on Class.forName

("com.mysql.jdbc.Driver");
  public static Connection getConnection() throws ClassNotFoundException, SQLException {
    if (connection == null) {
      Class.forName("com.mysql.jdbc.Driver");
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
    }
    return connection;
  }

I have never thought about why such a statement is needed before. I just do it according to the documentation. In this article, I will try to explain the reason for doing so.

Class loading mechanism

Before that, let's talk about the class loading mechanism in Java.

In Java, if you want to use a class, you must require that the class has been loaded into the Jvm. The loading process is actually to obtain the binary byte stream that defines the class through the fully qualified name of the class, and then convert the static storage structure represented by the byte stream into the dynamic runtime data structure of the method. At the same time, a java.lang.Class object is instantiated in memory as the data access entry for this class in the method area (for our use).

The following situations may trigger class loading (quoted from <<In-depth understanding of Java virtual machine>>):

1. When encountering the four bytecode instructions new, getstatic, putstatic or invokestatic, if the class has not been initialized, you need to trigger its initialization first. The most common Java code scenarios that generate these four instructions are: when instantiating an object using the new keyword, when reading or setting a static field of a class (except for static fields that are modified by final and have the results placed in the constant pool at compile time), and when calling a static method of a class.

2. When using the methods of the java.lang.reflect package to reflectively call a class, if the class has not been initialized, you need to trigger its initialization first.

3. When initializing a class, if it is found that its parent class has not been initialized, you need to trigger the initialization of its parent class first.

4. When the virtual machine starts, the user needs to specify a main class to be executed (the class containing the main() method), and the virtual machine will initialize this main class first.

Class.forName

The official Java documentation explains Class.forName as dynamically loading a class at runtime, and the return value is the generated Class object.

Then it is obvious that using Class.forName("com.mysql.jdbc.Driver"); in jdbc just loads the com.mysql.jdbc.Driver class into the Jvm, and most people should know this reason.

But we need to know that Class.forName seems to just load the class, and we don't even do any operations on the returned Class object, so why can we use it directly later?

First, Class.forName calls the native method forName0(...);

@CallerSensitive
public static Class<?> forName(String className)
      throws ClassNotFoundException {
  Class<?> caller = Reflection.getCallerClass();
  return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

private static native Class<?> forName0(String name, boolean initialize,ClassLoader loader,Class<?> caller);

It should be noted that there is a key parameter in forName0, boolean initialize, which is used to indicate whether to perform initialization after loading the class. You can see that if it is true in the code, it means that the initialization operation will be performed.

The initialization process is actually the process of assigning values ​​to variables (not assigning initial values, and not calling the constructor). Contains the assignment of all class variables and the execution code of static code statement blocks, including the initialization of the parent class.

Look at the com.mysql.jdbc.Driver driver class:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
  public Driver() throws SQLException {
  }

  static {
    try {
      DriverManager.registerDriver(new Driver());
    } catch (SQLException var1) {
      throw new RuntimeException("Can't register driver!");
    }
  }
}

A static code block is defined in this class. A driver class instance is created in the static code block and registered with DriverManager. The content of the static code block will be executed during the initialization process, so a connection can be directly obtained through DriverManager.getConnection .

Other loading class methods

What we need to understand is that in Java, it is not only through Class.forName() that classes can be loaded explicitly. So why not use other loading methods instead of Class.forName()?

ClassLoader.getSystemClassLoader().loadClass()

A class can also be loaded into the Jvm through a class loader. The driver class can also be loaded through ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver");

But if we look deeper into the implementation of loadClass:

public Class<?> loadClass(String name) throws ClassNotFoundException {
  return loadClass(name, false);
}

protected Class<?> loadClass(String name, boolean resolve);

You can see that it calls an overloaded method, which also has a boolean variable boolean resolve, which defaults to false when called. This parameter is used to identify whether to link the loaded class. If not, there will be no initialization operation.

Therefore, if this class loading method is used, theoretically the driver class cannot be used.

new Keyword

You can also use the new keyword to perform loading operations. When using the new keyword, it will check whether the class has been loaded. If it has not been loaded, it will load it. So we can also write this in our class:

public static Connection getConnection() throws ClassNotFoundException, SQLException {
  if (connection == null) {
    new Driver(); //The static code block will be called automatically connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxx");
  }
  return connection;
}

But in fact, there is already an operation to instantiate the object and register it with DriverMananger in the static code block of the driver class. So there is no process of instantiating an object here at all. Just use Class.forName, which can be regarded as an optimization process.

You don't need to use Class.forName("com.mysql.jdbc.Driver")

During the test, I found that I could connect to the database even if I did not use Class.forName("com.mysql.jdbc.Driver") explicitly, which I found very strange.

After tracking the code in depth, we found that as long as we introduce the MySQL driver package, a class will be created by default according to the configuration file provided under the driver package when it is used.

So in fact, as long as the driver package is introduced, you can use jdbc to obtain the connection directly through DriverManage.

public static Connection getConnection() SQLException {
  return DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx");
}

Summarize

The above is my introduction to why you need to add Class.forName("com.mysql.jdbc.Driver") when using JDBC to operate MySQL. I hope it will be helpful to you. If you have any questions, please leave me a message and I will reply to you in time. I would also like to thank everyone for their support of the 123WORDPRESS.COM website!

You may also be interested in:
  • Detailed explanation and summary of the URL for database connection
  • About the setting of MySql link url parameters
  • How to use MySQL driverClassName and url

<<:  List rendering instructions for efficient development of Vue front-end

>>:  Detailed tutorial on installing Docker on Windows

Recommend

How to check and organize website files using Dreamweaver8

What is the purpose of creating your own website u...

The latest Linux installation process of tomcat8

Download https://tomcat.apache.org/download-80.cg...

Summary of common operation skills of MySQL database

This article summarizes common operating techniqu...

Linux installation MongoDB startup and common problem solving

MongoDB installation process and problem records ...

Calendar effect based on jQuery

This article example shares the specific code of ...

Vue components dynamic components detailed explanation

Table of contents Summarize Summarize When the ar...

Things to note when writing self-closing XHTML tags

The img tag in XHTML should be written like this:...

Detailed explanation of CocosCreator Huarongdao digital puzzle

Table of contents Preface text 1. Panel 2. Huaron...

Detailed explanation of MySQL index principles and optimization

Preface This article was written by a big shot fr...

How to make a tar file of wsl through Docker

I've been playing with the remote development...

Implementation code for installing vsftpd in Ubuntu 18.04

Install vsftpd $ sudo apt-get install vsftpd -y S...

React native realizes the monitoring gesture up and down pull effect

React native implements the monitoring gesture to...

Tutorial diagram of installing zabbix2.4 under centos6.5

The fixed IP address of the centos-DVD1 version s...