The tools available to the Java developer exhibit several unifying concepts, which provide a framework to explore the next transition in Java-development tools.
The first development tool that many Java developers use is the "javac" compiler that is bundled with the Java Development Kit (JDK). This compiler translates Java source code into the bytecodes that the Java Virtual Machine (JVM) executes. The "javac" compiler is not sophisticated, but it works and that's enough to get started.
Another tool that may be used is "java" or "jre", the runtime environments for the JVM. The JVM interprets the bytecodes generated by the compile to portably execute the compiled program.
At this point the developer has encountered two concepts. First, "javac" uses the notion of static analysis and static compilation to translate the Java language source code into the bytecodes stored in the class files. Second, the tools "java" and "jre" both use the concept of dynamic interpretation to drive the execution of the program.
To improve these tools we can add the concept of dynamic compilation. The latest releases of the JDK include a feature known as a Just-In-Time (JIT) compiler. A JIT allows the software developer to deliver the program in a portable format and to defer optimization until the bytecodes are dynamically compiled into machine instructions on the host computer.
The class files in the application are not all compiled - that would increase the delay between downloading the application and starting its execution. A JVM enhanced with a JIT can leave most of the program as bytecodes that are interpreted by the JVM; but when the JIT wants to optimize the execution of a section of the bytecodes, that section is dynamically compiled into machine instructions to increase the execution speed with a small compilation penalty.
The JIT model of dynamic compilation is great for clients that are executing different Java programs. But for servers which are always running the same Java program, it's occasionally better to compile the entire program into optimized machine code for the target machine. This introduces the next concept, native code compilation. Native code compilers are like the "javac" tool we started with, except that they usually employ sophisticated semantic analysis, sometimes with the feedback of dynamically calculated information, to generate optimized machine instructions. Since these tools are designed to be occasionally executed, and the resulting program executed many times, these compilers can afford to do the extensive analysis necessary to optimize the Java program.
We have seen that as Java development and execution environments improve they usually incorporate increased usage of dynamic analysis techniques. This union of the compilation and execution models enables breakthrough tools which can take advantage of dynamic techniques in exciting new ways. Tools like profilers, feedback driven byte-code optimizers, memory leak detectors, or tools for source code coverage analysis are made possible when dynamic analysis is considered.
As an example of a novel application of dynamic analysis, consider the problems inherent when writing multithreaded Java programs. The Java runtime is inherently multithreaded, and Java supports explicitly multithreaded programming through the definition of a standard Thread class. But with this power comes a price. It's extremely difficult to prove that a multithreaded program is thread-safe, without making it inefficient by over-synchronizing all of the classes.
By using the concept of dynamic analysis, tools for multithreading defect analysis can be built to determine which objects are not correctly synchronized in the program and if the usage of the synchronized objects could cause the program to deadlock. Safe, correct, multithreaded programming in Java is practical and easy with tools based on dynamic analysis that provide a safety net to find overlooked problems.
The compilation, analysis and execution tools for Java have evolved to encompass both the static and the dynamic modes of operation. The Java developer gets the advantage and benefit of this symbiosis in Java's advanced development environments.
About the Author
Paul Petersen is a lead developer for KAI's Assure. You can reach him at [email protected]