Aaron Johnson Now with 50% less caffeine!

Posted
31 July 2005 @ 9pm

Tagged
ColdFusion, J2EE, Software Development

Java Class.forName(String className) and JDBC

A reader asked a question via a comment a couple months ago that I didn’t really have an answer for (and had always kind of wondered the same thing). In the original post (which showed how to use JDBC with ColdFusion), I used the following snippet of code:

Class.forName("jdbc.DriverXYZ");
Connection con = DriverManager.getConnection(url,
  "myLogin", "myPassword");

and the reader wanted to know what the Class.forName(..) method did. The most common answer you’ll hear is that it loads the database driver, which, while technically true, is shallow. Where does it get loaded? How does it happen? And why?

To answer the question I started with the JavaDoc for the Class.forName() method. According to the documentation, the method:

… attempts to locate, load, and link the class or interface

I wasn’t perfectly clear on what “locate, load, and link” meant, so I did a little digging through the Java Language Specification. According to chapter 12 of the JLS:

Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler, and constructing, from that binary form, a Class object to represent the class or interface.

Next, again according to the JLS, it must be transformed from it’s binary representation to something the Java virtual machine can use, this process is called linking. Finally, the class is initialized, which is the process that executes the static initializer and the initializers for static fields declared in the class.

So then back to the original problem, when Class.forName() is called with an argument like this:

Class.forName("org.gjt.mm.mysql.Driver");

the classloader attempts to load and link the Driver class in the “org.gjt.mm.mysql” package and if successful, the static initializer is run. The MySQL Driver (download the source code) static initializer looks like this:

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

So it calls a static method in the java.sql.DriverManager class which apparently registers a copy of itself when it loads.

So now I understand the where and the how, what about why? To understand the why you have to look at the next line in the initial code example:

Connection con = DriverManager.getConnection(url,
  "myLogin", "myPassword");

The DriverManager class (view DriverManager source here) returns a database connection given a JDBC URL string, a username and a password. In order to create that connection, the DriverManager class has to know which database driver you want to use. It does that by iterating over the array (internally a Vector) of drivers that have registered with it (ie: the registerDriver(Driver driver) method illustrated above) and calls the acceptsURL(url)) method on each driver in the array, effectively asking the driver to tell it whether or not it can handle the JDBC URL.

So there you have it. Class.forName explained.


34 Comments

Posted by
meh
2 August 2005 @ 1am

“Class.forName explained.” More like: Hidden-magic antipattern exposed! Or: Thank god for open-source where you can see what’s actually happening under-the-covers.


Posted by
alma
2 August 2005 @ 10am

>Thank god for open-source where you can see what’s actually happening under-the-covers.

A good specification should do it ;-)


Posted by
Gopi
27 December 2005 @ 5am

Good one !!


Posted by
Murthy
8 March 2006 @ 10pm

why can’t the following code do the job of “locate, load, and link”?

org.gjt.mm.mysql.Driver driver = new org.gjt.mm.mysql.Driver();

This would locate , load and link by executing the static block

Thanks,


Posted by
Anooj
3 April 2006 @ 5am

Can you please mention how the entry is being made in the DriverManager only when a driver is loaded using Class.forName() instead of a class like java.util.Vector ?What will happen if a class like vector is loaded using Class.forName() ?


Posted by
Kiran
11 April 2006 @ 4am

Good one Thank you


Posted by
maitri
17 October 2006 @ 9pm

simple and good


Posted by
Kirtish Parekh
14 November 2006 @ 2pm

Never found such explained answer on the forums. I think its our duty as a java developer to work on the common problems like this.

Thanks for the details.


Posted by
Chaitanya
17 December 2006 @ 6am

Great Aaron…..good explanation…..you are really great..!!


Posted by
Janeve George
18 December 2006 @ 2am

This are some hidden facts that most of the Java Masters might be unaware of. Thanks for sharing this information.


Posted by
vivek
16 March 2007 @ 8pm

It is really very good
thank you.


Posted by
zajjar
6 April 2007 @ 8am

Thank you very much for this explanation! Now it’s clear for me :)


Posted by
Seb
10 April 2007 @ 7am

Very good explanation… I had encountered that piece of code a lot of times but never understood what was going on under the covers.
A search on google returned your website and that was an interesting read!


Posted by
vedang
17 April 2007 @ 7am

nice… thanks for clearing the concepts…


Posted by
Moe
17 April 2007 @ 10am

Crystal! Good Job!


Posted by
snehal
3 June 2007 @ 10pm

Please tell me if we write to class.forName() statements simultaneously trying to load diferent drivers.ir first i load oracle driver and then jdbc which one will it load


Posted by
amirthan
20 November 2007 @ 1am

Neatly explained.Thanks


Posted by
poonam
21 December 2007 @ 4am

we dont have DriverManger class in j2me then how to etablish connection


Posted by
M.Shylaja
8 January 2008 @ 10pm

Thanks for ur Information. Cleared my doubt.


Posted by
Sree Ram
27 January 2008 @ 11pm

Thanks a real lot. People often do this stufff without understanding why and the explanation was crystal clear.


Posted by
Mete Takil
12 February 2008 @ 12am

Thanks a lot. Now I know why Class.forName(aString) is used.


Posted by
raghu
22 February 2008 @ 12am

excellent work…..thanks to the author


Posted by
encoded
25 March 2008 @ 7am

Nice job! i was googling and googling and found this, after reading through the spec and going through the class Class, makes perfect sense, thanks for making me lazy, hehe!


Posted by
Vasan
9 April 2008 @ 5pm

Well written and to the point! Now I understand!
On the why part - why does the standard way of opening a database be so complex? i.e. Loading the driver in step 1, and passing a URL in the step 2 which (hopefully) identifies the driver in step 1. Why not simply call the DriverManager with both the driver class, and the URL in one call? (The driver manager can do step 1 and 2 internally?).


Posted by
cvasilak
17 July 2008 @ 11am

Thanks for explaining the magic! :)


Posted by
dONI jAMES
18 July 2008 @ 1am

Thanks, You r coool


Posted by
hrishikesh
31 August 2008 @ 6am

such a outstanding approach. honestly , it is the best on the web.


Posted by
Rajesh
15 September 2008 @ 10pm

Hatsoff 2 the author.your explanation is a lesson for all of us not only belonging to this subject, But we can follow your way while posting further explanation on the web.


Posted by
Ram Dixit
15 November 2008 @ 2am

Great Explaination of Class.forName(),
Before this page I had gone through lot of websites but didn’t get the explaination as in this page.

Thanks a lot Mr. Aaron Johnson.


Posted by
swapnil
2 December 2008 @ 10pm

Nice Article ………..


Posted by
Jujahar
12 April 2009 @ 11pm

Just Great…. Thanks..


Posted by
Lasith
6 May 2009 @ 2am

Thanx a lot Aron.


Posted by
Girish Limaye
26 May 2009 @ 10am

Understood how internally database connection works.
Really cooool!!
Thank a lot.


Posted by
Abhinav
8 September 2009 @ 12pm

Its really nice……………..thanks.


Leave a Comment

Links: 7-29-2005 eBay Java / C# SOAP Examples