How does Class.forName() work?

JavaJdbc

Java Problem Overview


I just learned about java.sql package. It uses Class.forName() to dynamically load the driver which extends DriverManager. Then we get connection using DriverManager.getConnection() method.

So how does the entire thing work?
How does DriverManager class know how to get the connection without using class name of the actual driver.

Also can we use Class.forName() for custom applications... if this is explained with an example I will be very happy.

Java Solutions


Solution 1 - Java

Class.forName simply loads a class, including running its static initializers, like this:

class Foo {
    static {
        System.out.println("Foo initializing");
    }
}

public class Test {
    public static void main(String [] args) throws Exception {
        Class.forName("Foo");
    }
}

All the rest of the procedure you're talking about is JDBC-specific. The driver - which implements Driver, it doesn't extend DriverManager - simply registers an appropriate instance using DriverManager.registerDriver. Then when DriverManager needs to find a driver for a particular connection string, it calls connect on each registered driver in turn until one succeeds and returns a non-null connection.

Note that this way of registering drivers is reasonably old-fashioned - look at the docs for DriverManager for more modern ways of getting at a data source.

Solution 2 - Java

When we create an instace of a class using new operator, it does two things

  1. Load the class in to memory, if it is not loaded - which means creating in-memory representation of the class from the .class file so that an instance can be created out of it. This includes initializing static variables (resolving of that class)
  2. create an instance of that class and store the reference to the variable.

Class.forName does only the first thing. It loads the class in to memory and return that reference as an instance of Class. If we want to create an instance then, we can call newInstance method of that class. which will invoke the default constructor (no argument constructor). Note that if the default constructor is not accessible, then newInstance method will throw an IllegalAccessException. and if the class is an abstract class or interface or it does not have a default constructor, then it will throw an InstantiationException. If any exception araises during resolving of that class, it will throw an ExceptionInInitializerError.

If the default constructor is not defined, then we have to invoke the defiend constructor using reflection API.

But the main advantage with Class.forName is, it can accept the class name as a String argument. So we can pass the class name dynamically. But if we create an instance of a class using new operator, the class name can't be changed dynamically.

Class.forName() inturn will call loadClass method of the caller ClassLoader (ClassLoder of the class from where Class.forName is invoked).

By default, the Class.forName() resolve that class. which means, initialize all static variables inside that class. same can be changed using the overloaded method of Class.forName(String name,boolean initialize,ClassLoader loader)

The main reason for loading jdbc driver using Class.forName() is, the driver can change dynamically. in the static block all Drivers will create an instance of itself and register that class with DriverManager using DriverManager.registerDriver() method. Since the Class.forName(String className) by default resolve the class, it will initialize the static initializer. So when we call Class.forName("com.sun.jdbc.odbc.JdbcOdbcDriver"), the Driver class will be loaded, instanciated and registers with DriverManager

So if you are using new Operator you have to do the following things.
Code:

Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver();
DriverManager.registerDriver(drv);

Solution 3 - Java

Class.forName(..) loads and initializes the target class. This in turn means that the static initializer blocks are invoked (code defined in static { .. }.

If you look at, for example, MySQL's driver, in that static block the driver is registering itself: DriverManager.registerDriver(new Driver());

You can omit the Class.forName(..) and register the driver yourself if you can "afford" the compile-time dependency on MySQL's driver.

That said, it will rarely be relevant to use Class.forName(..) to initialize classes from your application, because compile-time dependency is not an issue there.

Also note that Class.forName(..) is no longer required for JDBC since version 4. By using the http://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider">service provider mechanism you can instruct the driver manager what to load by a system property.

Solution 4 - Java

The reason why Class.forName() is frequently mentioned in SQL examples, is because there was no magic to tell the JDBC DriverManager how to map the JDBC URL provided to a real driver.

E.g. "mysql" should map to a given MySQL class, "thin" maps to the Oracle class, "as400" maps to the DB2/400 class.

By explicitly loading the class, this allowed the code within the class registering itself with the DriverManager to be run.

These days the magic hooks are present allowing the JVM to autodiscover the drivers (if new enough) so the call is superfluous, but out of habit many still use it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSonOfTheEARThView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaShubham VermaView Answer on Stackoverflow
Solution 3 - JavaBozhoView Answer on Stackoverflow
Solution 4 - JavaThorbjørn Ravn AndersenView Answer on Stackoverflow