Get a load of that name! (Very good article !)

Source: Internet
Author: User

Get a load of that name! Subtle differences in varous ways you can dynamically load a class

By Vladimir roubtsov


Printer-friendly version | mail this to a friend

 
 

 

March 14,200 3

What is the differenceClass. forname ()AndClassloader. loadclass ()?

Both methods try to dynamically locate and loadJava. Lang. ClassObject corresponding to a given class name. However, their behavior differs regarding whichJava. Lang. classloaderThey use for class loading and whether or not the resultingClassObject is initialized.

the most common form of class. forname () , the one that takes a single string parameter, always uses the caller's classloader. this is the classloader that loads the code executing the forname () method. by comparison, classloader. loadclass () is an instance method and requires you to select a particle classloader, which may or may not be the loader that loads that calling code. if picking a specific loader to load the class is important to your design, you shoshould use classloader. loadclass () or the three-parameter version of forname () added in Java 2 platform, Standard Edition (j2se ): class. forname (string, Boolean, classloader) .

Additionally,Class. forname ()'S common form initializes the loaded class. the visible effect of this is the execution of the class's static initializers as well as byte code corresponding to initialization expressions of all static fields (this process occurs recursively for all the class's superclasses ). this differs fromClassloader. loadclass ()Behavior, which delays initialization until the class is used for the first time.

You can take advantage of the above behavioral differences. for example, if you are about to load a class you know has a very costly static initializer, you may choose to go ahead and load it to ensure it is found in the classpath but delay its initialization until the first time you need to make use of a field or method from this particle class.

The three-parameter methodClass. forname (string, Boolean, classloader)Is the most general of them all. You can delay initialization by setting the second parameterFalseAnd pick a given classloader using the third parameter. I recommend always using this method for maximum flexibility.

Class initialization errors are tricky
Just because you successfully load a class does not mean there won't be any more problems. recollect that static initialization code can throw an exception, and it will get wrapped in an instanceJava. Lang. exceptionininitializererror, At which point, the class becomes unusable. Thus, if it is important to process all such errors at a known point in code, you should useClass. forname ()Version that performs initialization.

Furthermore, if you handleExceptionininitializererrorAnd take measures so that the initialization can be retried, it will likely not work. This Code demonstrates what happens:

Public class main
{
Public static void main (string [] ARGs) throws exception
{
For (INT repeat = 0; repeat <3; ++ repeat)
{
Try
{
// "Real" name for X is outer class name + $ + nested Class Name:
Class. forname ("Main $ X ");
}
Catch (throwable T)
{
System. Out. println ("load attempt #" + Repeat + ":");
T. printstacktrace (system. Out );
}
}
}

Private Static Class X
{
Static
{
If (++ s_count = 1)
Throw new runtimeexception ("failing static initializer ...");
}

} // End of nested class

Private Static int s_count;

} // End of class

This code attempts to load the nested classXThree times. Even thoughX'S static initializer fails only on the first attempt, all of them fail:

> JAVA main
Load attempt #0:
Java. Lang. exceptionininitializererror
At java. Lang. Class. forname0 (native method)
At java. Lang. Class. forname (class. Java: 140)
At Main. Main (main. Java: 17)
Caused by: Java. Lang. runtimeexception: failing static initializer...
At Main $ X. <clinit> (main. Java: 40)
... 3 more
Load attempt #1:
Java. Lang. noclassdeffounderror
At java. Lang. Class. forname0 (native method)
At java. Lang. Class. forname (class. Java: 140)
At Main. Main (main. Java: 17)
Load attempt #2:
Java. Lang. noclassdeffounderror
At java. Lang. Class. forname0 (native method)
At java. Lang. Class. forname (class. Java: 140)
At Main. Main (main. Java: 17)

It is slightly surprising that the errors on subsequent load attempts are instancesJava. Lang. noclassdeffounderror. What happens here is that the JVM has already noted the fact thatXHas been loaded (before the initialization is attempted), and the class cannot be unloaded until the current classloader is garbage collected. So, on subsequent calltoClass. forname (), The JVM does not attempt initialization again but, rather misleadingly, throws an instanceNoclassdeffounderror.

The proper way to reload such a class is to discard the original classloader instance and create a new one. of course, this can be done only if you had anticipated that and used the proper three-parameter formForname ().

the hidden class. forname ()
I am sure you have used Java's X. class syntax to obtain a class object for a class whose name is known at compile time. less well known is how this is implemented at the byte-code level. the details are different compression SS compilers, but all of them generate code that uses the One-parameter form of class. forname () behind the scenes. for example, javac from j2se 1.4.1 translates class CLS = x. class; into the following equivalent form:

...
// This is how "class CLS = x. Class" is transformed:
If (class $ main $ x = NULL)
{
Class $ main $ x = Class $ ("Main $ X ");
}
Class CLS = Class $ main $ X;

...

Static class $ (string S)
{
Try
{
Return class. forname (s );
}
Catch (classnotfoundexception E)
{
Throw new noclassdeffounderror (E. getmessage ());
}
}

Static class $ main $ X; // a synthetic field created by the compiler

Of course, everything mentioned aboutClass. forname ()'S short form always initializing the class in question appliesX. ClassSyntactic form as well. The details are different when such syntax is used to getClassObjects for primitive and array types, and I leave that as an exercise for curious readers.

Fun with Sun's javac
In the previous example, you saw that the result of loading the class was cached in a special package-Private Static Field artificially created by the compiler, and a synthetic helper method executedClass. forname (). The reason this is convoluted may be because the syntax used was unavailable in early Java versions, so the feature was added on top of the Java 1.0 byte-code instruction set.

Armed with this insight, you can have a bit of fun at the compiler's expense. Compile this tongue-in-cheek code snippet using javac from j2se 1.3.1:

Public class main
{
Public static void main (string [] ARGs) throws exception
{
System. Out. println ("string class:" + String. Class );
Class $ Java $ Lang $ string = int. Class;
System. Out. println ("string class:" + String. Class );
}

Static class $ Java $ Lang $ string;

} // End of class

If you run it, you will get the following, which is ridiculous at best:

> JAVA main
String class: Class java. Lang. String
String class: int

At least the compiler in j2se 1.4.1 will reject the code above. But you can still fool it by setting the field reflectively:

Public static void main (string [] ARGs) throws exception
{
System. Out. println ("string class:" + String. Class );
Main. Class. getdeclaredfield ("class $ Java $ Lang $ string"). Set (null, Int. Class );
System. Out. println ("string class:" + String. Class );
}

So, next time you code the familiarClass. forname ()Incantation, you shoshould know what it entails and what alternatives exist.

Printer-friendly version | mail this to a friend

About the author
Vladimir roubtsov has programmed in a variety of versions for more than 13 years, including Java since 1995. Currently, he develops enterprise software as a senior developer for trilogy in Austin, Texas.

    Resources
  • Jeff Friesen's "class and object initialization"In Java 101Lesson (Javaworld,November 2001) studies initialization in some detail:
    Http://www.javaworld.com/javaworld/jw-11-2001/jw-1102-java101.html
  • Want more? SeeJava Q &Index page for the full Q & A catalog:
    Http://www.javaworld.com/columns/jw-qna-index.shtml
  • For more than 100 insightful Java tips, visitJavaworld'SJava tipsIndex page:
    Http://www.javaworld.com/columns/jw-tips-index.shtml
  • BrowseCore JavaSectionJavaworld'S topical index:
    Http://www.javaworld.com/channel_content/jw-core-index.shtml
  • Get more of your questions answered in ourJava beginnerDiscussion:
    Http://forums.devworld.com/webx? 50 @. ee6b804
  • Sign upJavaworld'S free weekly email newsletters:
    Http://www.javaworld.com/subscribe
  • You'll find a wealth of IT-related articles from our sister publications at idg.net

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.