Archives
 
 
 
  Special
 
 
 
  About Us
 
 
 

Newsletter
Free E-mail Newsletter from BYTE.com

 
    
           
Visit the home page Browse the four-year online archive Download platform-neutral CPU/FPU benchmarks Find information for advertisers, authors, vendors, subscribers Request free information on products written about or advertised in BYTE Submit a press release, or scan recent announcements Talk with BYTE's staff and readers about products and technologies

ArticlesBetter Java Programming


September 1996 / Core Technologies / Better Java Programming

Knowing how Java's dynamic linking works can help you improve a program's performance.

Peter Wayner

There's a certain irony in that Sun's Java started life as an embedded programming language, yet it now makes reusable and transportable code a reality on the Internet. Java applets are relatively small but powerful units of code that can travel across the network and link themselves to class libraries that reside on the host computer. However, this flexible linking mechanism exacts a price: It allows easy code migration at the expense of performance. Optimizing compilers can boost the speed of Java programs, but you can help with judicious program design.

The key to understanding the performance trade-off incurred by this dynamic linking mechanism is to study Java's method invocations (object-oriented procedure calls) in depth. Java has highly structured method invocations. If a programmer invokes a foo() method, the interpreter must determine the correct version of the foo() method to use. That's because foo() could be defined by the applet itself, or it might inherit foo() from the host computer's libraries or from another object downloaded off the Net.

This situation differs from languages like C++, where a compiler scans the source code and resolves the correct method out of several. Then it embeds a pointer to this method within the generated machine code. This static linking works well for self-contained programs that run locally on only one machine. However, moving a program to another system requires copying all of the program, not just a portion of it. Also, if a new class inherits properties from an existing class, then the sour ce code must be recompiled so that the linker can reevaluate all the method calls. Because Java's dynamic linking mechanism resolves the correct method at run time, it enables preexisting code modules to migrate to a new machine and link up quickly with the local code libraries.

When a Java program is "compiled," it is converted into bytecodes for interpretation on a hypothetical virtual machine (VM). Each computer runs its own VM implementation locally, and this is where the dynamic linking happens. Four different bytecodes, as described by the Java VM specification, handle executing a method. Each bytecode applies to a different method type. The most common bytecode is known by the label INVOKE_VIRTUAL , and it handles most method calls. The call is dispatched based on the run-time (or virtual) type of the object that owns the method.

Dynamic Links

How does Java establish the run-time links with programs that have just come from the Internet? Objects in these pro grams get loaded into a pool of constants located in memory. This pool, called a class constant pool , stores data constants, program bytecodes, class descriptions, and method descriptions. The text string of each method's name, combined with extra information, is encoded and stored in a method signature table in the program's constant pool.

When the Java VM executes a program and encounters an INVOKE_VIRTUAL bytecode, it pushes the method's parameters and a pointer to the object onto the stack. A 2-byte reference number follows the INVOKE_VIRTUAL bytecode, which the Java VM uses as an index into the calling object's constant pool to obtain the method's signature. The VM uses the pointer on the stack to locate the target object's method table. It searches this table until it finds a method block with the proper signature. This method block contains information as to the method's type, how its call is set up, and where its code is located in memory (as shown in the figure "Java's Hot Links" ). With the start address of the appropriate method in hand, the Java virtual machine begins executing it and retrieves the arguments off the stack.

The amount of indirection here is a product of compromise. The first indexed lookup into the constant pool is necessary in order to limit the size of the compiled code. Only 2 bytes are needed to specify the correct method, while searches based on a name string require both more storage as well as more cycles. The result is more compact program code, particularly if some methods are called frequently.

The second lookup is more complicated because the VM must locate the appropriate method for the chosen object. Unfortunately, the object-oriented nature of Java means the compiler can't predict a method's type when it runs. So, the VM uses the signature mechanism to find the correct method in the class to execute.

The Java VM does include a neat trick to optimize code at run time. If you call the function foo() repeatedly from inside the same method, only the first call goes through the elaborate lookup process. Subsequent calls become much faster because the VM substitutes INVOKE_VIRTUAL_QUICK bytecodes in place of the INVOKE_VIRTUAL bytecodes. The index bytes after this QUICK version are already decoded references to the method. The Java VM specification suggests that this optimization occur automatically on-the-fly, but different Java implementations might approach this differently.

Speed Tricks

It should be clear that the dynamic links established for methods in a Java program are much more involved than for a statically linked language like C++. The overhead for switching the processor state between functions is still one of the biggest problems for compiler writers to tackle, and the standard solution to reduce this overhead is method inlining . That is, a method's instructions are simply copied and pasted into the calling meth od so they replace the method call. All the overhead in making the method call -- the pushing and popping of the stack, and the table searches used by the dynamic linking mechanism -- disappear. The downside is that all the inlined code results in code expansion.

While method inlining is a good optimization tool for Java programs, you often can't use it in general circumstances. Imagine that a class has a method foo() that is called by another method, bar() . At compile time, there may be no other subclasses that replace foo() , so it would be perfectly fine to inline the instructions for foo() inside of bar() . But Java is flexible enough so that another subclass could come along later and override foo() . The Java compiler must be ready to deal with these situations, so no inlining can take place.

Java's designers realized this flexibility would have an impact on performance, so they provided a keyword that allows you to forgo this flexibility. I f you declare a method final , you indicate to the compiler that no other subclasses will try to define their own version of the method. When the compiler knows this, it can inline processes. Any attempt to override a final method generates a compile-time error.

If you write Java code, you should make liberal use of the final keyword. Many programmers use short methods because it makes their code more readable. Unfortunately, this can significantly increase the execution time because of a method's calling overhead. The final keyword eases the burden.

The code fragment in "Method Inlining" shows a sample class called Rectangle . In this case, the final keyword isn't used, so the Java compiler can't inline the code for FindArea() into FindPaintCost() . If it did, the result would look like the function FindPaintCostInline() . While the result is that the method can't be optimized, it means you can override the behavior of FindArea() in the future (to calculate the area of a cylindrical tank, for example). The trade-off, then, is either better performance or code flexibility. You must decide which is most important to the program's operation in that situation.

Although Java looks very similar to C++ on the surface, the language is intended to be used differently than conventional programming languages. What might work for a C++ program can impair performance in a Java program. A Java program with many small methods can hamper performance due to the method-calling overhead. Armed with this knowledge and the final keyword, you can improve the performance of your Java applets.


Method Inlining

// Example of standard method calls and method inlining

 class Rectangle{
 double length; // The length of the rectangle.
 double height; //Its height.
 double FindArea(){
 return length*height
 }
 double FindPaintCost(){
 int area
 area = FindArea()
 r
eturn area*4
 // Cost is 4 times the area.
 }
 final double FindPaintCostInline(){
 int area
 area = length*width
 return area*4
 // Cost is 4 times the area.
 }
}



Java's Hot Links

illustration_link (20 Kbytes)

Downloaded objects can link to other Java libraries dynamically and inherit or override their behavior.


BYTE consulting editor Peter Wayner's book Java and JavaScript Programming will be published by AP Professional. You can reach him at pcw@access.digex.net .

Up to the Core Technologies section contentsGo to previous article: SearchSend a comment on this articleSubscribe to BYTE or BYTE on CD-ROM  
Flexible C++
Matthew Wilson
My approach to software engineering is far more pragmatic than it is theoretical--and no language better exemplifies this than C++.

more...

BYTE Digest

BYTE Digest editors every month analyze and evaluate the best articles from Information Week, EE Times, Dr. Dobb's Journal, Network Computing, Sys Admin, and dozens of other CMP publications—bringing you critical news and information about wireless communication, computer security, software development, embedded systems, and more!

Find out more

BYTE.com Store

BYTE CD-ROM
NOW, on one CD-ROM, you can instantly access more than 8 years of BYTE.
 
The Best of BYTE Volume 1: Programming Languages
The Best of BYTE
Volume 1: Programming Languages
In this issue of Best of BYTE, we bring together some of the leading programming language designers and implementors...

Copyright © 2005 CMP Media LLC, Privacy Policy, Your California Privacy rights, Terms of Service
Site comments: webmaster@byte.com
SDMG Web Sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, New Architect, SD Expo, SD Magazine, Sys Admin, The Perl Journal, UnixReview.com, Windows Developer Network