Java-Tools(pdf) - DOC SERVE

docserve.files.wordpress.com
  • No tags were found...

Java-Tools(pdf) - DOC SERVE

Chapter - 1Java Tools TerminologyCertificate: A digitally signed statement from the issuer saying that the public key of the subject hassome specific value.Certificate Chain: A series of certificates that one certificate signs the public key of the issuer of thenext certificate. Usually the top certificate (the first certificate) is self-signed, where issuer signed itsown public key.JAR (Java Archive): A platform-independent file format that aggregates many files into one. MultipleJava applets and their requisite components (.class files, images and sounds) can be bundled in a JARfile and subsequently downloaded to a browser in a single HTTP transaction, greatly improving thedownload speed. The JAR format also supports compression, which reduces the file size, furtherimproving the download time. In addition, the applet author can digitally sign individual entries in aJAR file to authenticate their origin. It is fully extensible."jar": A command line tool for managing JAR files. "jar" is distributed as part of the JDK packagefrom Sun."java": The Java launcher - A command line tool to launch Java applications. "java" is distributed aspart of the JDK package from Sun."javac": The Java compier - A command line tool to compile Java source files. "javac" is distributed aspart of the JDK package from Sun."javap": The Java Class File Disassembler - A command line tool that reads Java bytecode class filesand disassembles them."jdb": The Java Debugger - A command line tool to debug Java applications. "jdb" is distributed aspart of the JDK package from Sun."JDI (Java Debug Interface)": A high level Java API providing information useful for debuggers andsimilar systems needing access to the running state of a (usually remote) virtual machine."JPDA (Java Platform Debugger Architecture)": An infrastructure that allows user to build end-userdebugger applications. It includes the following three-layered APIs:• Java Debug Interface (JDI), a high-level Java programming language interface, includingsupport for remote debugging;• Java Debug Wire Protocol (JDWP), which defines the format of information and requeststransferred between the debugging process and the debugger front end;• The JVM(TM) Tools Interface, JVM TI. This is a low-level native interface that defines theservices a Java virtual machine provides for tools, including debugging. JVM TI is new in J2SE5.0 and replaces JVMDI and JVMPI, both of which are deprecated and will be removed in afuture release."JVM (Java Virtual Machine)": A software that simulates a central process unit (Virtual Machine) torun compiled Java code."keystore": A database used by JDK "keytool" command and KeyStore class to store your own privatekeys, and public key certificates you received from someone else. "keystore" supports the followingfeatures.


"keytool": A command line tool introduced in JDK 1.2 to manage keys and certificates using"keystore". "keytool" replaces the same functions offered by "javakey" in JDK 1.1. "keytool" offers anumber functions through the following major command options.native2ascii: Native-to-ASCII Encoding Converter - A command line tool that reads a text file storedin a non-ASCII encoding and converts it to an ASCII text file. All non-ASCII characters will beconverted into \udddd sequences, where dddd is the Unicode code value of the non-ASCII character.ZIP: A file format is a popular data compression and archival format. A ZIP file contains one or morefiles that have been compressed or stored.The format was originally designed by Phil Katz for PKZIP. However, many software utilities otherthan PKZIP itself are now available to create, modify or open ZIP files, notably WinZip,BOMArchiveHelper, PicoZip, Info-ZIP, WinRAR and 7-Zip. Microsoft has also included minimal ZIPsupport (under the name "compressed folders") in later versions of its Windows operating system.


Chapter - 2Installing J2SE 1.6.0 on WindowsThis chapter provides tutorial notes on installing Java SE (JDK) on your own Windows system to allowyou to run sample JDBC Java programs. Topics include downloading and installing Java SE 6;compiling and executing Java programs; installing Java documentation.Downloading and Installing J2SE 1.6.0 on WindowsTesting J2SE 1.6.0 InstallationDownloading and Installing J2SE 1.6.0 on WindowsTo learn JDBC, you have to a copy of JDK (Java Development Kit) installed on your machine. Thelatest version of JDK is JDK 6u2 (Java(TM) SE Development Kit 6 Update 2), which is also calledJava SE 6 (Java Standard Edition 6). Here is what I did to download and install JDK 6u2 on my localmachine.• Open the Java SE Download page with this URL: http://java.sun.com/javase/downloads/.• Click the download button next to "JDK 6u2". You will see a new page with a list of differentdownload files of JDK 6u2.• Locate the "Windows Platform - Java(TM) SE Development Kit 6 Update 2" section.• Click the hyper link of "Windows Offline Installation (build 06), Multi-language", which linksto jdk-6u2-windows-i586-p.exe with size of 65.57 MB.• Save jdk-6u2-windows-i586-p.exe to a temporary directory.• Double-click on jdk-6u2-windows-i586-p.exe to start the installation wizard.• The installation wizard will guide you to finish the installation.To test the installation, open a command window to try the java command. If you are getting thefollowing output, your installation was ok:C:\>\progra~1\java\jdk1.6.0_02\bin\java -versionjava version "1.6.0_02"Java(TM) SE Runtime Environment (build 1.6.0_02-b06)Java HotSpot(TM) Client VM (build 1.6.0_02-b06, mixed mode,sharing)Testing J2SE 1.6.0 InstallationWhen JDK is installed on your machine, it provides two commands for you to compile and run Javaprograms.• "javac class_name.java" - Compiles a Java program stored a file named with the program classname.• "java -cp . class_name" - Runs a compiled Java program. "-cp ." specifies the current directoryas the class path.Let's try these commands with a very simple Java program. Use NotePad to enter the following Java


program into a file called Hello.java:class Hello {public static void main(String[] a) {System.out.println("Hello world!");}}Then compile this program in a command window with the "javac" command:C:\>\progra~1\java\jdk1.6.0_02\bin\javac Hello.javaTo execute the program, use the java command:C:\>\progra~1\java\jdk1.6.0_02\bin\java HelloHello world!Congratulations, you have successfully entered, compiled and executed your first Java program.


Chapter - 3Installing J2SE 1.5.0 on WindowsDownloading and Installing J2SE 1.5.0 on WindowsHere is what I did to download and install JDK 1.5.0 on my Windows system:1. Go to http://java.sun.com/j2se/1.5.0/download.jsp.2. Click the "Download JDK" hyper link.3. Follow the instructions on the Web pages to download jdk-1_5_0-windows-i586.exe to a workingdirectory on your hard disk. This file is about 45 MB.4. Double click on the file name: jdk-1_5_0-windows-i586.exe in the working directory in the FileExplorer.5. Follow the instruction on the installation window to finish the installation. Remember to specify thetarget directory as: \j2sdk1.5.0.6. Open a command window to try the java command. If you are getting the following output, youknow your installation is done correctly:C:\>\j2sdk1.5.0\bin\java -versionjava version "1.5.0"Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode)Testing J2SE 1.5.0 InstallationNow let's test the JDK 1.5 installation.1. Use NotePad to enter the following Java program:class Hello {public static void main(String[] a) {System.out.println("Hello world!");}}2. Save this program with the file Hello.java in a working folder C:\herong3. Then compile this program in a command window with the javac command:C:\>cd \herongC:\herong> \j2sdk1.5.0\bin\javac Hello.java3. Finally, execute the program using the java command:C:\herong>\j2sdk1.5.0\bin\java -cp . HelloHello world!


Congratulations, you have successfully entered, compiled and executed your first Java program withyour newly installed JDK 1.5.0.


Chapter - 4'javac' - The Java Program CompilerThis chapter describes the Java compilation tool 'javac'. Topics include listing of 'javac' options,specifying class path with '-classpath', specifying source path with '-sourcpath', processing 'import'statements, generating debugging information with '-g'.'javac' - Java Compilation Command and OptionsCompiling Hello.java - My First Java ProgramOption '-classpath' - Specifying Class PathOption '-sourcepath' - Specifying Source PathOption '-d' - Specifying Output DirectoryTwo Types of 'import' Statements'import' Statements Processed by 'javac'Option "-g" - Controlling Debugging InformationConclusions:• "javac" is the standard compiler in JDK.• "-sourcepath" specifies places where to search for source definitions of new types.• "-classpath" specifies places where to search for class definitions of new types.• Two types of "import" statements behave differently with "javac".• Never distribute your class files with debugging information in them.'javac' - Java Compilation Command and Options"javac": A command line tool that reads Java source files and compiles them into bytecode class files."javac" is distributed as part of the Sun JDK package and represented by the \j2sdk1.5.0\bin\javac.exeprogram file. It has the following syntax:javac [options] [sourcefiles]where "options" is a list of options and "sourcefiles" is a list of Java source files.Commonly used options are:• "-help" - Displays a short help text.• "-verbose" - Generates verbose output to standard output.• "-classpath classpath" - Specifies a list of path names where the compiler will search forcompiled type definitions. If "-classpath" is not specified, the current directory will be used asthe class path.• "-sourcepath sourcepath" - Specifies a list of path names where the compiler will search forsource type definitions. If "-source" is not specified, the current directory will be used as thesource path.• "-d directory" - Specifies the directory where the compiler will store the generated class files. If


"-d" is not specified, the class files will be stored in the same places as the source files.• "-g | -g:none" - Asks the compiler to generate debugging information into the class files orgenerates no debugging information at all.If you run the "javac" command without any options, you will get the quick usage information asshown below:C:\>\j2sdk1.5.0\bin\javacUsage: javac where possible options include:-g Generate all debugging info-g:noneGenerate no debugging info-g:{lines,vars,source} Generate only some debugging info-nowarnGenerate no warnings-verboseOutput messages about what the compiler isdoing-deprecationOutput source locations where deprecatedAPIs are used-classpath Specify where to find user class files-cp Specify where to find user class files-sourcepath Specify where to find input source files-bootclasspath Override location of bootstrap class files-extdirs Override location of installed extensions-endorseddirs Override location of endorsed standards path-d Specify where to place generated class files-encoding Specify character encoding used by sourcefiles-source Provide source compatibility with specifiedrelease-target Generate class files for specific VM version-versionVersion information-helpPrint a synopsis of standard options-X Print a synopsis of nonstandard options-JPass directly to the runtime systemCompiling Hello.java - My First Java ProgramTo test the compiler, I wrote my first Java program with a text editor:class Hello {public static void main(String[] a) {System.out.println("Hello world!");}}Then I saved this program with the file Hello.java in a working directory C:\herongHere is what I did in a command window to compile Hello.java with the 'javac' Java compiler tool. Theoutput of the compilation is a Java class file called Hello.class:C:\>cd \herongC:\herong>\j2sdk1.5.0\bin\javac Hello.javaC:\herong>dir Hello.*416 Hello.class


116 Hello.javaAs you can see from this tutorial, the simplest way to use the 'javac' Java compiler is to:• Open a command line window.• Change the current directory to the directory with the Java program is stored.• Run the 'javac' Java compiler tool with the full path name \j2sdk1.5.0\bin\javac.exe.• The compilation output file is a class file, stored in the current directory.Option '-classpath' - Specifying Class PathThe most commonly used "javac" option is "-classpath", which specifies a list of path names where thecompiler will search for compiled type definitions. If "-classpath" is not specified, the current directorywill be used as the class path.When compiler encounters an unknown type in the source file, it will try to find the type definition bysearching class files in the class path.To experiment how the compiler uses "-classpath", I wrote the following simple source file,EchoerTest.java:/*** EchoerTest.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/public class EchoerTest {public static void main(String[] a) {Echoer e = new Echoer();e.setReq("Hello world!");System.out.println(e.getRes());}}When I tried to compile this source file, I got the following error:C:\herong>javac EchoerTest.javaEchoerTest.java:7: cannot resolve symbolsymbol : class Echoerlocation: class EchoerTestEchoer e = new Echoer();As you can see, the compiler failed to find the definition for the type "Echoer".In order to help the compiler to find the missing type definition, I wrote the following source code forthe Echoer class, Echoer.java:/*** Echoer.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/public class Echoer {private String req = null;private String res = null;public void setReq(String r) {req = new String(r);


}char[] a = r.toCharArray();int n = a.length;for (int i=0; ijavac Echoer.javaC:\herong>javac -verbose -classpath . EchoerTest.java[parsing started EchoerTest.java][parsing completed 30ms][loading \j2sdk1.5.0\jre\lib\rt.jar(java/lang/Object.class)][loading \j2sdk1.5.0\jre\lib\rt.jar(java/lang/String.class)][checking EchoerTest][loading .\Echoer.class][loading \j2sdk1.5.0\jre\lib\rt.jar(java/lang/System.class)][loading \j2sdk1.5.0\jre\lib\rt.jar(java/io/PrintStream.class)][loading \j2sdk1.5.0\jre\lib\rt.jar(java/io/FilterOutputStream.class)][loading \j2sdk1.5.0\jre\lib\rt.jar(java/io/OutputStream.class)][wrote EchoerTest.class][total 221ms]C:\herong>java EchoerTest!dlrow olleHNote that:• I used "-classpath ." to specify the current directory as the class path for the compiler to searchfor the class definition of "Echoer".• The compiler loaded .\Echoer.class correctly, when Echoer definition was needed.• The compiler loaded other class definitions from the "rt.jar" from the system path.Option '-sourcepath' - Specifying Source PathIf you use a new type, and you don't have the class definition of that type, but you have its sourcedefinition, you can use the "-sourcepath sourcepath" option to tell compiler to get that sourcedefinition.Let's use the same source files, Echoer.java and EchoerTest.java, to test this:C:\herong>del Echoer.classC:\herong>del EchoerTest.classC:\herong>javac -verbose -sourcepath . EchoerTest.java[parsing started EchoerTest.java][parsing completed 30ms]


following 4 source files.1. ClsA.java:/*** ClsA.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/package com.herong.util;public class ClsA {public void printInfo() {System.out.println("Class: com.herong.util.ClsA");}}2. ClsB.java:/*** ClsB.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/package com.herong.util;public class ClsB {public void printInfo() {System.out.println("Class: com.herong.util.ClsB");}}3. ImportTestA.java:/*** ImportTestA.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/import com.herong.util.*;public class ImportTestA {public static void main(String[] arg){ClsA a = new ClsA();a.printInfo();ClsB b = new ClsB();b.printInfo();}}4. ImportTestB.java:/*** ImportTestB.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/import com.herong.util.ClsA;import com.herong.util.ClsB;public class ImportTestB {public static void main(String[] arg){ClsA a = new ClsA();a.printInfo();ClsB b = new ClsB();b.printInfo();}}


Read the following section to see how "javac" compilation tool processing "import" statements.'import' Statements Processed by 'javac'After saving all 4 source files described in the previous section, I did the following:C:\herong>mkdir .\comC:\herong>mkdir .\com\herongC:\herong>mkdir .\com\herong\utilC:\herong>copy ClsA.java .\com\herong\utilC:\herong>copy ClsB.java .\com\herong\utilC:\herong>javac ImportTestA.javaImportTestA.java:8: cannot access ClsAbad class file: .\ClsA.javafile does not contain class ClsAPlease remove or make sure it appears in the correct subdirectory ofthe classpath.ClsA a = new ClsA();^1 errorWhat's wrong with ImportTestA.java, which uses the "On-demand type import" statement? The answeris obvious if we use the -verbose compiler option:C:\herong>javac -verbose ImportTestA.java[parsing started ImportTestA.java][parsing completed 30ms][loading c:\j2sdk1.4.2\jre\lib\rt.jar(java/lang/Object.class)][loading c:\j2sdk1.4.2\jre\lib\rt.jar(java/lang/String.class)][checking ImportTestA][loading .\ClsA.java][parsing started .\ClsA.java][parsing completed 0ms]ImportTestA.java:8: cannot access ClsAbad class file: .\ClsA.javafile does not contain class ClsAPlease remove or make sure it appears in the correct subdirectory ofthe classpath.ClsA a = new ClsA();^[total 230ms]1 errorC:\herong>javac -verbose ImportTestB.java[parsing started ImportTestB.java][parsing completed 30ms][loading .\com\herong\util\ClsA.class][loading .\com\herong\util\ClsB.class][loading c:\j2sdk1.4.2\jre\lib\rt.jar(java/lang/Object.class)][loading c:\j2sdk1.4.2\jre\lib\rt.jar(java/lang/String.class)][checking ImportTestB][wrote ImportTestB.class][total 221ms]


What happened with ImportTestA.java compilation was that:• First, the compiler reached "import com.herong.util.*;", but it did not load any type definition.• Then, the compiler reached "ClsA a = new ClsA();", it started to search for the definition of"ClsA".• Then, the compiler found "ClsA.java" in the current directory.• Then, the compiler found out that "ClsA.java" is in the wrong directory path comparing with itspackage name.The compilation of ImportTestB.java went very smoothly:• First, the compiler reached "import com.herong.util.ClsA;", it loaded.\com\herong\util\ClsA.class immediately. ClsA.java has already compiled by the previous test.• Then, the compiler reached "import com.herong.util.ClsB;", it loaded.\com\herong\util\ClsB.class immediately. ClsB.java has already compiled by the previous test.• Then, the compiler reached "ClsA a = new ClsA();", it had the definition of ClsA ready to use,no search needed.• Then, the compiler reached "ClsB b = new ClsB();", it had the definition of ClsB ready to use,no search needed.Of course, we know how to fix the problem. Just remove ClsA.java and ClsB.java from the currentdirectory. "javac" will continue to search for the ClsA in the package specified in "importcom.herong.util;".This test shows us that:• "Single type import" statements load classes immediately.• "javac" searches for definitions of new types first in the loaded classes, then in the source path,and finally in the packages specified in the "On-demand type import" statements.Option "-g" - Controlling Debugging InformationAs we see earlier, the "-g" compiler option can be used to control how much debugginginformation should be generated into the class files. Here are the choices on how to use thisoption:Choice Option Information generated in class1 -g:none No debug information2 -g:lines Line number only3 -g:lines,source Line number & source file4 (default) Same as #35 -g:lines,source,vars Line number, source file & variables6 -g Same as #5Of course, the more debugging information you generate in a class file, the more debugging power youwill get when you debug this class. However, once your source code is fully debugged, you shouldrecompile your code with "-g:none", so that you don't distribute you class file will any debugginginformation.Leaving debugging information in your class file will have the following negative effects:• Class file will be larger - Harder to distribute. Longer time to load.• Easier for others to reverse engineer your source code.


Chapter - 5'java' - The Java Program LauncherThis chapter describes the Java launch tool 'java'. Topics include listing of 'java' options, specifyingclass path with '-classpath', specifying an executable JAR file with '-jar', specifying non-standardoptions with '-X', launching Java programs without the console window.'java' - Java Launching Command and OptionsLaunching Hello.java - My First Java ProgramOption "-classpath" - Specifying Class PathOption '-jar' - Specifying Executable JAR FilesOption '-X' - Specifying Non-Standard Options'javaw' - Launching Java Programs without ConsoleConclusions:• "java" is the standard application launcher in JDK.• "-sourcepath" specifies places where to search for class definitions of new types.• "-jar" specifies a JAR file and launches the class specified in the manifest file.• "javaw" is identical to "java" except that it will not create the console window.'java' - Java Launching Command and Options"java": A command line tool that launches Java applications. It starts a Java virtual machine, loads thespecified class, and invokes that class's main method. "java" has the following syntax:java [options] class [arguments]where "options" is a list of options; "class" is the full name of a Java class to be launched; "arguments"is a list of arguments to be passed to the main method of the class to be launched.Another way of launching a Java class is to use the "-jar" option:java [options] -jar file [arguments]where "file" is a JAR file, which should contain a "Main-Class" attribute in the manifest file. The"Main-Class" attibute defines the Java class to be launched.Commonly used options are:• "-help" - Displays a short help text.• "-verbose" - Generates verbose output to standard output.• "-version" - Prints the version information of the launcher.• "-classpath classpath" - Specifies a list of path names where the launcher will search forcompiled type definitions. If "-classpath" is not specified, the current directory will be used asthe class path.


• "-Dproperty=value" - Defines a new system property, which can be accessed by the application.If you run the "java" command without any options, you will get the quick usage information as shownbelow:C:\>\j2sdk1.5.0\bin\javaUsage: java [-options] class [args...](to execute a class)or java [-options] -jar jarfile [args...](to execute a jar file)where options include:-client to select the "client" VM-server to select the "server" VM-hotspot is a synonym for the "client" VM [deprecated]The default VM is client.-cp -classpath A ; separated list of directories, JAR archives,and ZIP archives to search for class files.-D=set a system property-verbose[:class|gc|jni]enable verbose output-version print product version and exit-version:require the specified version to run-showversion print product version and continue-jre-restrict-search | -jre-no-restrict-search include/excludeuser private JREs in the version search-? -help print this help message-X print help on non-standard options-ea[:...|:]-enableassertions[:...|:]enable assertions-da[:...|:]-disableassertions[:...|:]disable assertions-esa | -enablesystemassertionsenable system assertions-dsa | -disablesystemassertionsdisable system assertions-agentlib:[=]load native agent library ,e.g. -agentlib:hprof see also,-agentlib:jdwp=help and -agentlib:hprof=help-agentpath:[=]load native agent library by full pathname-javaagent:[=]load Java programming language agent,see java.lang.instrumentLaunching Hello.java - My First Java ProgramTo test the Java launcher, 'java', I wrote the following Java file, Hello.java:


class Hello {public static void main(String[] a) {System.out.println("Hello world!");}}Here is what I did in a command window to compile Hello.java into Hello.class:C:\herong>javac Hello.javaC:\herong>dir Hello.*416 Hello.class116 Hello.javaC:\herong>java HelloHello world!As you can see, launching a simple Java application is easy - Run the 'java' command without anyoptions.Option "-classpath" - Specifying Class PathThe most commonly used "java" option is "-classpath", which specifies a list of path names where thelauncher will search for compiled type definitions. If "-classpath" is not specified, the current directorywill be used as the class path.To experiment how the compiler uses "-classpath", I wrote the following simple source file,Echoer.java:/*** Echoer.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/public class Echoer {private String req = null;private String res = null;public void setReq(String r) {req = new String(r);char[] a = r.toCharArray();int n = a.length;for (int i=0; i


* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/public class EchoerTest {public static void main(String[] a) {Echoer e = new Echoer();e.setReq("Hello world!");System.out.println(e.getRes());}}Then I stored them in two different directories, and tried to launch EchoerTest:C:\herong>mkdir echoC:\herong>copy Echoer.java echoC:\herong>mkdir testC:\herong>copy EchoerTest.java testC:\herong>cd testC:\herong>javac -classpath ..\echo EchoerTest.java>java EchoerTestException in thread "main" java.lang.NoClassDefFoundError: Echoerat EchoerTest.main(EchoerTest.java:7)C:\herong>java -classpath ..\echo EchoerTestException in thread "main" java.lang.NoClassDefFoundError: EchoerTestC:\herong>java -classpath .;..\echo EchoerTest!dlrow olleHNote that:• The first time I tried to launch "EchoerTest" without "-classpath", "java" failed to find "Echoer"class, because "java" uses the current directory as the default class path.• The second time I tried to launch "EchoerTest" with "-classpath ..\echo", "java" failed to find"EchoerTest" class, because the specified class path didn't include the current directory.• The third time I tried to launch "EchoerTest" with "-classpath .;..\echo", "java" was able to findboth "EchoerTest" and "Echoer".Option '-jar' - Specifying Executable JAR FilesIn order to use the "-jar" option, we need to create a JAR file with a "Main-Class" attribute in themanifest file.Here is what I did to create a JAR file, and launch it with the "-jar" option.First I created a manifest file, hello.fs:Main-Class: HelloThen I created an executable JAR file, hello.jar, with Hello.class and hello.fs:


C:\herong>javac Hello.javaC:\herong>jar -cvmf hello.fs hello.jar Hello.classadded manifestadding: Hello.class(in = 416) (out= 285)(deflated 31%)Finally, I launched the Hello.class program included in the executable JAR file:C:\herong>java -jar hello.jarHello world!Option '-X' - Specifying Non-Standard Options"java" can also take "non-standard" options by using the "-X" option.Two of the "non-standard" options are very useful to control the memory size of the JVM to belaunched.-Xmsn-Xmxnwhere "ms" specifies the initial size of the JVM, "mx" specifies the maximum size of the JVM, and "n"specifies the memory size in bytes, kilo bytes or mega bytes. For example: -Xms32M and -Xmx64M.Here is a program to show you how to use these options:/*** ShowMemory.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/class ShowMemory {public static void main(String[] a) {Runtime rt = Runtime.getRuntime();System.out.println(" Free memory: " + rt.freeMemory());System.out.println("Total memory: " + rt.totalMemory());while (true);}}I launched the program with different options:C:\herong>javac ShowMemory.javaC:\herong>java ShowMemoryFree memory: 1896232Total memory: 2031616C:\herong>java -Xms32M -Xmx128M ShowMemoryFree memory: 33222440Total memory: 33357824C:\herong>java -Xms64M -Xmx128M ShowMemoryFree memory: 66514728Total memory: 66650112


'javaw' - Launching Java Programs without ConsoleIf you launch a Java application with "java" in a command window, JVM will use that commandwindow as the console. If you launch a Java application with "java" in a different way, "java" willcreate new command window and use it as the console.If you don't want console, you can user "javaw" launch your application. "javaw" works exactly like"java" except that it will not create any console.Here is what I did to test the "javaw" tool.1. Compile ShowMemory.java and copy ShowMemory.class to c:\herong.2. Go to Start > Run, type "java -classpath c:\herong ShowMemory", and click OK.3. You should see a command window showing up displaying the program output. "java" tool createdthis window as the console.4. Go to Start > Run, type "javaw -classpath c:\herong ShowMemory", and click OK.5. You should see no command window showing up. But what happens to my program? Is it stillrunning?6. Go to Start > Run, type "taskmgr", and click OK. The Windows Task Manager windows shows up.7. Go to "Process" tab, you should see two Java processes: "java" and "javaw". This answers myprevious question. "javaw" is still running ShowMemory without any console as expected.Through this tutorial, we should remember that when you use "javaw" to launch an application, noconsole window will be created and data sent to the standard output stream will not be displayed. So"javaw" is good tool for applications that do not need the console window, like GUI applications andserver applications.


Chapter - 6'jdb' - The Java DebuggerThis chapter provides tutorial notes on the Java debugger 'jdb'. Topics include starting 'jdb' to debug anapplication, running 'jdb' separately from the application, debugging remote application, debuggingmulti-thread application, listing and switching execution threads.'jdb' - Java Debugger Command and OptionsStarting a Debugging Session with 'jdb'Debugging Applications with Separate 'jdb' SessionsDebugging Java Applications RemotelyListing Debugging Commands with 'help' CommandPrimeNumberSeeker.java - Multi-Thread Sample ProgramStarting Debugging Session on a Multi-Thread ApplicationStepping through Statements of the Child ThreadChecking Variable Values in a Debugging SessionDebugging the Main Thread of a Multi-Thread ApplicationSwitching Execution Threads in a Debugging SessionSuspending Main Thread to Debug Child ThreadConclusions:• "jdb" is a nice debugging tool. But it only offers a command line interface, not so easy to use. Itis much more efficient to use graphical interface debugger.• JPDA is well designed, allowing us to debug Java applications remotely.• Debugging multi-thread application is tricky. The following "jdb" notes may help you.• Whenever one thread reaches a break point, all other threads are stopped also.• The command prompt tells what is the current thread.• "where all" tells where the execution are currently in all threads.• "threads" lists all the threads with thread indexes as Hex numbers.'jdb' - Java Debugger Command and Options"jdb": A command line tool that allows you to debug a Java application interactively with in acommand line mode. "javac" is distributed as part of the Sun JDK package. It has the following syntax:jdb [options] main_class_namejdb [options] -attach where "options" is a list of options, "main_class_name" is a the name of the main class of a Javaapplication, and "address" is the debugging connection address of a running Java application.


As you can see from the syntax, there are two ways of running "jdb":1. Running "jdb" to launch a Java application and start a debug session on that application.2. Running "jdb" to connect to a separately launched Java application and start a debug session on thatapplication.Commonly used options are:• "-help" - Displays a short help text.• "-verbose" - Generates verbose output to standard output.• "-classpath classpath" - Specifies a list of path names where the launcher will search forcompiled type definitions.• "-Dproperty=value" - Defines a new system property, which can be accessed by the application.• "-launch" - Launches the debugged application immediately upon startup of jdb. This optionremoves the need for using the run command. The target application is launched and thenstopped just before the initial application class is loaded. At that point you can set any necessarybreakpoints and use the cont to continue execution.Note that in order to use all debugging commands, the target application must be compiled with "-g"option, which will generate all debugging information, including source file, line number, and localvariables, into the class file.Starting a Debugging Session with 'jdb'To test the debugger, I wrote the following simple Java application, Hello.java:class Hello {public static void main(String[] a) {System.out.println("Hello world!");}}Here is what I did in a command window to run "jdb" to launch and debug Hello.java:C:\herong>javac Hello.javaC:\herong>jdb HelloInitializing jdb ...> stop in Hello.mainDeferring breakpoint Hello.main.It will be set after the class is loaded.> runrun HelloSet uncaught java.lang.ThrowableSet deferred uncaught java.lang.Throwable>VM Started: Set deferred breakpoint Hello.mainBreakpoint hit: "thread=main", Hello.main(), line=3 bci=03 System.out.println("Hello world!");main[1] nextHello world!


Step completed: "thread=main", Hello.main(), line=4 bci=84 }main[1] cont>The application exitedNotice that:• Once started, "jdb" offers you command prompt to allow you to run debugging commandsinteractively.• Without the "-launch" option, "jdb" will not start the main() method of the specified class.• "stop in" command sets a breakpoint at the beginning of the specified method. See the nextsection for other commonly used debugging commands.• "run" command starts a new JVM process with run your application in debug mode.• "jdb" and the JVM of your application are different processes. If you use Windows TaskManager, you should see two processes named as "jdb" and "java".• "next" command executes only the current statement of the debugged application.• "cont" command resumes the execution to the end or the next breakpoint.If you want to launch the target application immediately, you can use the "-launch" option:C:\herong>jdb -launch HelloSet uncaught java.lang.ThrowableSet deferred uncaught java.lang.ThrowableInitializing jdb ...>VM Started: No frames on the current call stackmain[1] cont> Hello world!The application has been disconnectedAs we expected, "jdb -launch" command launches the target application immediately, and stops at thebeginning of the main() method.Debugging Applications with Separate 'jdb' SessionsIf you ask "Can I launch the debugger ('jdb') and the target application separately?", the answer is "Yes,you can.". In JDK 1.5, both "jdb" and "java" have been enhanced to use the latest JPDA (Java PlatformDebugger Architecture) technology to give you the following options:DebuggerTargetOption jdb java1 Shared memory client Shared memory server2 Shared memory server Shared memory client3 Socket client Socket server4 Socket server Socket clientThe shared memory options requires that the debugger and the target application to be on the samemachine. Of course, the socket options allow you to run them remotely.


Let's try option #1 first. Open a command window on a windows system and run:C:\herong>java -agentlib:jdwp=transport=dt_shmem,address=MyHello,server=y,suspend=y HelloListening for transport dt_shmem at address: MyHelloThe target application is launched in "shared memory server" mode. Its execution is suspended. Nowopen another command window and run:C:\herong>jdb -attach MyHelloSet uncaught java.lang.ThrowableSet deferred uncaught java.lang.ThrowableInitializing jdb ...>VM Started: No frames on the current call stackmain[1] stop in Hello.mainDeferring breakpoint Hello.main.It will be set after the class is loaded.main[1] cont> Set deferred breakpoint Hello.mainBreakpoint hit: "thread=main", Hello.main(), line=3 bci=03 System.out.println("Hello world!");main[1] list1 public class Hello {2 public static void main(String[] a) {3 => System.out.println("Hello world!");4 }5 }main[1] cont>The application exitedAs you can see, the debugger successfully connected to the target application. I used "next" commandto let the target application to execute the current statement.Debugging Java Applications RemotelyAs we can see from the previous section, we can run a Java application and the 'jdb' debuggerseparately in shared memory mode. But this requires that the Java application and the 'jdb' debuggermust be running on the same machine.If you have a large application that you need to run a big server machine, you can debug thatapplication by running the 'jdb' debugger on your own desktop machine using the socket debuggingcommunication mode as presented in the previous section.Let's try it now. Open a command window on a windows system and run:C:\herong>java -agentlib:jdwp=transport=dt_socket,address=localhost:8888,server=y,suspend=y HelloListening for transport dt_socket at address: 8888


The target application is launched in "socket server" mode. Its execution is suspended. Now openanother command window and run:C:\herong>jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8888Set uncaught java.lang.ThrowableSet deferred uncaught java.lang.ThrowableInitializing jdb ...>VM Started: No frames on the current call stackmain[1] stop in Hello.mainDeferring breakpoint Hello.main.It will be set after the class is loaded.main[1] cont> Set deferred breakpoint Hello.mainBreakpoint hit: "thread=main", Hello.main(), line=3 bci=03 System.out.println("Hello world!");main[1] quiteCool. I know how to run "jdb" to debug an application running on a remote machine now!However, the command suggested in the JPDA documentation did not work:C:\herong>jdb -attach localhost:8888java.io.IOException: shmemBase_attach failed: The system cannot findthe file specifiedat com.sun.tools.jdi.SharedMemoryTransportService.attach0(......My guess is that the Windows version of "jdb" assumes "shared memory" as the default transportmode.Listing Debugging Commands with 'help' CommandOk, I think we did enough excises about launching the debugger and connecting to the targetapplication. Let's now move on to look at some debugging commands.Here is list of commonly used debugging commands. I got this list by using "help" at debuggingprompt.C:\herong>jdb> run...run [class [args]]-- start execution of an applicationthreads [threadgroup] -- list threadsthread -- set default threadsuspend [thread id(s)] -- suspend threads (default: all)resume [thread id(s)] -- resume threads (default: all)where [ | all] -- dump a thread's stackup [n frames]-- move up a thread's stackdown [n frames]-- move down a thread's stack


kill interrupt print dump eval set = localsclassesclass methods fields threadgroupsthreadgroup -- kill a thread with the given exception-- interrupt a thread-- print value of expression-- print all object information-- evaluate expression (same as print)-- assign new value to a variable-- print all local variables-- list currently known classes-- show details of named class-- list a class's methods-- list a class's fields-- list threadgroups-- set current threadgroupstop in .[(argument_type,...)]-- set a breakpoint in a methodstop at : -- set a breakpoint at a lineclear .[(argument_type,...)]-- clear a breakpoint in a methodclear : -- clear a breakpoint at a lineclear-- list breakpointscatch [uncaught|caught|all] |-- break when specified exception occursignore [uncaught|caught|all] |-- cancel 'catch'watch [access|all] .-- watch access/modifications to a fieldunwatch [access|all] .-- discontinue watchingtrace methods [thread] -- trace method entry and exituntrace methods [thread] -- stop tracing method entry and exitstep-- execute current linestep up-- execute until the current method returnsstepi-- execute current instructionnext-- step one line (step OVER calls)cont-- continue execution from breakpointlist [line number|method] -- print source codeuse (or sourcepath) [source file path]-- display or change the source pathclasspath-- print classpath info from target VMmonitor monitorunmonitor read lock threadlocks [thread id]disablegc enablegc -- execute specified command at stop time-- list monitors-- delete a monitor-- read and execute a command file-- print lock info for an object-- print lock info for a thread-- prevent garbage collection of an object-- permit garbage collection of an object!! -- repeat last command -- repeat command n times


help (or ?)versionexit (or quit)-- list commands-- print version information-- exit debuggerPrimeNumberSeeker.java - Multi-Thread Sample ProgramTo help me practice debugging commands, I wrote the following simple multi-thread application,PrimeNumberSeeker.java:1 /**2 * PrimeNumberSeeker.java3 * Copyright (c) 2003 by Dr. Herong Yang, www.herongyang.com4 */5 public class PrimeNumberSeeker extends Thread {6 private static final int ceiling = 100;7 private static final int interval = 1000;8 private static final int delay = 100;9 public int count = 0;10 public int current = 2;11 public int[] primes = null;12 public static void main(String[] a) {13 System.out.println("Period, Current int, # primes");14 PrimeNumberSeeker t = new PrimeNumberSeeker();15 t.start();16 int i = 0;17 while (true) {18 i++;19 System.out.println( i+", "+t.current+", "+t.count);20 try {21 sleep(interval);22 } catch (InterruptedException e) {23 System.out.println("Monitor interrupted.");24 }25 }26 }27 public void run() {28 primes = new int[ceiling];29 while (count < ceiling) {30 current++;31 int j = 2;32 boolean isPrime = true;33 while (j 0;35 j++;36 }37 if (isPrime) {38 count++;39 primes[count-1] = current;40 }41 try {42 sleep(delay);43 } catch (InterruptedException e) {44 System.out.println("Runner interrupted.");45 }46 }47 }48 }


Note that:• This application tries to use a sub-thread to calculate prime numbers.• The main thread is monitoring how the sub-thread is doing.• A delay mechanism is used to slow the calculation.• The application has an infinite loop. So you have to terminate it by "Ctrl-C".Here is how I compiled the application and executed without debugging:C:\herong>javac -g PrimeNumberSeeker.javaC:\herong>java PrimeNumberSeekerPeriod, Current int, # primes1, 2, 02, 12, 53, 22, 84, 32, 115, 42, 136, 52, 157, 62, 188, 72, 209, 82, 2210, 92, 2411, 102, 2612, 112, 2913, 122, 30...53, 521, 9854, 531, 9955, 541, 10056, 541, 10057, 541, 100...The output seems to be fine. But I want to use "jdb" to exam the calculation and to practice thedebugging commands. I will show my debugging session in multiple parts with my comments insections below.Starting Debugging Session on a Multi-Thread Application1. Setting up breakpoints and getting the debugging session going:C:\herong>jdb PrimeNumberSeekerInitializing jdb ...> stop in PrimeNumberSeeker.mainDeferring breakpoint PrimeNumberSeeker.main.It will be set after the class is loaded.> runrun PrimeNumberSeekerSet uncaught java.lang.ThrowableSet deferred uncaught java.lang.Throwable>VM Started: Set deferred breakpoint PrimeNumberSeeker.main


Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=1313 System.out.println("Period, Current int, # primes");main[1] stop in PrimeNumberSeeker.runSet breakpoint PrimeNumberSeeker.runmain[1] contPeriod, Current int, # primes1, 2, 0>Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=2828 primes = new int[ceiling];Thread-0[1] threadsGroup system:(java.lang.ref.Reference$ReferenceHandler)0xe2 Reference Handler(java.lang.ref.Finalizer$FinalizerThread)0xe1 Finalizer(java.lang.Thread)0xe0Signal DispatcherGroup main:(java.lang.Thread)0x1 main running(PrimeNumberSeeker)0x118 Thread-0 running (at breakpoint)Ok. What I have done so far:• Started the debugging session with the first breakpoint at the beginning of the main() method,which cause the execution to stop at line 13.• Then I created the second breakpoint at the beginning of the run() method in order to catch thesub thread.• Then I issued the "cont" command. My application continued with the sub thread createdstopped at the breakpoint at line 28. The main thread also stopped.• Noticed that the debugger prompt is changed from "main[1]" to "Thread-0[1]". This is to informyou that you are currently in the sub thread, no longer in the main thread.• Then I used the "threads" command to list all threads. I saw two thread groups: "system" and"main". Of course, I am not interested in the "system" group at this point. The "main" showstwo threads: "main" (my monitoring thread) and "Thread-0" (my sub thread working on thecalculation).• Thread "Thread-0" status shows "running (at breakpoint)". But the word "running" is referringto the thread execution mode, not the current execution status.• Notice that tread "main" is also stopped at this moment. As a general rule, if one thread isstopped, all other threads are stopped also.Stepping through Statements of the Child Thread2. Stepping through statements in the sub thread:Thread-0[1] where allSignal Dispatcher:Finalizer:[1] java.lang.Object.wait (native method)[2] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:111)[3] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:127)[4] java.lang.ref.Finalizer$FinalizerThread.run (Finalizer.java:...Reference Handler:[1] java.lang.Object.wait (native method)[2] java.lang.Object.wait (Object.java:429)[3] java.lang.ref.Reference$ReferenceHandler.run (Reference.java...


main:[1] java.lang.Thread.sleep (native method)[2] PrimeNumberSeeker.main (PrimeNumberSeeker.java:21)Thread-0:[1] PrimeNumberSeeker.run (PrimeNumberSeeker.java:28)Thread-0[1] next2, 2, 0>Step completed: "thread=Thread-0", PrimeNumberSeeker.run(), line=2929 while (count < ceiling) {Thread-0[1] where all...main:[1] java.lang.Thread.sleep (native method)[2] PrimeNumberSeeker.main (PrimeNumberSeeker.java:21)Thread-0:[1] PrimeNumberSeeker.run (PrimeNumberSeeker.java:29)Thread-0[1] next3, 2, 0>30 current++;Thread-0[1] next4, 3, 0>31 int j = 2;Thread-0[1] next> 5, 3, 032 boolean isPrime = true;Thread-0[1] next6, 3, 0>33 while (j while (j 0;35 j++;36 }37 if (isPrime) {38 count++;Thread-0[1] print currentcurrent = 3What I have done here:• I used "where all" to display the current location of all threads.• Then I used "next" to execute one statement in the current thread, the sub thread, going fromline 28 to line 29.


• The next "where all" command showed me that the main thread went through an entire iterationof the "while" loop. The main thread stopped again at line 21.• Then I used a couple of "next" command in the sub thread to bring the execution to line 33. Atthe same time, the main thread went through a couple of iterations, printed some outputmessages.• Then I used "print" to check the current value of variable "current". Value 3 is correct.Checking Variable Values in a Debugging Session3. Checking local variables:Thread-0[1] next7, 3, 0>37 if (isPrime) {Thread-0[1] print isPrimeisPrime = trueThread-0[1] next8, 3, 0>38 count++;Thread-0[1] next9, 3, 0>39 primes[count-1] = current;Thread-0[1] print countcount = 1Thread-0[1] next> 10, 3, 142 sleep(delay);Thread-0[1] list38 count++;39 primes[count-1] = current;40 }41 try {42 => sleep(delay);43 } catch (InterruptedException e) {44 System.out.println("Runner interrupted.");45 }46 }47 }Thread-0[1] print primes[0]primes[0] = 3What I have done here:• I used "next" again. The sub thread jumped over the calculation loop between line 33 and 36.This is correct, since "current" has "3", a prime number, no need to do any calculation.• Then I used "next" and "print" several times. I saw prime number 3 was correctly recorded in


the "primes" array.Debugging the Main Thread of a Multi-Thread Application4. Going back to the main thread:Thread-0[1] stop at PrimeNumberSeeker:19Set breakpoint PrimeNumberSeeker:19Thread-0[1] cont>Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 bci=2519 System.out.println( i+", "+t.current+", "+t.count);main[1] where allmain:[1] PrimeNumberSeeker.main (PrimeNumberSeeker.java:19)Thread-0:[1] java.lang.Thread.sleep (native method)[2] PrimeNumberSeeker.run (PrimeNumberSeeker.java:42)main[1] print ii = 11main[1] print t.currentt.current = 3main[1] print t.countt.count = 1What I have done here:• I created another breakpoint in the main thread at line 19.• Then I allowed both threads to run naturally to the next breakpoint, line 19. The commandprompt is changed back to "main[1]".• Then I used "where all" to check where the execution are stopped in all threads. It is interestingto see that the sub thread stopped inside the sleep() method.• Then I checked some local variables, "i", "t.current", and "t.count". Their values were allcorrect.Switching Execution Threads in a Debugging Session5. Switching threads:main[1] cont>Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 bci=2519 System.out.println( i+", "+t.current+", "+t.count);main[1] print t.currentt.current = 14main[1] print t.countt.count = 6main[1] where all...


main:[1] PrimeNumberSeeker.main (PrimeNumberSeeker.java:19)Thread-0:[1] java.lang.Thread.sleep (native method)[2] PrimeNumberSeeker.run (PrimeNumberSeeker.java:42)main[1] threads...Group main:(java.lang.Thread)0x1 main running(PrimeNumberSeeker)0x118 Thread-0 running (at breakpoint)main[1] thread 280Thread-0[1] listCurrent method is nativeThread-0[1] step out11, 22, 8>Step completed: "thread=Thread-0", PrimeNumberSeeker.run(), line=4545 }Thread-0[1] list41 try {42 sleep(delay);43 } catch (InterruptedException e) {44 System.out.println("Runner interrupted.");45 => }46 }47 }48 }Thread-0[1] print countcount = 8What I have done here:• I let the main thread executed a full period stopping at line 19 again. Of course, the sub threadexecute some number of statements and stopped inside the sleep() native method.• Then I listed all threads and want to find a way to switch the command prompt to the sub threadto check local variable there. The manual says to use "thread n", where n is the thread index tochange the current thread. But where can I to get the thread index? I tried to search the Web anddid not get any clear answer.• However I got the answer from the output of the threads output. The thread index was listed as ahex number next to the class name. For example, "(PrimeNumberSeeker)0x118" means thread0x118 = 280.• So I used "thread 280" to switch to the sub thread as the current thread. Notice that thecommand prompt changed.• The first "list" command did not work, because the sub thread was stopped inside the "sleep()"method. The "step out" command continued the execution just enough to finish "sleep()" andback to the caller, run().Suspending Main Thread to Debug Child Thread6. Suspending the main thread and keeping only the child thread running:


Thread-0[1] stop at PrimeNumberSeeker:39Set breakpoint PrimeNumberSeeker:39Thread-0[1] cont>Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=3939 primes[count-1] = current;Thread-0[1] cont>Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=1919 System.out.println( i+", "+t.current+", "+t.count);main[1] cont> 12, 23, 9Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=3939 primes[count-1] = current;Thread-0[1] cont>Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=1919 System.out.println( i+", "+t.current+", "+t.count);main[1] suspend 1main[1] cont>Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=3939 primes[count-1] = current;Thread-0[1] cont>Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=3939 primes[count-1] = current;Thread-0[1] cont>Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=3939 primes[count-1] = current;Thread-0[1] print currentcurrent = 41Thread-0[1] print countcount = 13What I have done here:• After check different areas of the code, I wanted to only the break the execution when a newprime number is found. So I created a breakpoint at line 39.• Then I used "cont" to let the execution to continue. But two threads always executed at the sametime, and stopped at the same time whenever one thread reached a breakpoint.• So I used "suspend 1" to suspend the main thread. This is a cool command, allowing me toconcentrate on a single thread. Of course, you can use "resume 1" to release the suspension.I think I have done enough debugging practice and want to stop here now. However, my program doeshave a calculation error. I want to leave it to you to find out.


Chapter - 7'jconsole' - Java Monitoring and Management ConsoleThis chapter provides tutorial notes on the Java monitoring and management console, jconsole. Topicsinclude description of JMX technology, list of 'jconsole' command options, turning on JMX agent forlocal and remote connection, running 'jconsole' to monitor local and remote Java applications.JMX Technology and 'jconsole' Tool'jconsole' Command Options and Connection Window'com.sun.management.jmxremote' - JMX Agent for Local Connection'jconsole' - Connecting to a Local JMX Agent'com.sun.management.jmxremote.port' - JMX Agent for Remote Connection'jconsole' - Connecting to a Remote JMX AgentConclusions:• jconsole is a GUI tool that allows you to monitor a local or remote JVM process using the JMX(Java Management Extension) technology.• JVM processes must be launched with the default JMX properties turned on in order to beconnected by jconsole.• jconsole displays monitoring diagrams for heap memory usage, counts on loaded classes, countson threads, and CPU usages.JMX Technology and 'jconsole' Tool"JMX (Java Management Extensions)": A Java standard API for management and monitoring ofresources such as applications, devices, services, and the Java virtual machine. The JMX technologywas developed through the Java Community Process (JCP) as Java Specification Request (JSR) 3, JavaManagement Extensions, and JSR 160, JMX Remote API.JMX has been implemented into JDK 5 now. You can set out-of-the-box JMX monitoring andmanagement properties when you start the JVM to run your Java application. This allows you to uselocal or remote JMX connectors to monitor your application.JDK 5 offers a graphical user interface called "jconsole" that uses the JMX technology to monitor yourJava application locally or remotely. The picture below shows you how "jconsole" works with yourJava application:


'jconsole' Command Options and Connection Window"jconsole": A graphical user interface tool that enables you to monitor and manage Java applicationsand virtual machines on a local or remote machine using the JMX technology.The "jconsole" tool supports several command options, which can be obtained by the "-help" option:C:\Progra~1\java\jdk1.6.0_02\bin\jconsole -helpUsage: jconsole [ -interval=n ] [ -notile ] [ -pluginpath ][ -version ] [ connection ... ]-interval Set the update interval to n seconds (default is 4 seconds)-notile Do not tile windows initially (for two or more connections)-pluginpath Specify the path that jconsole uses to look up theplugins-version Print program versionconnection = pid || host:port || JMX URL(service:jmx:://...)pid The process id of a target processhost A remote host name or IP addressport The port number for the remote connection-J Specify the input arguments to the Java virtual machineon which jconsole is runningIf you run the "jconsole" command without any option in JDK 1.6, you will get the connection windowas shown below:


This connection window allows you to specify the connection information from UI instead of thecommand line.'com.sun.management.jmxremote' - JMX Agent for Local ConnectionSince JDK 1.5, JMX has been included the Sun JVM. You can turn on the out-of-the-box JMX agentwhen you launch the JVM to run your application. This enables "jconsole" to connect to the JMX agentto monitor you Java application local or remotely.In order to run your Java application and allow "jconsole" to monitor it on the local machine, you needto turn the "com.sun.management.jmxremote" system property with the "-D" option on the "java"command.To this out, I modified the my PrimeNumberSeeker.java program with a higher ceiling value of1000000 to let the loop running much longer:/*** PrimeNumberSeeker.java* Copyright (c) 2008 by Dr. Herong Yang, http://www.herongyang.com/*/public class PrimeNumberSeeker extends Thread {private static final int ceiling = 1000000;private static final int interval = 1000;private static final int delay = 100;public int count = 0;public int current = 2;public int[] primes = null;public static void main(String[] a) {System.out.println("Period, Current int, # primes");PrimeNumberSeeker t = new PrimeNumberSeeker();t.start();int i = 0;while (true) {i++;System.out.println( i+", "+t.current+", "+t.count);try {


}sleep(interval);} catch (InterruptedException e) {System.out.println("Monitor interrupted.");}}}public void run() {primes = new int[ceiling];while (count < ceiling) {current++;int j = 2;boolean isPrime = true;while (j 0;j++;}if (isPrime) {count++;primes[count-1] = current;}try {sleep(delay);} catch (InterruptedException e) {System.out.println("Runner interrupted.");}}}To run this program with the out-of-the-box JMX agent turned on, I used the following commands:C:\Progra~1\java\jdk1.6.0_02\bin\javac PrimeNumberSeeker.javaC:\Progra~1\java\jdk1.6.0_02\bin\java -Dcom.sun.management.jmxremotePrimeNumberSeekerPeriod, Current int, # primes1, 2, 02, 10, 4...Now my application PrimeNumberSeeker.java is running with the JMX agent turned on for localconnection. See the next section on how to run "jconsole" to monitor this application.'jconsole' - Connecting to a Local JMX AgentIf you follow the tutorial presented in the previous section, the PrimeNumberSeeker.java is running in aJVM with the default JMX agent turned on.Now we can run "jconsole" to connect to this JVM to monitor how my PrimeNumberSeeker.java isrunning in two ways:1. Find out the PID (Process ID) of this JVM and use the "jconsole " command to start "jconsole"and connect to this JVM on the local machine.2. Use the "jconsole" command to start "jconsole". It will search for any JVM process that has the local


JMX agent turned on. You can make the connection by clicking the search result list.Obviously, the second way is better, because I don't have figure out the PID of my running JVMprocess. Here what I did to run "jconsole" and connect it to the JVM that runsPrimeNumberSeeker.java:1. Run "C:\Progra~1\java\jdk1.6.0_02\bin\jconole". The connection window shows up with 2 JVMlisted in the local processes section:NamePIDsun.tools.jconsole.JConsole 2204PrimeNumberSeeker 7362. Double click the name "PrimeNumberSeeker", the Java Monitoring & Management Console windowshows with the Overview tab opened as shown in the picture below:Cool. "jconsole" automatically collects some basic statistics like: heap memory usage, number ofthreads, number of classes, and CPU usage.'com.sun.management.jmxremote.port' - JMX Agent for Remote ConnectionIf you want to run 'jconsole' on a remote machine to monitor a Java application, you need to launch theJVM with the default JMX agent turned on using this system property:"com.sun.management.jmxremote.port="Here is what I did to run my PrimeNumberSeeker.java with the default JMX agent for remotemonitoring connections:


1. To run this program with the out-of-the-box JMX agent turned on, I used the following commands:C:\Progra~1\java\jdk1.6.0_02\bin\java-Dcom.sun.management.jmxremote.port=6789PrimeNumberSeekerError: Password file not found: C:\Program Files\java\jdk1.6.0_02\jre\lib\management\jmxremote.password2. I got this error because the remote JMX agent requires a password file to only give permissions toauthorized remote connections. For testing purpose, I used this system property:"com.sun.management.jmxremote.authenticate=false" to turn off the authentication function:C:\Progra~1\java\jdk1.6.0_02\bin\java-Dcom.sun.management.jmxremote.port=6789-Dcom.sun.management.jmxremote.authenticate=falsePrimeNumberSeekerPeriod, Current int, # primes1, 2, 02, 10, 4...3. I tried to run "jconsole localhost:6789" to connect to this JMX agent remotely. But the connectionfailed with this error dialog box:4. The connection failed because the remote JMX agent also requires a SSL client certificate. Fortesting purpose, I used this system property: "com.sun.management.jmxremote.ssl=false" to turn off theSSL function:C:\Progra~1\java\jdk1.6.0_02\bin\java-Dcom.sun.management.jmxremote.port=6789-Dcom.sun.management.jmxremote.authenticate=false-Dcom.sun.management.jmxremote.ssl=falsePrimeNumberSeekerPeriod, Current int, # primes1, 2, 02, 10, 4...Now I am ready run "jconsole" to connect to this JMX agent remotely. See the next section for moretutorial examples.'jconsole' - Connecting to a Remote JMX AgentIf you follow the tutorial presented in the previous section, the PrimeNumberSeeker.java is running in aJVM with the remote JMX agent turned on waiting for remote connections at the port: 6789.Now we can run "jconsole localhost:6789" to connect to this JVM remotely to monitor how my


PrimeNumberSeeker.java is running:1. Run "jconsole localhost:6789". "jconsole" connects to my Java application correctly. The JavaMonitoring & Management Console shows up.2. Click the Memory tab, the memory usage detail information show up as shown in this picture:


Chapter - 8'jstat' - JVM Statistics Monitoring ToolThis chapter provides tutorial notes on JVM statistics monitoring tools. Topics include listing JVMprocesses with 'jps', the JVM remote monitoring server - 'jstatd', Java security policy file, connecting'jps' and 'jstat' to a remote machine, RMI protocol and URL, getting garbage collection statistics with'jstat -gcutil'.'jps' - JVM Process Status ToolListing JVM Processes on the Local Machine with "jps"'jstatd' - JVM Remote Monitoring ServerStarting 'jstatd' with a Security Policy FileConnecting to 'jps' to Remote 'jstatd''jstat' Command Options and ParametersGarbage Collection Testing Program'jstat -gcutil' - Garbage Collection StatisticsAccessing Remote JVM Processes with 'jstat'Conclusions:• JDK 1.6 offers 3 nice JVM monitoring tools: jps, jstatd, and jstat.• jps is simple tool that allows you to list all running JVM processes on the local machine or aremote machine.• jstatd is an RMI server that allows you to access local JVM processes by jps and jstat fromremote machines.• jstat is a monitoring tool that allows you to obtain sample data periodically from a local orremote JVM process.'jps' - JVM Process Status Tool"jps": A new Java tool that lists all JVM processes on the local machine or a remote machine. "jps" toolis distributed as part of the Sun JDK package and represented by the\Progra~1\java\jdk1.6.0_02\bin\jps.exe program file. "jps" can be executed with the following syntax:jps [options] [hostid]where "options" is a list of options and "hostid" is the host identifier of a remote machine."jps" options are listed below:• -l Output the full package name for the application's main class or the full path name to theapplication's JAR file.• -m Output the arguments passed to the main method. The output may be null for embeddedJVMs.• -q Suppress the output of the class name, JAR file name, and arguments passed to the main


method, producing only a list of local VM identifiers.• -v Output the arguments passed to the JVM.• -Joption Pass option to the java launcher called by jps. For example, -J-Xms48m sets the startupmemory to 48 megabytes. It is a common convention for -J to pass options to the underlyingVM executing applications written in Java.You don't need to use the "hostid" command argument, if you want to list JVM processes on the localmachine. But to list JVM processes on a remote, you need to use "hostid" to specify how to connect tothe remove machine. The "hostid" is a string with the following syntax:[protocol:][[//]hostname][:port][/servername]protocolThe communications protocol. The default protocol is "rmi".hostnameA hostname or IP address indicating the remote host.portThe default port for communicating with the remote server.The default port is the RMI registry port (1099).servernameThe treatment of this parameter depends on the implementation.For the "rmi" protocol, this parameter is a string representingthe name of the RMI remote object on the remote host.See sections below for tutorial examples on how to use "jps" to list JVM processes on the local or aremote machine.Listing JVM Processes on the Local Machine with "jps"It is very easy to listing JVM processes on the local machine using the "jps" tool. Here is what I did:1. Run the PrimeNumberSeeker.java program I wrote in another tutorial in a command window:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\javac PrimeNumberSeeker.javaC:\herong>\Progra~1\java\jdk1.6.0_02\bin\java PrimeNumberSeeker 10 200Period, Current int, # primes1, 2, 02, 12, 53, 21, 8...2. While PrimeNumberSeeker.java is running to search for prime numbers, run the "jps" tool in anothercommand window:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m -v2836 PrimeNumberSeeker 10 2003812 sun.tools.jps.Jps -l -m -v-Dapplication.home=C:\Program Files\java\jdk1.6.0_02 -Xms8m


Several interesting notes on the "jps" output:• Each JVM process is represented by starting class running in side the JVM.• The number displayed before the class name is the process ID.• When you run "jps", it starts a JVM process, which is also listed in the "jps" output.• The package name, "sun.tools.jps", is displayed because of the "-l" option.• The arguments passed to the main method, "10 200", are displayed because of the "-m" option.• The parameters passed to the JVM, "-D... -X...", are displayed because of the "-v" option.'jstatd' - JVM Remote Monitoring Server"jstatd": A server that allows JVM monitoring tools like "jps" and "jstat" to access JVM processes froma remote machine. "jstatd" tool is distributed as part of the Sun JDK package and represented by the\Progra~1\java\jdk1.6.0_02\bin\jstatd.exe program file. "jstatd" can be executed with the followingsyntax:jstatd [options]"jstatd" options are listed below:• "-p port" Port number where the RMI registry is expected to be found. If not found, an internalRMI registry will be created with this port number.• "-n rminame" Name to which the remote RMI object is bound in the RMI registry. The defaultname is JStatRemoteHost.After "jstatd" is started, JVM monitoring tools, "jps" and "jstat", can connect to it from a remotemachine and access local JVM processes as shown in the picture below:See next section on how to start "jstatd".Starting 'jstatd' with a Security Policy FileIn this tutorial, we are going to try to start the JVM remote monitoring server, "jstatd".1. Run the "jstatd" command in a command window:


C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstatdCould not create remote objectaccess denied (java.util.PropertyPermissionjava.rmi.server.ignoreSubClasses write)java.security.AccessControlException: access denied(java.util.PropertyPermissionjava.rmi.server.ignoreSubClasses write)at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)at java.security.AccessController.checkPermission(AccessController.java:546)at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)at java.lang.System.setProperty(System.java:727)at sun.tools.jstatd.Jstatd.main(Jstatd.java:122)The "access denied" error is expected, because "jstatd" requires a security policy file specified with the"java.security.policy" system property, if there is no security manager running on my machine.2. Create the security policy file, tools.policy, that grants permissions to run "jstatd" and other tools inthe tools.jar:grant codebase "file:${java.home}/../lib/tools.jar" {permission java.security.AllPermission;};3. Run "jstatd" with the security policy file, tools.policy specified to the "java.security.policy" systemproperty:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstatd -p 1234-J-Djava.security.policy=tools.policy"jstatd" is running correctly now. It created an internal RMI registry and waiting at port 1234 for RMIprotocol connections from remote machines by JVM monitoring tools. See the next section on how torun "jps" and "jstat" tools from remote machines.Connecting to 'jps' to Remote 'jstatd'With the "jstatd" server running on my local machine as described in the previous section, now I amready to test how to connect to this "jstatd" server with the "jps" command from a remote machine tolist JVM processes.1. Run my test Java program PrimeNumberSeeker.java in another command window on my localmachine:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\java PrimeNumberSeeker 10 200Period, Current int, # primes1, 2, 02, 10, 4...


2. Run the "jps" command to connect to the "jstatd" server with the "rmi://localhost" URL as the hostidentifier:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m -v rmi://localhostRMI Registry not available at localhost:1099Connection refused to host: localhost; nested exception is:java.net.ConnectException: Connection refused: connect3. The cause of the error is obvious, the "jstatd" server started the internal RMI registry at the port1234, not the default port 1099. So Run the "jps" command again with the "rmi://localhost:1234":C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m -vrmi://localhost:12343056 sun.tools.jstatd.Jstatd -p 1234 -Dapplication.home=C:\jdk -Xms8m-Djava.security.policy=tools.policy4080 sun.tools.jps.Jps -l -m -v rmi://localhost:1234-Dapplication.home=C:\Program Files\java\jdk1.6.0_02 -Xms8m2024 PrimeNumberSeeker 10 200Cool. The "jps" successfully connected to the RMI registry through the "jstatd" server. The outputshows correctly all running JVM processes.'jstat' Command Options and Parameters"jstat": A JVM statistics monitoring tool that displays performance statistics of a given JVM processwith a specified sampling interval. "jstat" tool is distributed as part of the Sun JDK package andrepresented by the \Progra~1\java\jdk1.6.0_02\bin\jstat.exe program file. "jstat" can be executed withthe following syntax:jstat [options] vmid interval [count]• "options" - List of "jstat" command options.• "vmid" - Virtual machine identifier string to identify a local or a remote JVM process.• "interval" - Sampling interval in seconds (s) or mimilliseconds (ms).• "count" - Number of samples to collect. Default value is infinity; that is, jstat displays statisticsuntil the target JVM terminates or the jstat command is terminated.Some "jstat" options are listed below:• "-t" - Display a timestamp column as the first column of output. The timestamp is the the timesince the start time of the target JVM.• "-class" - Display multiple columns of statistics on the behavior of the class loader.• "-compiler" - Display multiple columns of statistics of the behavior of the HotSpot Just-in-Timecompiler.• "-gc" - Display multiple columns of statistics of the behavior of the garbage collected heap.• "-gcutil" - Display multiple columns of summary of garbage collection statistics.• "-gccapacity" - Display multiple columns of statistics of the capacities of the generations andtheir corresponding spaces.See the next section on how to use "jstat" to collect statistic samples of a given JVM process.


Garbage Collection Testing ProgramSince most of "jstat" options are about garbage collection statistics, I wrote this garbage collectiontesting program to test the "jstat" tool:/*** GarbageCollection.java* Copyright (c) 2008 by Dr. Herong Yang, http://www.herongyang.com/*/class GarbageCollection {public static void main(String[] a) {int max = 10000;int min = 16;Object[] arr = new Object[min];Runtime rt = Runtime.getRuntime();System.out.println("Free/total memory:");for (int m=0; m


19429328 2503475218330752 2503475217237416 2503475216137560 2503475215040664 2503475213943848 2503475212843752 2503475211747448 2503475210650832 250347529552096 250347528452192 250347527357216 250347526258720 250347525159112 250347524060976 250347522965296 250347521865656 25034752767256 250347527356032 25034752 // Garbage Collection6257576 250347525159368 250347524060712 250347522964336 250347521867032 25034752767176 250347527356512 25034752 // Garbage Collection6258136 250347525159360 250347524060464 250347522964064 250347521866728 25034752766568 250347527356272 25034752 // Garbage Collection...The output shows that the garbage collector is working correctly to remove those objects shifted out ofthe arr[].'jstat -gcutil' - Garbage Collection StatisticsWith the garbage collection testing program running, I am ready to test the "jstat" tool. The first test isrun "jstat" with the "-gcutil -t" option to get statistic samples on a local JVM process.1. Run the "jps" to get the process ID of the GarbageCollection.java JVM:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m -v3824 sun.tools.jps.Jps -l -m -v-Dapplication.home=C:\Program Files\java\jdk1.6.0_02 -Xms8m3868 GarbageCollection -Xms24m -Xmx24m2924 PrimeNumberSeeker 10 2002544 sun.tools.jstatd.Jstatd -p 1234 -Dapplication.home=C:\jdk -Xms8m-Djava.security.policy=tools.policy2. Run the "jstat" to get the summary of garbage collection statistics of the GarbageCollection JVM


identified by the process ID 3868:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstat -gcutil -t 3868 1s 30Time S0 S1 E O P YGC YGCT FGC FGCT GCT313.7 0.00 99.99 4.20 84.56 0.15 2093 3.653 416 13.998 17.651314.6 0.00 99.99 0.00 97.66 0.15 2100 3.665 417 14.023 17.688315.6 0.00 0.00 0.00 71.25 0.15 2106 3.674 419 14.090 17.764316.7 0.00 99.99 4.20 84.56 0.15 2113 3.687 420 14.124 17.811317.7 0.00 99.99 0.00 97.66 0.15 2120 3.699 421 14.158 17.858318.6 0.00 0.00 0.00 71.25 0.15 2126 3.708 423 14.225 17.933319.7 0.00 99.99 4.20 84.56 0.15 2133 3.721 424 14.259 17.980320.7 0.00 99.99 0.00 97.66 0.15 2140 3.734 425 14.293 18.027321.6 0.00 0.00 0.00 71.25 0.15 2146 3.743 427 14.360 18.103322.7 0.00 99.99 4.20 84.56 0.15 2153 3.756 428 14.394 18.149323.7 0.00 99.99 0.00 97.66 0.15 2160 3.769 429 14.428 18.196324.7 0.00 0.00 67.14 71.25 0.15 2166 3.777 431 14.495 18.272325.7 0.00 99.99 4.20 84.56 0.15 2173 3.790 432 14.528 18.319326.7 0.00 99.99 0.00 97.66 0.15 2180 3.803 433 14.563 18.366327.7 0.00 99.99 86.29 97.66 0.15 2185 3.810 434 14.588 18.397328.7 99.99 0.00 0.00 77.66 0.15 2192 3.821 436 14.656 18.476329.7 0.00 99.99 71.29 84.56 0.15 2198 3.832 437 14.690 18.522330.7 0.00 99.99 19.15 97.66 0.15 2205 3.845 438 14.723 18.568331.7 99.99 0.00 0.00 77.66 0.15 2212 3.855 440 14.791 18.646332.7 0.00 99.99 71.29 84.56 0.15 2218 3.867 441 14.825 18.692...The last two parameters "1s 30" tells "jstat" to collect 30 samples with an interval of 1 second.To understand the statistic output, you need to read the full documentation of the "jstat" tool.Accessing Remote JVM Processes with 'jstat'In the previous section, I used the "jstat" tool to get garbage collection statistic against a JVM processon the local machine.Now I want to use the "jstat" tool to get garbage collection statistic against a JVM process on a remotemachine. Like the "jps" tool, the "jstat" tool also requires that the remote machine running the "jstatd"server with a RMI registry.1. Make sure that the "jstatd" server is running on the remote machine:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstatd -p 1234-J-Djava.security.policy=tools.policy2. Make sure that the garbage collection program is running on the remote machine:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\java-Xms24m -Xmx24m GarbageCollectionFree/total memory:23725256 2503475222710400 25034752...


3. Run the "jps" tool to get a list of JVM process IDs on the remote machine:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m -vrmi://localhost:12342924 PrimeNumberSeeker 10 2002544 sun.tools.jstatd.Jstatd -p 1234 -Dapplication.home=C:\jdk -Xms8m-Djava.security.policy=tools.policy3028 sun.tools.jps.Jps -l -m -v rmi://localhost:1234-Dapplication.home=C:\Program Files\java\jdk1.6.0_02 -Xms8m3536 GarbageCollection -Xms24m -Xmx24m4. I am ready to run the "jstat" tool to get some statistics data on the garbage collection program:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstat -gcutil -trmi://3536@localhost:1234 1s 30Time S0 S1 E O P YGC YGCT FGC FGCT GCT303.6 0.00 99.99 86.29 97.66 0.15 2025 3.589 402 13.500 17.089304.6 99.99 0.00 35.16 77.66 0.15 2032 3.597 404 13.559 17.155305.6 100.00 0.00 51.20 90.69 0.15 2039 3.610 405 13.592 17.202...Cool. The "jstat" tool works nicely to get statistics data from a JVM process on a remote machine.


Chapter - 9JVM Troubleshooting ToolsThis chapter tutorial notes on JVM troubleshooting tools. Topics include 'jinfo' to check JVM optionvalues, 'jstack' to dump stack traces and detect deadlocks, 'jmap' to print heap histogram and dump heapfiles, 'jhat' to browse head files and run OQL queries.JVM Troubleshooting Tools in JDK 1.5'jinfo' - VM Option Value CheckerChanging HotSpot VM Option using 'jinfo''jstack' - Stack Tracer of JVM ThreadsJava Thread Deadlock Demo ProgramDetecting Java Thread Deadlocks with 'jstack''jmap' - JVM Heap Dump ToolPrinting Histogram of Java Object HeapGenerating Heap Dump File with 'jmap''jhat' - Java Heap Analysis ToolStarting 'jhat' Web Server on a Heap Dump FileListing Instance Counts of All ClassesBrowsing Object Instance ValuesObject Query Language (OQL)Searching for Instances with OQL StatementsConclusions:• JDK 1.6 offers a number of nice trouble shooting tools: jinfo, jstack, jmap, and jhat.• jinfo allows you to check current VM options of a running JVM process.• jstack allows you to dump thread stack traces and find any deadlocks.• jmap allows you to print heap memory usages and instance counts by classes and dump theentire heap to a file.• jhat allows you to browse a heap dump file with a Web interface.• jhat also supports OQL (Object Query Language) statements - a very powerful tool toinvestigate any data issues in your Java application.JVM Troubleshooting Tools in JDK 1.5If you look at Java tools section of the JDK 1.5 documentation page, you will see a group of newexperimental tools called "Troubleshooting Tools":"jinfo": Prints configuration information for a given JVM process or a Java core file on the localmachine or on a remote machine through a debug server.


"jhat" - Heap Dump Browser: Starts a Web server on a Java heap dump file (eg, produced by "jmap-dump"), allowing the heap to be browsed."jmap" - Memory Map: Prints shared object memory maps or heap memory details of a given JVMprocess or a Java core file on the local machine or on a remote machine through a debug server."jsadebugd" - Serviceability Agent Debug Daemon: Attaches to a JVM process or a Java core file andacts as a debug server for remote tools to connect."jstack" - Stack Trace: Prints a stack trace of threads for a given JVM process or a Java core file onthe local machine or on a remote machine through a debug server.Note that not all functions described above are available on Windows systems. See next sections onhow to use those tools provided in JDK 1.6 on a Windows system.'jinfo' - VM Option Value CheckerThe first JVM troubleshooting tool I want try is the "jinfo" tool.The "jinfo" tool included in the Windows version of JDK 1.6 only supports functions to view andmodify HotSpot VM options of the specified JVM process. Here is the "jinfo" command syntax:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jinfoUsage:jinfo (to connect to a running process)where is one of:-flag to print the value of the named VM option-flag [+|-] to enable or disable the named VM option-flag = to set the named VM option to the given value-h | -help to print this help messageHotSpot VM supports many options as described on the "Java HotSpot VM Options" page. You canchange the default value of any HotSpot VM option using the "-XX:..." command option when runningthe "java" command.Here is a tutorial example of how to use the "jinfo" tool get the current value of a given VM option:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\java-jar "\Program Files\java\jdk1.6.0_02\demo\jfc\Notepad\notepad.jar"(Notepad started.)(Start another command window.)C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m424 \Program Files\java\jdk1.6.0_02\demo\jfc\Notepad\notepad.jar3984 sun.tools.jps.Jps -l -mC:\herong>\Progra~1\java\jdk1.6.0_02\bin\jinfo-flag ThreadStackSize 424-XX:ThreadStackSize=0


Note that:• The "jps" tool is used to get the process ID (pid) of the Notepad JVM: 424.• The output of the "jinfo" command shows that the current value of the ThreadStackSize optionis 0 in the Notepad JVM.Changing HotSpot VM Option using 'jinfo'The "jinfo" tool can be used to view the current value of any HotSpot VM option of a given JVMprocess as described in the previous section.The "jinfo" tool can also be used set a new value of any HotSpot VM option using the "jinfo -flagname=value" format. Here is what I did to test this function with JDK 1.6 on a Windows system:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\java -XX:ThreadStackSize=512-jar "\Program Files\java\jdk1.6.0_02\demo\jfc\Notepad\notepad.jar"(Notepad started)(Start another command window.)C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m1424 \Program Files\java\jdk1.6.0_02\demo\jfc\Notepad\notepad.jar3124 sun.tools.jps.Jps -l -mC:\herong>\Progra~1\java\jdk1.6.0_02\bin\jinfo-flag ThreadStackSize 1424-XX:ThreadStackSize=512C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jinfo-flag ThreadStackSize=1024 1424Exception in thread "main" java.io.IOException:Command failed in target VMat sun.tools.attach.WindowsVirtualMachine.execute(WindowsVirtualMachine.java:94)at sun.tools.attach.HotSpotVirtualMachine.executeCommand(HotSpotVirtualMachine.java:195)at sun.tools.attach.HotSpotVirtualMachine.setFlag(HotSpotVirtualMachine.java:172)at sun.tools.jinfo.JInfo.flag(JInfo.java:105)at sun.tools.jinfo.JInfo.main(JInfo.java:58)Apparently, the target VM (the Notepad VM) does not allow me to change its option. I do not knowwhy?'jstack' - Stack Tracer of JVM Threads"jstack": A JVM troubleshooting tool that prints stack traces of all running threads of a given JVMprocess, a Java core file, or remote debug server. The "jstack" tool included in the JDK 1.6 Windowsversion only supports limited functions as shown the this help message:


C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstack -helpUsage:jstack [-l] (to connect to running process)Options:-l long listing. Prints additional information about locks-h or -help to print this help messageIn order to test "jstack", I used this simple Java program, LongSleep.java:/*** LongSleep.java* Copyright (c) 2008 by Dr. Herong Yang, http://www.herongyang.com/*/class LongSleep {public static void main(String[] a) {Runtime rt = Runtime.getRuntime();System.out.println(" Free memory: " + rt.freeMemory());System.out.println("Total memory: " + rt.totalMemory());try {Thread.sleep(1000*60*60);}catch (InterruptedException e) {}}}When LongSleep.java is running, I used "jps" to get its JVM process ID, pid. Then I ran "jstack" withthat pid to get the following stack information:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\javac LongSleep.javaC:\herong>\Progra~1\java\jdk1.6.0_02\bin\java LongSleepFree memory: 4997104Total memory: 5177344(Start another command window.)C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m3296 LongSleep2224 sun.tools.jps.Jps -l -mC:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstack 3296Full thread dump Java HotSpot(TM) Client VM (1.6.0_02-b06 mixed mod..."Low Memory Detector" daemon prio=6 tid=0x02a7c800 nid=0xf20 runnablejava.lang.Thread.State: RUNNABLE"CompilerThread0" daemon prio=10 tid=0x02a78000 nid=0xb3c waiting ...java.lang.Thread.State: RUNNABLE"Attach Listener" daemon prio=10 tid=0x02a76c00 nid=0x37c waiting ...java.lang.Thread.State: RUNNABLE"Signal Dispatcher" daemon prio=10 tid=0x02a75c00 nid=0xd7c runnablejava.lang.Thread.State: RUNNABLE"Finalizer" daemon prio=8 tid=0x02a71400 nid=0x2e8 in Object.wait()


java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)- locked (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)"Reference Handler" daemon prio=10 tid=0x02a6d000 nid=0xfbc in Obje...java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:485)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)- locked (a java.lang.ref.Reference$Lock)"main" prio=6 tid=0x00296000 nid=0xef4 waiting on condition [0x0090...java.lang.Thread.State: TIMED_WAITING (sleeping)at java.lang.Thread.sleep(Native Method)at LongSleep.main(LongSleep.java:10)"VM Thread" prio=10 tid=0x02a63c00 nid=0xc70 runnable"VM Periodic Task Thread" prio=10 tid=0x02a7e000 nid=0xdd0 waiting ...JNI global references: 571Cool. Now I know how many threads are running inside a JVM, 8 of them. But my Java application,LongSleep, only runs under 1 thread named as "main", which is in a state called, TIMED_WAITING.This matches my expectation.Java Thread Deadlock Demo ProgramIn the previous section, "jstack" was used to print stack traces of all running threads of a given JVMprocess. But "jstack" can also be used to detect deadlocks inside a given JVM process. The tutorialexample below shows you how "jstack" prints deadlock information:1. Copy and save this Java program,/*** SimpleDeadLock.java* Copyright (c) 2008 by Dr. Herong Yang, http://www.herongyang.com/*/import java.util.*;public class SimpleDeadLock extends Thread {public static Object l1 = new Object();public static Object l2 = new Object();private int index;public static void main(String[] a) {Thread t1 = new Thread1();Thread t2 = new Thread2();t1.start();t2.start();}private static class Thread1 extends Thread {public void run() {synchronized (l1) {


}System.out.println("Thread 1: Holding lock 1...");try { Thread.sleep(10); }catch (InterruptedException e) {}System.out.println("Thread 1: Waiting for lock 2...");synchronized (l2) {System.out.println("Thread 2: Holding lock 1 & 2...");}}}}private static class Thread2 extends Thread {public void run() {synchronized (l2) {System.out.println("Thread 2: Holding lock 2...");try { Thread.sleep(10); }catch (InterruptedException e) {}System.out.println("Thread 2: Waiting for lock 1...");synchronized (l1) {System.out.println("Thread 2: Holding lock 2 & 1...");}}}}2. Compile and run SimpleDeadLock.java. A deadlock will be created immediately between tworunning threads:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\javac SimpleDeadLock.javaC:\herong>\Progra~1\java\jdk1.6.0_02\bin\java SimpleDeadLockThread 1: Holding lock 1...Thread 2: Holding lock 2...Thread 2: Waiting for lock 1...Thread 1: Waiting for lock 2...This deadlock is expected - Thread 1 is holding lock 1 and waiting for lock 2, while thread 2 is holdinglock 2 and waiting for lock 1.See the next section on how to use "jstack" to print the deadlock information and stack traces of 2related threads.Detecting Java Thread Deadlocks with 'jstack'This section provides a tutorial example on how to detect Java thread deadlocks with the thread stacktrace dump tool, 'jstack'.With the deadlock demo program, SimpleDeadLock.java, running in a locked status as described in theprevious section, I am ready to run "jstack" to print the deadlock information and stack traces of 2locked threads:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m1464 SimpleDeadLock


464 sun.tools.jps.Jps -l -mC:\herong>\Progra~1\java\jdk1.6.0_02\bin\jstack 1464Full thread dump Java HotSpot(TM) Client VM (1.6.0_02-b06 mixed mod..."DestroyJavaVM" prio=6 tid=0x00296000 nid=0x198 waiting on conditio...java.lang.Thread.State: RUNNABLE"Thread-1" prio=6 tid=0x02a99c00 nid=0xee0 waiting for monitor entr...java.lang.Thread.State: BLOCKED (on object monitor)at SimpleDeadLock$Thread2.run(SimpleDeadLock.java:37)- waiting to lock (a java.lang.Object)- locked (a java.lang.Object)"Thread-0" prio=6 tid=0x02a99000 nid=0xefc waiting for monitor entr...java.lang.Thread.State: BLOCKED (on object monitor)at SimpleDeadLock$Thread1.run(SimpleDeadLock.java:24)- waiting to lock (a java.lang.Object)- locked (a java.lang.Object)"Low Memory Detector" daemon prio=6 tid=0x02a7c800 nid=0xd2c runnab...java.lang.Thread.State: RUNNABLE"CompilerThread0" daemon prio=10 tid=0x02a78000 nid=0x500 waiting o...java.lang.Thread.State: RUNNABLE"Attach Listener" daemon prio=10 tid=0x02a76c00 nid=0x32c waiting o...java.lang.Thread.State: RUNNABLE"Signal Dispatcher" daemon prio=10 tid=0x02a75c00 nid=0x190 runnabl...java.lang.Thread.State: RUNNABLE"Finalizer" daemon prio=8 tid=0x02a6e000 nid=0xdb0 in Object.wait()...java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)- locked (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)"Reference Handler" daemon prio=10 tid=0x02a6d000 nid=0xa44 in Obje...java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:485)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)- locked (a java.lang.ref.Reference$Lock)"VM Thread" prio=10 tid=0x02a63c00 nid=0xe88 runnable"VM Periodic Task Thread" prio=10 tid=0x02a7e000 nid=0xf58 waiting ...JNI global references: 571Found one Java-level deadlock:


============================="Thread-1":waiting to lock monitor 0x02a6ee64 (object 0x229bd238,a java.lang.Object), which is held by "Thread-0""Thread-0":waiting to lock monitor 0x02a6eecc (object 0x229bd240,a java.lang.Object), which is held by "Thread-1"Java stack information for the threads listed above:==================================================="Thread-1":at SimpleDeadLock$Thread2.run(SimpleDeadLock.java:37)- waiting to lock (a java.lang.Object)- locked (a java.lang.Object)"Thread-0":at SimpleDeadLock$Thread1.run(SimpleDeadLock.java:24)- waiting to lock (a java.lang.Object)- locked (a java.lang.Object)Found 1 deadlock.The output of "jstack" is very useful for debugging. It tells me:• How many deadlocks exist in this JVM process.• What are the 2 waiting threads for each deadlock.• Stack traces of waiting threads with source code line numbers, if source codes were compilewith debug options.'jmap' - JVM Heap Dump Tool"jmap" - Memory Map: Prints shared object memory maps or heap memory details of a given JVMprocess or a Java core file on the local machine or on a remote machine through a debug server. "jmap"supports several functions with these syntaxes:jmap [ option ] pidjmap [ option ] executable corejmap [ option ] [server-id@]remote-hostname-or-IPWhen no option is used jmap prints shared object mappings.For each shared object loaded in the target VM, start address,the size of the mapping, and the full path of the shared objectfile are printed. This is similar to the Solaris pmap utility.-dump:[live,]format=b,file=Dumps the Java heap in hprof binary format to filename. The livesuboption is optional. If specified, only the live objects in theheap are dumped. To browse the heap dump, you can use jhat (JavaHeap Analysis Tool) to read the generated file.-finalizerinfoPrints information on objects awaiting finalization.-heapPrints a heap summary. GC algorithm used, heap configuration andgeneration wise heap usage are printed.


-histo[:live]Prints a histogram of the heap. For each Java class, number ofobjects, memory size in bytes, and fully qualified class namesare printed. VM internal class names are printed with '*' prefix.If the live suboption is specified, only live objects are counted.-permstatPrints class loader wise statistics of permanent generation ofJava heap. For each class loader, its name, liveness, address,parent class loader, and the number and size of classes it hasloaded are printed. In addition, the number and size of internedStrings are printed.-FForce. Use with jmap -dump or jmap -histo option if the pid doesnot respond. The live suboption is not supported in this mode.But the "jmap" tool included in the Windows version of JDK 1.6 only supports functions to printhistogram of Java object heap and generate a heap dump of a given JVM process:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jmapUsage:jmap -histo (to print histogram of java object heap of the JVM process)jmap -dump: (to dump java heap of the JVM process)dump-options:format=b binary defaultfile= dump heap to Example: jmap -dump:format=b,file=heap.bin See the next section on how to use "jmap" to print heap histogram and to generate heap dump.Printing Histogram of Java Object HeapThe first function of the "jmap" tool is to print histogram of object heap of a given JVM process. Now Iam going to use a sample Java program, GarbageCollection.java, I wrote in another tutorial example inthis book.The first test is to print the heap histogram of a JVM process that runs GarbageCollection.java with the"jmap -histo pid" command:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\javac GarbageCollection.javaC:\herong>\Progra~1\java\jdk1.6.0_02\bin\java-Xms24m -Xmx24m GarbageCollectionFree/total memory:23725256 2503475222710400 2503475221618728 2503475220523584 25034752...


(Start another command window.)C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m492 sun.tools.jps.Jps -l -m428 GarbageCollectionC:\herong>\Progra~1\java\jdk1.6.0_02\bin\jmap -histo 428num #instances #bytes class name--------------------------------------1: 23 4723136 [I2: 19 4718928 [J3: 18 4718880 [D4: 73925 1774200 java.lang.String5: 208 1226400 [C6: 28 1205064 [B7: 18 1179936 [F8: 68 297040 [Ljava.lang.String;9: 332 14136 [Ljava.lang.Object;10: 32 10240 11: 42 4032 java.lang.Class12: 58 1392 java.util.Hashtable$Entry13: 16 1280 [Ljava.util.HashMap$Entry;14: 27 1000 15: 6 864 [S16: 7 680 [Ljava.util.Hashtable$Entry;17: 11 616 java.net.URL18: 19 608 java.util.Locale19: 5 560 java.lang.Thread20: 14 560 java.util.HashMap...The histogram gives a very good summary of heap objects used in my GarbageCollection.javaprogram:• Most of the objects were String objects. There were 73925 of them. This matches well withwhat I allocated in the program: one array of 64*64 string objects for each 1-MB object. If 16 1-MB objects were allocated, there should be 65536 string objects.• "[Ljava.lang.String;" is a special class name representing a java.lang.String[] array.• "[I" is a special class name representing a int[] array.Generating Heap Dump File with 'jmap'The second function of the "jmap" tool is to generate a heap dump of a given JVM process with the"jmap -dump:file=" command:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\java-Xms24m -Xmx24m GarbageCollectionFree/total memory:23725256 2503475222710400 2503475221618728 2503475220523584 25034752


...(Start another command window.)C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jps -l -m764 GarbageCollection1204 sun.tools.jps.Jps -l -mC:\herong>\Progra~1\java\jdk1.6.0_02\bin\jmap-dump:file=GarbageCollection.map 764Dumping heap to C:\herong\GarbageCollection.map ...Heap dump file createdC:\herong>dir *.map12:08 AM 19,816,895 GarbageCollection.mapSo the heap dump file, "GarbageCollection.map", is a snapshot of all heap objects used by the runningGarbageCollection.java process.Heap dump files can be browsed by the heap dump browser, "jhat", as described in the next section.'jhat' - Java Heap Analysis Tool"jhat" - Java heap analysis tool or heap dump file browser: Parses a Java heap dump file and launches aWeb server. "jhat" enables you to browse heap dump files using your favorite webbrowser. "jhat"supports pre-designed queries (such as 'show all instances of a known class "Foo"') as well as OQL(Object Query Language) - a SQL-like query language to query heap dumps. Help on OQL is availablefrom the OQL help page shown by "jhat". With the default port, OQL help is available athttp://localhost:7000/oqlhelp/But the "jmap" tool included in the Windows version of JDK 1.6 only supports functions to printhistogram of Java object heap and generate a heap dump of a given JVM process:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jhat -helpUsage: jhat [-stack ] [-refs ] [-port ][-baseline ] [-debug ] [-version] [-h|-help] -stack false Turn off tracking object allocation call stack.-refs false Turn off tracking of references to objects-port Set the port for the HTTP server. Default is 7000.-exclude Specify a file that lists data members that shouldbe excluded from the reachableFrom query.-baseline Specify a baseline object dump. Objects inboth heap dumps with the same ID and same classwill be marked as not being "new".-debug Set debug level.0: No debug output1: Debug hprof file parsing2: Debug hprof file parsing, no server-versionReport version number-h|-helpPrint this help and exit


The file to readFor a dump file that contains multiple heap dumps,you may specify which dump in the fileby appending "#" to the file name, i.e. "foo.hprof#3".All boolean options default to "true"Starting 'jhat' Web Server on a Heap Dump FileIn an earlier tutorial example, I created a Java heap dump file with the "jmap" tool on myGarbageCollection.java program. The heap dump file is named as GarbageCollection.map. Now I wantto try to run the "jhat" Web server on this dump file and browse the heap dump with a Web browser.1. Run the "jhat" command with default options:C:\herong>\Progra~1\java\jdk1.6.0_02\bin\jhat GarbageCollection.mapReading from GarbageCollection.map...Dump file created Jan 1 00:08:10 EDT 2008Snapshot read, resolving...Resolving 67324 objects...Chasing references, expect 13 dots.............Eliminating duplicate references.............Snapshot resolved.Started HTTP server on port 7000Server is ready.2. Run a Web browser with http://localhost:7000. The "jhat" heap dump file server page shows up:See next sections on how to use "jhat" Web server to browse heap objects.


Listing Instance Counts of All ClassesRunning "jhat" Web server on a heap dump file offers us a very good debugging tool. You can getstatistical counts of loaded classes and objects. You can review object contents and references. You canalso run object queries to search for any specific information.First, let's see how to get instance counts for all loaded classes.1. Run a Web browser with http://localhost:7000. The heap dump first page shows up.2. Click the link of "Show instance counts for all classes (including platform)". The instance count pageshows up:65733 instances of class java.lang.String362 instances of class java.lang.Class330 instances of class [Ljava.lang.Object;206 instances of class [C66 instances of class [Ljava.lang.String;58 instances of class java.util.Hashtable$Entry50 instances of class [I26 instances of class [B19 instances of class java.util.Locale19 instances of class java.util.concurrent.ConcurrentHashMap$HashEntry17 instances of class [J16 instances of class java.util.HashMap$Entry16 instances of class java.util.concurrent.ConcurrentHashMap$Segment16 instances of class java.util.concurrent.locks.ReentrantLock$NonfairSync16 instances of class [D16 instances of class [F16 instances of class [Ljava.util.HashMap$Entry;16 instances of class [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;14 instances of class java.lang.Object14 instances of class java.util.HashMap14 instances of class java.util.LinkedHashMap$Entry12 instances of class java.io.ExpiringCache$Entry11 instances of class java.net.URL10 instances of class java.io.ObjectStreamField....The output shows that the highest count is the number of java.lang.String instances. This is expected,because I created String arrays with 64*64 Strings in each array.Browsing Object Instance ValuesAfter looking object instance counts, I want to find some object instances created by my program andbrowse their values. My program, GarbageCollection.java, used the following code to create manyjava.lang.Object[] instances:private static Object getOneMega() {Object[] lst = new Object[10];lst[0] = new long[256*128];lst[1] = new int[256*256];lst[2] = new double[256*128];lst[3] = new float[64*256];lst[4] = new byte[64*1024];


}String[] l = new String[64*64];for (int i=0; i


Object Query Language (OQL)OQL (Object Query Language): A SQL-like query language to query Java heap. OQL allows tofilter/select information wanted from Java heap. While pre-defined queries such as "show all instancesof class X" are already supported by HAT, OQL adds more flexibility. OQL is based on JavaScriptexpression language.OQL query is of the form"select [ from [instanceof] [ where ] ]where class name is fully qualified Java class name (example: java.net.URL) or array class name. [C ischar array name, [Ljava.io.File; is name of java.io.File[] and so on. Note that fully qualified class namedoes not always uniquely identify a Java class at runtime. There may be more than one Java class withthe same name but loaded by different loaders. So, class name is permitted to be id string of the classobject. If instanceof keyword is used, subtype objects are selected. If this keyword is not specified, onlythe instances of exact class specified are selected. Both from and where clauses are optional.In select and (optional) where clauses, the expression used in JavaScript expression. Java heap objectsare wrapped as convenient script objects so that fields may be accessed in natural syntax. For example,Java fields can be accessed with obj.field_name syntax and array elements can be accessed witharray[index] syntax. Each Java object selected is bound to a JavaScript variable of the identifier namespecified in from clause.OQL Examples:select all Strings of length 100 or more:select s from java.lang.String s where s.count >= 100select all int arrays of length 256 or more:select a from [I a where a.length >= 256show content of Strings that match a regular expression:select s.value.toString() from java.lang.String swhere /java/(s.value.toString())show path value of all File objects:select file.path.value.toString() from java.io.File fileshow names of all ClassLoader classes:select classof(cl).namefrom instanceof java.lang.ClassLoader clshow instances of the Class identified by given id string:select o from instanceof 0xd404b198 oNote that 0xd404b198 is id of a Class (in a session).This is found by looking at the id shown in that class's page.See next section on how to run OQL statements on the "jhat" Web server.


Searching for Instances with OQL StatementsTo test the power of OQL, I want to find those Object[] instances created by my program, excludingObject[] created by the JVM platform.1. Run a Web browser with http://localhost:7000. The heap dump first page shows up.2. Click the link of "Execute Object Query Language (OQL) query". The OQL query page shows up.3. Enter the following query and click the Execute button:select i from [Ljava.lang.Object; i where i.length == 10Cool. "jhat" returns a list of instances that matches my query condition:But the previous OQL query is not good enough to return only Object[] instances I wanted. The querybelow will do a better job. Try it.select i from [Ljava.lang.Object; i where i.length == 10&& i[5] != null && classof(i[5]).name == '[Ljava.lang.String;'Watch out the OQL statement syntax. It takes JavaScript expressions only, not SQL expressions.


Chapter - 10'jar' - The JAR File ToolThis chapter provides notes and tutorials on JAR file tool, 'jar'. Topics include Java Archive (JAR) fileforma, 'jar' command options, creating JAR files, managing JAR files with WinZIP, using manifest file,creating executable JAR files.JAR - Java Archive File Format'jar' - JAR File Tool Command and OptionsCreating the First JAR File - hello.jarManaging JAR Files with WinZIPMETA-INF/MANIFEST.MF - JAR Manifest FileAdding META-INF/MANIFEST.MF to JAR FilesUsing JAR Files in Java Class PathsCreating Executable JAR FilesConclusions:• JAR files are ZIP files.• JAR files can have attributes stored in the META-INF/MANIFEST.MF file.• JAR files can be used in Java class paths.• JAR files can be "executable".JAR - Java Archive File FormatJAR (Java Archive): A file format that compresses many files into a single package file. A JAR maycontain additional package attributes and supporting data. It has some interesting features:• It uses the standard ZIP algorithm for compression.• Package attributes and supporting data are stored as files in a special directory called META-INF.The main purpose of a JAR file is to aggregate your .class files, not your .java files, into a single file todistribute them to your customers. A JAR file can be directly included in the class path if you want toaccess those class files in the JAR file. No need to extract those class files into Java class directories.Usually, JAR files are managed by the 'jar' tool provided in the JDK package.But JAR files can also be managed by most ZIP tools, since JAR files are really ZIP files.'jar' - JAR File Tool Command and Options"jar": A command line tool for managing JAR files. "jar" is distributed as part of the Sun JDK package.It has some interesting features:• It can create, update or extract a JAR file.• ZIP compression is optional.


"jar" command syntax:Create jar filejar c[v0M]f jarfile inputfilesjar c[v0]mf manifest jarfile inputfilesUpdate jar filejar u[v0M]f jarfile inputfilesjar u[v0]mf manifest jarfile inputfilesExtract jar filejar x[v]f jarfile [inputfiles]List table of contents of jar filejar t[v]f jarfile [inputfiles]where:• "c" - Creates a new JAR file.• "v" - Generates verbose output to standard output.• "0" - Specifies no compression.• "M" - Specifies no manifest file.• "f" - Specifies the JAR file name.• "m" - Specifies the manifest file name.• "u" - Updates a JAR file.• "x" - Extracts files out of a JAR file.• "t" - Displays the table of contents of a JAR file."jar" command is supported by the file, \j2sdk1.5.0\bin\jar.exe, if you installed JDK as in my previouschapter.Creating the First JAR File - hello.jarTo create my first JAR file, I wrote the following Java file, Hello.java:class Hello {public static void main(String[] a) {System.out.println("Hello world!");}}Here is what I did in a command window to create and extract my first JAR file, hello.jar:C:\herong>javac Hello.javaC:\herong>jar cvf hello.jar Hello.classadded manifestadding: Hello.class(in = 416) (out= 285)(deflated 31%)C:\herong>jar tf hello.jarMETA-INF/META-INF/MANIFEST.MFHello.class>del Hello.classC:\herong>jar xvf hello.jarcreated: META-INF/


extracted: META-INF/MANIFEST.MFextracted: Hello.classC:\herong>dir Hello.class416 Hello.classC:\herong>type meta-inf\manifest.mfManifest-Version: 1.0Created-By: 1.4.2 (Sun Microsystems Inc.)What happened here is that:• My first "jar" command created a new JAR file called hello.jar. "jar" automatically added"manifest".• My second "jar" command displayed what is in hello.jar. As you can see, the first "jar"command actually added a directory called META-INF into the jar file.• My third "jar" command extracted all files out of hello.jar.• My "type" command showed you what was added as "manifest": two package attributes:version and create-by.Managing JAR Files with WinZIPThe JAR specification says that "JAR file is a file format based on the popular ZIP file format". So areJAR files really ZIP files? Let's do some tests to find out.Test 1. Create a JAR file, test.jar, with "jar" command. Rename test.jar to test.zip. Unzip test.zip withWinZIP. You should have no problem to extract all files out of test.zip with WinZIP.Test 2. Create a ZIP file, tutu.zip, with WinZIP. Rename tutu.zip to tutu.jar. Extract files from tutu.jarwith "jar". You should have no problem to extract all files out of tutu.jar with "jar" command.Test 3. Create a password protected ZIP file, secure.zip, with WinZIP. Rename secure.zip to secure.jar.Extract files from secure.jar with "jar". You should get a run time exception like this:C:\herong>jar tf secure.jarjava.io.FileNotFoundException: secure.jar (The system cannot find thefile specified)at java.io.FileInputStream.open(Native Method)at java.io.FileInputStream.(FileInputStream.java:106)at java.io.FileInputStream.(FileInputStream.java:66)at sun.tools.jar.Main.run(Main.java:185)at sun.tools.jar.Main.main(Main.java:904)So JAR files and ZIP files are fully compatible, as long as no encryptions are used on ZIP files.I guess I don't need WinZIP anymore.META-INF/MANIFEST.MF - JAR Manifest File"manifest" in a JAR file is a file named as META-INF/MANIFEST.MF. It contains attributes about theJAR file and its contents.Attributes in "manifest" are recorded as a list of name-value pairs in the form of "name: value\n". The


list is divided into a main section for package-level attributes and multiple sub sections for entry-levelattributes. Note that each attribute must be ended with a new line character.The main section may contain only the package level attributes like:• Manifest-Version• Created-By• Main-Class• Class-Path• Implementation-Vendor• Implementation-URLSub sections are optional. They are used to provide entry-level attributes with one section per entry. Asub sections must be preceded with a blank line and started with a "Name" attribute to associate thissection with a content entry in the JAR file. Example of entry-level attributes are:• Content-Type• Java-BeanAdding META-INF/MANIFEST.MF to JAR FilesThere are two ways to add "manifest" to a JAR file.1. Adding "manifest" through "jar" command line. Store all your manifest attributes in a file. Andspecify this file in the "jar" command line with the "m" option:jar c[v0]mf manifest jarfile inputfilesFor example, I created my own manifest file called manifest.txt with one attribute in it:Main-Class: HelloRemember to press the key at the end of the attribute. This will insert a new line character (\n)to terminate the attribute.Here is how I added my manifest to a JAR file with the "m" option:C:\herong>jar cvmf manifest.txt hello.jar Hello.classadded manifestadding: Hello.class(in = 416) (out= 285)(deflated 31%)C:\herong>jar xvf hello.jarcreated: META-INF/extracted: META-INF/MANIFEST.MFextracted: Hello.classC:\herong>type META-INF\MANIFEST.MFManifest-Version: 1.0Created-By: 1.4.2 (Sun Microsystems Inc.)Main-Class: HelloAs you can see that "jar" command copied the attribute from my manifest file to the end of the autogeneratedMANIFEST.MF file.


2. Adding "manifest" through META-INF/MANIFEST.MF file. Create META-INF/MANIFEST.MF asa text file. Enter all your manifest attributes in this file. And include META-INF/MANIFEST.MF as aninput file to JAR file.For example, I created my own META-INF/MANIFEST.MF with a text editor as:Manifest-Version: 3.3Created-By: Herong YangMain-Class: HelloHere is how I added my manifest to a JAR file with the "M" option:C:\herong>jar cvMf tutu.jar Hello.class META-INFadding: Hello.class(in = 416) (out= 285)(deflated 31%)adding: META-INF/(in = 0) (out= 0)(stored 0%)adding: META-INF/MANIFEST.MF(in = 19) (out= 21)(deflated -10%)C:\herong>jar tf tutu.jarHello.classMETA-INF/META-INF/MANIFEST.MFNote that:• The "M" option stops "jar" to auto-generate the META-INF/MANIFEST.MF file.• When MANIFEST.MF is included as an input file, it was compressed. This is different than theauto-generated version, which was not compressed at all.Using JAR Files in Java Class PathsOne advantage of aggregating individual class files into a JAR file is that other Java tools recognizeJAR files as collections of class files and allow you to use them in the class paths.To test this, I created the following class, TempratureConvertorBean.java:/*** TempratureConvertorBean.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/package herong;public class TempratureConvertorBean {private double celsius = 0.0;private double fahrenheit = 32.0;public double getCelsius() {return celsius;}public void setCelsius(double c) {celsius = c;fahrenheit = 1.8*c + 32.0;}public double getFahrenheit() {return fahrenheit;}public void setFahrenheit(double f) {fahrenheit = f;celsius = (f-32.0)/1.8;}


}public String getInfo() {return new String("My TempraturConvertorBean - Version 1.00");}I did the following to create a JAR file, herong.jar:C:\herong>mkdir clsC:\herong>javac -d cls TempratureConvertorBean.javaC:\herong>jar cvf herong.jar -C cls herongadded manifestadding: herong/(in = 0) (out= 0)(stored 0%)adding: herong/TempratureConvertorBean.class(in = 798) (out= 458)...C:\herong>jar tf herong.jarMETA-INF/META-INF/MANIFEST.MFherong/herong/TempratureConvertorBean.classI also created a testing class, F2C.java:/*** F2C.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/import herong.TempratureConvertorBean;public class F2C {public static void main(String[] arg) {TempratureConvertorBean b = new TempratureConvertorBean();double f = 0.0;if (arg.length>0) f = Double.parseDouble(arg[0]);b.setFahrenheit(f);double c = b.getCelsius();System.out.println("Fahrenheit = "+f);System.out.println("Celsius = "+c);System.out.println(b.getInfo());}}Here is what I did to test using JAR files in a class path:C:\herong>javac -classpath herong.jar F2C.javaC:\herong>java -cp .;herong.jar F2C 70.0Fahrenheit = 70.0Celsius = 21.11111111111111My TempraturConvertorBean - Version 1.00This is nice. Right? I can take herong.jar to anywhere on any system. Just add it to "-classpath" for"javac" command, and "-cp" for "java" command.Creating Executable JAR FilesJAR files can be used to distribute supporting classes. They can also be used to distribute main classes


for stand-alone applications.If you put a stand-alone application into a JAR file, you could make it executable by adding the "Main-Class" attribute to the manifest file.Here is what I did to add my F2C class to herong.jar and make it executable.First I created a manifest file, fs_f2c.txt:Main-Class: F2CThen I added F2C class to herong.jar:C:\herong>javac -classpath herong.jar F2C.javaC:\herong>jar uvmf fs_f2c.txt herong.jar F2C.classupdated manifestadding: F2C.class(in = 919) (out= 551)(deflated 40%)C:\herong>jar tf herong.jarMETA-INF/META-INF/MANIFEST.MFherong/herong/TempratureConvertorBean.classF2C.classNow herong.jar contains a small stand-alone application. But how to execute this JAR file? That's easy.You can run a JAR file with the "java -jar" command like this:C:\herong>java -jar herong.jar 60.0Fahrenheit = 60.0Celsius = 15.555555555555555My TempraturConvertorBean - Version 1.00Cool. Right? But you can make it even better. You can register JAR files to be automatically opened bythe "java -jar" command on Windows system to make JAR files "truly" executable. Here is what I didto make this happen.Warning: this following tutorial modifies Windows registry database. Please do not follow it if youdon't have enough knowledge about Windows system.1. Go to Start > Run. And enter "regedit" followed by clicking OK. Registry Editor window shows up.2. Go to [HKEY_CLASSES_ROOT\jarfile\shell\open\command]. You should see the current value likethis: ("C:\Program Files\Java\j2re1.4.2\bin\javaw.exe" -jar "%1" %*). This was added when you installJDK on your system.3. Double click this value and change it to: ("C:\Program Files\Java\j2re1.4.2\bin\java.exe" -jar "%1"%*).4. Open a command window and try this:C:\herong>herong.jar 50Fahrenheit = 50.0Celsius = 10.0My TempraturConvertorBean - Version 1.00


Better. Right? You can run any JAR files by just typing their file names now.You can also double click any JAR files on Window Explorer now. Try it and see what happens.


Chapter - 11'javap' - The Java Class File DisassemblerThis chapter provides tutorial notes on 'javap', the Java class file disassember. Topics include list of'javap' command options, showing public variables and methods, showing private variables andmethods, disassembling bytecode to JVM assembler code.'javap' - Java Disassembler Command and OptionsListing Public Variables and Methods with 'javap'Listing Private Variables and Methods with 'javap -private'Disassembling Java Bytecode Class Files with 'javap -c -private'Looking Up Method Signature with 'javap' Command'javap' - Java Disassembler Command and Options"javap": A command line tool that reads Java bytecode class files and disassembles them. "javap" isdistributed as part of the Sun JDK package and represented by the \j2sdk1.5.0\bin\javap.exe programfile. It has the following syntax:javap [options] classnameswhere "options" is a list of options and "classnames" is a list of Java classe names.If you want to see the complete list of all options, you can run the "javap" command with the "-help"option:C:\herong>javap -helpUsage: javap ...where options include:-c Disassemble the code-classpath Specify where to find user class files-extdirs Override location of installed extensions-helpPrint this usage message-JPass directly to the runtime system-l Print line number and local variable tables-publicShow only public classes and members-protectedShow protected/public classes and members-packageShow package/protected/public classesand members (default)-privateShow all classes and members-s Print internal type signatures-bootclasspath Override location of class files loadedby the bootstrap class loader-verbosePrint stack size, number of locals and argsfor methods. If verifying, print reasonsListing Public Variables and Methods with 'javap'In order to test the Java disassembler tool, I wrote this simple Java application file, Circle.java:


*** Circle.java* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/*/public class Circle {public String uom = "Centimeter";private int x = 0;private int y = 0;private int r = 1;}public void setRadius(int radius) {r = radius;}public void setCenter(int centerX, int centerY) {x = centerX;y = centerY;}public void printRadius() {System.out.println(r + " " + uom);}public void printArea() {double area = getArea();System.out.println(area + " " + uom + "^2");}private double getArea() {return 3.14159*r*r;}To test "javap", we need to compile this source code file into a bytecode class file, Circle.class:C:\herong>javac Circle.javaC:\herong>dir Circle.*1,153 Circle.class630 Circle.javaNow we can see what "javap" will do for use on this bytecode class file:C:\herong>javap CircleCompiled from "Circle.java"public class Circle extends java.lang.Object{public java.lang.String uom;public Circle();public void setRadius(int);public void setCenter(int, int);public void printRadius();public void printArea();}Very nice. By default, "javap" print a list of all public variables and methods.Listing Private Variables and Methods with 'javap -private'From the previous tutorial, we learned that the default behavior of the "javap" command is to list all


public variables and methods of the specified class.If you want to list both public and private variables and methods, you can use the "javap" commandwith the "-private" option:C:\herong>javap -private CircleCompiled from "Circle.java"public class Circle extends java.lang.Object{public java.lang.String uom;private int x;private int y;private int r;public Circle();public void setRadius(int);public void setCenter(int, int);public void printRadius();public void printArea();private double getArea();}As you can see from the output, all private and public variables and methods are printed by the "javap"command.Disassembling Java Bytecode Class Files with 'javap -c -private'Actually, the main function of "javap" is to disassemble Java bytecodes with the "-c" option. Thedisassembed codes are execution instructions of JVM (Java Virtual Machine).Now, let's try "javap -c -private" with the bytecode compiled from Circle.java source code.C:\herong>javap -private CircleCompiled from "Circle.java"public class Circle extends java.lang.Object{public java.lang.String uom;private int x;private int y;private int r;public Circle();Code:0: aload_01: invokespecial #1; //Method java/lang/Object."":()V4: aload_05: ldc #2; //String Centimeter7: putfield #3; //Field uom:Ljava/lang/String;10: aload_011: iconst_012: putfield #4; //Field x:I15: aload_016: iconst_017: putfield #5; //Field y:I20: aload_0


21: iconst_122: putfield #6; //Field r:I25: returnpublic void setRadius(int);Code:0: aload_01: iload_12: putfield #6; //Field r:I5: returnpublic void setCenter(int, int);Code:0: aload_01: iload_12: putfield #4; //Field x:I5: aload_06: iload_27: putfield #5; //Field y:I10: return...private double getArea();Code:0: ldc2_w #18; //double 3.14159d3: aload_04: getfield #6; //Field r:I7: i2d8: dmul9: aload_010: getfield #6; //Field r:I13: i2d14: dmul15: dreturn}Note that:• I used "-c" and "-private" options together to disassemble both private and public methods.• All class level variables are printed out in the disassembled codes as comments like "//Field r:I".• Constants are printed out in the disasembled codes as comments like "//double 3.14159d".• String constants are also printed out in the disasembled codes as comments like "//StringCentimeter". So don't distribute any Java bytecode compiled from source codes that contain anypassword strings. People can easy find the passwords using the "javap" tool.• If you want to understand each statement listed in the disassembled code, you need to read theJVM Specification first.Looking Up Method Signature with 'javap' Command"javap" can also be used as a handy tool to look up method signatures while you are writing Javaprograms.For example, if you are coding a Java program, and you need to convert a byte array into a characterstring, but you don't remember which method in the String class to use, and how many arguments are


needed for that method. If you are using a good Java IDE, it will help you with a list of public methodsand their signatures.But what can you do, if you are using a simple text editor, not a smart Java IDE? You can use the"javap" command as a handy tool to look up method signatures. The following tutorial example showsyou how to find the method to convert a byte array into a character string:C:\herong>javap java.lang.String | find "byte"public java.lang.String(byte[], int, int, int);public java.lang.String(byte[], int);public java.lang.String(byte[], int, int, java.lang.String)throws java.io.UnsupportedEncodingException;public java.lang.String(byte[], java.lang.String)throws java.io.UnsupportedEncodingException;public java.lang.String(byte[], int, int);public java.lang.String(byte[]);public void getBytes(int, int, byte[], int);public byte[] getBytes(java.lang.String)throws java.io.UnsupportedEncodingException;public byte[] getBytes();What can you learn from this tutorial example:• "java.lang.String" is the fully qualified class name for the String class.• The bytecode of "java.lang.String" is inside the JDK JAR file: \j2sdk1.5.0\jre\lib\rt.jar. since"rt.jar" is the default JAR file, you don't need to specify it with the "-classpath" option.• I used the Windows "find" command (similar to the Unix "grep" command) to select methodsignatures that contains the word "byte" to reduce the amount of output lines.• Based on the output, the simplest method is the constructor "String(byte[])", which converts allbytes in the specified byte array into a string using the default character encoding.


Chapter - 12'keytool' - Public Key Certificate ToolThis chapter provides notes and tutorials on the public key certificate management tool, 'keytool'.Topics include introduction of certificates and 'keystore' files, list of 'keytool' commands, generatingprivate and public key pair, importing and exporting certificates.Certificates and Certificate Chains'keystore' - Public Key Certificate Storage FileJDK 1.5 'keytool' - keystore File Management CommandsJDK 1.6 'keytool' - keystore File Management CommandsGenerating Key Pairs and Self-Signed CertificatesExporting and Import CertificatesCloning Certificates with New IdentitiesConclusion:• A key entry in keystore contains a private key and a certificate of the public key.• Certificates can be exported into certificate files out of keystore.• Certificates can be imported from certificate back into keystore.• There seems be to no way to export private keys.• There seems be to no way to generate a certificate of a given public key - signing a public key.Certificates and Certificate ChainsCertificate: A digitally signed statement from the issuer saying that the public key of the subject hassome specific value.The above definition is copied from the JDK 1.3.1 documentation. It has a couple of important terms:• "signed statement" - The certificate must be signed by the issuer with a digital signature.• "issuer" - The person or organization who is issuing this certificate.• "public key" - The public key of a key pair selected by the subject.• "subject" - The person or organization who owns the public key.X.509 Certificate - A certificate written in X.509 standard format. X.509 standard was introduction in1988. It requires a certificate to have the following information:• Version - X.509 standard version number.• Serial Number - A sequence number given to each certificate.• Signature Algorithm Identifier - Name of the algorithm used to sign this certificate by the issuer• Issuer Name - Name of the issuer.• Validity Period - Period during which this certificate is valid.• Subject Name - Name of the owner of the public key.• Subject Public Key Information - The public key and its related information.How can you get a certificate for your own public key?• Requesting it from a Certificate Authority (CA), like VeriSign, Thawte or Entrust.


• Doing it yourself - using tools like JDK "keytool" to generate a self-signed certificate.Certificate Chain: A series of certificates that one certificate signs the public key of the issuer of thenext certificate. Usually the top certificate (the first certificate) is self-signed, where issuer signed itsown public key.'keystore' - Public Key Certificate Storage File"keystore" - A database used by JDK "keytool" command and KeyStore class to store your own privatekeys, and public key certificates you received from someone else. "keystore" supports the followingfeatures:• Two types of entries: key entries for private keys and certificate entries for public keycertificates.• A key entry contains the private key and a certificate chain of the corresponding public key.• Every entry has a unique alias name.• Key entries are protected by separate passwords.• "keystore" may have different implementations from different security package providers. Thedefault implementation from Sun is called JKS (Java KeyStore).JDK 1.5 'keytool' - keystore File Management Commands"keytool" is command line tool introduced in JDK 1.2 to manage keys and certificates using "keystore"."keytool" replaces the same functions offered by "javakey" in JDK 1.1. "keytool" offers a numberfunctions through the following major command options:• "-certreq": Generates a Certificate Signing Request (CSR).• "-delete": Deletes the entry of the specified alias name.• "-export": Exports the certificate of the specified key entry or certificate entry out of thekeystore to a certificate file.• "-genkey": Generates a key pair and stores it as a key entry in the keystore.• "-help": Lists the basic commands and their options.• "-identitydb": Reads the JDK 1.1.x-style identity database from the file idb_file, and adds itsentries to the keystore. If no file is given, the identity database is read from stdin. If a keystoredoes not exist, it is created.• "-import": Imports the certificate from a certificate file as a certificate entry into the keystore.• "-keyclone": Creates a new key entry by copying an existing key entry.• "-keypasswd": Changes the password under which the private/secret key identified by alias isprotected, from old_keypass to new_keypass, which must be at least 6 characters long.• "-list": Lists all entries in the keystore.• "-printcert": Prints summary information of a certificate from a certificate file.• "-selfcert": Replaces the certificate in a key entry with a new self-signed certificate.• "-storepasswd": Changes the password used to protect the integrity of the keystore contents. Thenew password is new_storepass, which must be at least 6 characters long..The above list of "keytool" commands are supported by JDK 1.5. See next section for "keytool"


commands supported in JDK 1.6.JDK 1.6 'keytool' - keystore File Management CommandsIn JDK 1.6, the "keytool" has been changed to offer the following set of commands:• "-genkeypair": Same as the old command "-genkey" to generate a key pair (a public key andassociated private key). Wraps the public key into an X.509 v3 self-signed certificate, which isstored as a single-element certificate chain. This certificate chain and the private key are storedin a new keystore entry identified by alias.• "-genseckey": Generates a secret key and stores it in a new KeyStore.SecretKeyEntry identifiedby alias.• "-importcert": Same as the old commnad "-import" to read the certificate or certificate chain(where the latter is supplied in a PKCS#7 formatted reply) from the file cert_file, and stores it inthe keystore entry identified by alias. If no file is given, the certificate or PKCS#7 reply is readfrom stdin.• "-importkeystore": Imports a single entry or all entries from a source keystore to a destinationkeystore. The "-importkeystore" command can also be used to migrate keys from other storageformats like PKCS#12.• "-certreq": Generates a Certificate Signing Request (CSR), using the PKCS#10 format.• "-exportcert": Same as the old commnad "-export" to read (from the keystore) the certificateassociated with alias, and stores it in the file cert_file.• "-list": Prints (to stdout) the contents of the keystore entry identified by alias. If no alias isspecified, the contents of the entire keystore are printed.• "-printcert": Reads the certificate from the file cert_file, and prints its contents in a humanreadableformat. If no file is given, the certificate is read from stdin.• "-storepasswd": Changes the password used to protect the integrity of the keystore contents. Thenew password is new_storepass, which must be at least 6 characters long..• "-keypasswd": Changes the password under which the private/secret key identified by alias isprotected, from old_keypass to new_keypass, which must be at least 6 characters long.• "-delete": Deletes from the keystore the entry identified by alias. The user is prompted for thealias, if no alias is provided at the command line.• "-changealias": Move an existing keystore entry from the specified alias to a new alias,destalias. If no destination alias is provided, the command will prompt for one. If the originalentry is protected with an entry password, the password can be supplied via the "-keypass"option. If no key password is provided, the storepass (if given) will be attempted first. If thatattempt fails, the user will be prompted for a password.• "-help": Lists the basic commands and their options.Generating Key Pairs and Self-Signed CertificatesIn the first example, I want to try the "-genkey" command option using JDK 1.3.1:C:\herong>keytool -genkey -alias my_home -keystore herong.jksEnter keystore password: HerongJKSWhat is your first and last name?[Unknown]: Herong YangWhat is the name of your organizational unit?


[Unknown]: My UnitWhat is the name of your organization?[Unknown]: My HomeWhat is the name of your City or Locality?[Unknown]: My CityWhat is the name of your State or Province?[Unknown]: My StateWhat is the two-letter country code for this unit?[Unknown]: USIs correct?[no]: yesEnter key password for (RETURN if same as keystore password): My1stKeyBased on the documentation, the above example command should do the following for me:• Create a "keystore" file, herong.jks, in JKS format, with password of "HerongJKS".• Generate a pair of private key and public key for me using the default implementation of thedefault security package.• Generate a certificate chain with a single self-signed certificate of my public key.• Insert a key entry into the keystore with my private key and the certificate chain.The following command shows that we do have a key entry in the keystore file:C:\herong>keytool -list -keystore herong.jks -storepass HerongJKSKeystore type: jksKeystore provider: SUNYour keystore contains 1 entry:my_home, Sat Jun 1 07:15:16 EDT 2002, keyEntry,Certificate fingerprint(MD5): BE:D2:AF:4E:A7:44:13:08:16:4C:68:3B:D1:99:79:55Exporting and Import CertificatesIn the second example, I want to export the certificate stored in the key entry to a certificate file, thenimport it back into the keystore as certificate entry:C:\herong>keytool -export -alias my_home -file my_home.crt-keystore herong.jks -storepass HerongJKSCertificate stored in file C:\herong>keytool -printcert -file my_home.crtOwner: CN=Herong Yang, OU=My Unit, O=My Home, L=My City, ST=My Sta...Issuer: CN=Herong Yang, OU=My Unit, O=My Home, L=My City, ST=My St...Serial number: 407928a4Valid from: Sat Jun 1 07:14:44 EDT 2002 until: Sat Aug 31 07:14:44...Certificate fingerprints:MD5: BE:D2:AF:4E:A7:44:13:08:16:4C:68:3B:D1:99:79:55SHA1: AE:67:0C:C5:21:5C:F6:6F:45:33:9E:FB:8E:50:EA:32:32:D1:92:BBC:\herong>keytool -import -alias my_home_crt -file my_home.crt-keystore herong.jks -storepass HerongJKS


Certificate already exists in keystore under alias Do you still want to add it? [no]: yesCertificate was added to keystoreC:\herong>keytool -list -keystore herong.jks -storepass HerongJKSKeystore type: jksKeystore provider: SUNYour keystore contains 2 entries:my_home_crt, Sat Jun 1 12:25:46 EDT 2004, trustedCertEntry,Certificate fingerprint (MD5): BE:D2:AF:4E:A7:44:13:08:16:4C:68:3B...my_home, Sat Jun 1 07:15:16 EDT 2002, keyEntry,Certificate fingerprint (MD5): BE:D2:AF:4E:A7:44:13:08:16:4C:68:3B...Looking good so far:• The "-export" command option exports the self-signed certificate of my public key into a file,my_home.crt.• The "-printcert" command option prints out summary information of a certificate stored in a filein X.509 format. As you can see from the print out, I am the issuer and the owner of thiscertificate.• The "-import" command option imports the certificate from the certificate file back into thekeystore under different alias, my_home_crt.Certificates can also be exported in a printable format: based on RFC 1421 specification, using theBASE64 encoding algorithm.C:\herong>keytool -export -alias my_home_crt -file my_home.rfc -rfc-keystore herong.jks -storepass HerongJKSCertificate stored in file type my_home.rfc-----BEGIN CERTIFICATE-----MIIDDTCCAssCBEB5KKQwCwYHKoZIzjgEAwUAMGwxCzAJBgNVBAYTAlVTMREwDwYDVQ...dGF0ZTEQMA4GA1UEBxMHTXkgQ2l0eTEQMA4GA1UEChMHTXkgSG9tZTEQMA4GA1UECx...dDEUMBIGA1UEAxMLSGVyb25nIFlhbmcwHhcNMDQwNDExMTExNDQ0WhcNMDQwNzEwMT...MQswCQYDVQQGEwJVUzERMA8GA1UECBMITXkgU3RhdGUxEDAOBgNVBAcTB015IENpdH...BAoTB015IEhvbWUxEDAOBgNVBAsTB015IFVuaXQxFDASBgNVBAMTC0hlcm9uZyBZYW...ASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2US...WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1...+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCou...gYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgL...FhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkI...BpKLZl6Ae1UlZAFMO/7PSSoDgYUAAoGBAJdQsMlIf1nh4T/HZvVeltsrTGED118CkG...ygy53OLwrSK+6ptJpXP8tPMn9YFVJ3eigJrMTaZvGyd40WRiYM6Woyj3T4H73LEKLD...QeNYOAm8cp3l9ZQkNnmIA1P6CRR43EeAmdTUlK8y6RWTsrOiJMdDMAsGByqGSM44BA...AhQ4zAUOPWe1wdiwye9XDsVPcKS1xwIUWTdok6RIeeCMRIytKwcTOo7/qpM=-----END CERTIFICATE-----Cloning Certificates with New IdentitiesIn the third example, I want to create a new key entry with the same key pair of an existing key entry,


ut change the identity information:C:\herong>keytool -keyclone -alias my_home -dest my_copy -keypass My1stKey-new My2ndKey -keystore herong.jks -storepass HerongJKSC:\herong>keytool -selfcert -alias my_copy -keypass My2ndKey-dname "cn=Herong Yang, ou=My Unit 2, o=My Organization 2, c=US"-keystore herong.jks -storepass HerongJKSC:\herong>keytool -export -alias my_copy -file my_copy.crt-keystore herong.jks -storepass HerongJKSCertificate stored in file C:\herong>keytool -printcert -file my_copy.crtOwner: CN=Herong Yang, OU=My Unit 2, O=My Organization 2, C=USIssuer: CN=Herong Yang, OU=My Unit 2, O=My Organization 2, C=USSerial number: 40798b4fValid from: Sat Jun 1 14:15:43 EDT 2002 until: Sat Aug 31 14:15:43...Certificate fingerprints:MD5: 4A:E4:D9:BC:E9:8C:50:27:6C:00:59:76:D1:14:05:79SHA1: FA:F5:30:78:22:3B:52:28:0D:41:24:0B:CA:CC:6F:D4:0E:...


Chapter -12native2ascii' - Native-to-ASCII Encoding Converter 'This chapter provides tutorial notes on the native-to-ASCII encoding converter 'native2ascii'. Topicsinclude 'native2ascii' command options, default encoding CP1252 used by 'javac', converting UTF-8characters into \udddd Unicode code sequences, converting \udddd sequences back to native encodings.'native2ascii' - Encoding Converter Command and Options'javac' Using CP1252 to Process Source FileUTF-8 to \udddd Conversion with 'native2ascii -encoding'Setting UTF-8 Encoding in PrintStreamConverting \udddd Sequences Back with "-reverse" Option'native2ascii' - Encoding Converter Command and Options"native2ascii": A command line tool that reads a text file stored in a non-ASCII encoding and convertsit to an ASCII text file. All non-ASCII characters will be converted into \udddd sequences, where ddddis the Unicode code value of the non-ASCII character."native2ascii" is an important Java tool, because Java compiler and other Java tools can only processfiles which contain ASCII characters and \udddd Unicode code sequences. If you have any non-ASCIIcharacter strings written in a native encoding included in your Java source code, you need to run this"native2ascii" tool to convert your Java source code."native2ascii" has the following command syntax:native2ascii [options] inputfile outputfilewhere "options" is a list of these options:• "-encoding encoding_name" - Specify the encoding name which is used by the conversionprocedure. The "encoding_name" string must be one of those supported encodings in theSupported Encodings document. "encoding_name" example: utf-8.• "-reverse" - Perform the reverse operation: convert a file with \udddd Unicode code sequencesto one with native-encoded characters.'javac' Using CP1252 to Process Source FileIn order to test the "native2ascii" tool, I wrote the following Java source code file: HelloUtf8.javapublic class HelloUtf8 {public static void main(String[] a) {System.out.println("Hello world!");System.out.println(" 世 界 你 好 !");}}"HelloUtf8.java" contains a string of Chinese characters written in UTF-8 encoding. When I tried to


compile it, I got the following warning:C:\herong>javac HelloUtf8.javaHelloUTF8.java:4: warning: unmappable character for encoding Cp1252System.out.println("S+ tS+ s +n+?");^1 warningThe compiler used "Cp1252" as the default encoding to process the source file, HelloUtf8.java. The lastcharacter of my Chinese string encoded in UTF-8 can not be mapped to any CP1252 character. But thecompiler did finish the compilation. The output HelloUtf8.class can still be executed in JVM:C:\herong>java HelloUtf8Hello world!S+ tS+ s +n+?But the last character was compiled as a question mark "?" character. To fix this problem, you need touse the "native2ascii" tool - see the next section.UTF-8 to \udddd Conversion with 'native2ascii -encoding'Now let's see how we can fix the encoding problem with HelloUtf8.java demonstrated in the previoussection.1. Convert HelloUtf8.java to \udddd Unicode code sequences using the "native2ascii -encoding utf-8"command:C:\herong>native2ascii -encoding utf-8HelloUtf8.java HelloUtf8Converted.java2. Rename the class name in HelloUtf8Converted.java with an editor:public class HelloUtf8Converted {public static void main(String[] a) {System.out.println("Hello world!");System.out.println("\u4e16\u754c\u4f60\u597d\uff01");}}3. Compile and run HelloUtf8Converted.java:C:\herong>javac HelloUtf8Converted.javaC:\herong>java HelloUtf8ConvertedHello world!?????What happens to the Chinese string printed on the console? Why I am not getting Chinese charactersback in the output?The problem is not caused by those \udddd Unicode code sequences used to represent the Chinesestring. Those \udddd Unicode code sequences correctly inserted Chinese characters into the storage of astring variable. The problem is caused by the default encoding used by the "out" stream. See the next


section on how to fix this problem.Setting UTF-8 Encoding in PrintStreamIn order to print non-ASCII characters stored in Java strings, you need to set the correct encoding in thePrintStream object.Here is how I fixed the problem you saw in the previous section:import java.io.*;public class HelloUtf8ConvertedFixed {public static void main(String[] a) {try {PrintStream out =new PrintStream("\\herong\\Hello.txt", "UTF-8");System.setOut(out);System.out.println("Hello world!");System.out.println("\u4e16\u754c\u4f60\u597d\uff01");} catch (Exception e) {}}}Check the output of this program:C:\herong>javac HelloUtf8ConvertedFixed.javaC:\herong>java HelloUtf8ConvertedFixedC:\herong>type Hello.txtHello world!世 界 你 好 !Excellent! This final program shows how Chinese characters can be correctly encoded in the Javasource file, and correctly printed in the output file.Converting \udddd Sequences Back with "-reverse" Option"native2ascii" also offers the "-reverse" option to help you convert text files with any \udddd Unicodecode sequences back to any native encodings, like UTF-8, or GB2312.The tutorial example below shows you how I converted some Chinese characters in a UTF-8 file to\udddd Unicode code sequences, then back to a GB2312 encoded file:C:\herong>type HelloUtf8.javapublic class HelloUtf8 {public static void main(String[] a) {System.out.println("Hello world!");System.out.println(" 世 界 你 好 !");}}C:\herong>native2ascii -encoding utf-8HelloUtf8.java HelloUtf8.unicode


C:\herong>type HelloUtf8.unicodepublic class HelloUtf8 {public static void main(String[] a) {System.out.println("Hello world!");System.out.println("\u4e16\u754c\u4f60\u597d\uff01");}}C:\herong>native2ascii -encoding gb2312 -reverseHelloUtf8.unicode HelloUtf8.gb2312C:\herong>type HelloUtf8.gb2312public class HelloUtf8 {public static void main(String[] a) {System.out.println("Hello world!");System.out.println("-++t-p¦+úí");}}As you can see, if you use "native2ascii" and "native2ascii -reverse" together, you can convert any non-ASCII file from one encoding to another encoding.Monitor and diagnose performance in Java SE 6Summary: Java Platform, Standard Edition 6 (Java SE) focuses on performance, with expandedtools for managing and monitoring applications as well as diagnosing common problems. This articleoutlines the basis of monitoring and management in the Java SE platform and provides detailedinformation about the relevant enhancements in Java SE 6.Java SE 6 provides an in-depth focus on performance, offering expanded tools for managing andmonitoring applications and for diagnosing common problems. The improvements include:• Monitoring and management API enhancements• Official support for an improved graphical monitoring tool called JConsole• Enhanced instrumentation of the Java virtual machine (JVM)This article outlines the basis of monitoring and management in the Java SE platform and providesdetailed information about the performance monitoring and management enhancements in the latestrelease. It also describes the diagnostic and troubleshooting tools available in the Java SE 6 platform.To benefit from this article, you should have a strong understanding of the monitoring and managementfunctionality introduced in previous Java SE releases. See Resources for detailed backgroundinformation.Monitoring and management APIThe java.lang.management package introduced in Java SE 5 defines nine MBeans calledplatform MBeans, or MXBeans (see Resources). Each MXBean encapsulates a single functional area ofthe JVM. Beginning with Java SE 5, the JVM has included a built-in MBean server called the platform


MBean server. MBeans reside in and are managed by this repository. Table 1 outlines the nineMXBeans in the Java platform:Table 1. Platform MBeansManagement interfaceResource managedClassLoadingMXBeanClass loaderCompilationMXBeanCompilerMemoryMXBeanMemoryThreadMXBeanThreadsRuntimeMXBeanRuntimeOperatingSystemMXBeanOperating systemGarbageCollectorMXBean Garbage collectorMemoryManagerMXBeanMemory managerMemoryPoolMXBeanMemory poolAny application can obtain and use the JVM-provided platform MBeans by obtaining an instance of thedesired bean and invoking the appropriate methods. MXBeans can be used to monitor the behavior ofboth local and remote JVMs and retrieve information about them.Platform MBeans provide access to information such as the number of classes loaded, uptime of theJVM, the amount of memory consumed, and the number of threads running, as well as statistics aboutthread contention.You can monitor and manage the JVM resources in one of two ways:• Direct access to the MXBean interface• Indirect access using the MBeanServer interfaceDirect access using the MXBean interfaceYou can retrieve an MXBean instance from a static factory method that gives you direct access to thelocally running JVM's MXBean interface. The ManagementFactory class provides the staticfactory methods for obtaining the MXBeans. The example in Listing 1 demonstrates how to retrieve theRuntimeMXBean using this factory and get the value of one of its standard attributes: VmVendor:Listing 1. Direct access to MXBeanRuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();// Get the standard attribute "VmVendor"String vendor = mxbean.getVmVendor();Indirect access using the MBeanServer interfaceThe platform MBeanServer interface uses MXBeanServerConnection to allow you to connectto remote JVMs and access MXBeans running on those platforms. You can use theManagementFactory class's getPlatformMBeanServer method to access the platformMBean server. Listing 2 demonstrates how to get the RuntimeMXBean running in a remote JVM andget the value of its VmVendor attribute:


Listing 2. Indirect access to MXBeanMBeanServerConnection serverConn;try {//connect to a remote VM using JMX RMIJMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://");JMXConnector jmxConnector = JMXConnectorFactory.connect(url);serverConn = jmxConnector.getMBeanServerConnection();ObjectName objName = newObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);// Get standard attribute "VmVendor"String vendor =(String) serverConn.getAttribute(objName, "VmVendor");} catch (...) { }See Resources for more detailed information on MXBeans and the java.lang.management API.API enhancements in Java SE 6Java SE 5 introduced the java.util.concurrent.locks package, which provides a frameworkfor lock and wait conditions. This framework is distinct from Java's built-in synchronization supportand allows greater flexibility in the use of locks.Java SE 6 adds support for java.util.concurrent.locks in the java.lang.managementpackage. This includes new classes that provide information about locks, as well as enhancements tothe ThreadInfo, ThreadMXBean, and OperatingSystemMXBean interfaces.Java SE 6 introduces two new classes:• LockInfo contains information about a lock.• MonitorInfo extends LockInfo and contains information about an object-monitor lock.The ThreadInfo class makes use of these new objects with the introduction of three new methods:• getLockInfo() returns the LockInfo object for which the given thread is blockedwaiting.• getLockedMonitors() returns the MonitorInfo objects that are currently locked by thegiven thread.• getLockedSynchronizers() returns the LockInfo objects, representing ownablesynchronizers that are currently locked by the given thread.In Java SE 5, the ThreadMXBean.getThreadInfo methods report only an object monitor that athread is waiting to acquire or is blocked from entering. In Java SE 6, these methods are enhanced toreport the AbstractOwnableSynchronizer that a thread is waiting to acquire.Four new methods have been added to the ThreadMXBean interface:• isObjectMonitorUsageSupported() tests if the virtual machine supports monitoring


the usage of object monitors.• isSynchronizerUsageSupported() tests if the virtual machine supports monitoringthe usage of ownable synchronizers.• findDeadlockedThreads() returns an array of thread IDs that are deadlocked. Threadsthat are deadlocked are blocking one another from entering an object monitor or synchronizer.• dumpAllThreads() returns stack-trace and synchronization information for all live threads.Finally, the OperatingSystemMXBean interface was updated to include thegetSystemLoadAverage() method, which returns the system load average for the past minute.In addition to this programmatic support, Java SE 6 also includes several diagnostic andtroubleshooting tools that can be used to detect problems and monitor usage of JVM resources. Thenext two sections describe and demonstrate some of the available diagnostic tools.Java Monitoring and Management Console (JConsole)Java SE 6 includes official support for JConsole, a monitoring and management console introduced inJava SE 5. JConsole lets you monitor various JVM resource statistics during run time. It's particularlyuseful for detecting symptoms of deadlocks, lock contention, memory leaks, and cycling threads. It canconnect to a local or remote JVM and can be used to monitor:• Thread state (including associated locks)• Memory usage• Garbage collection• Runtime information• JVM informationThe following subsections describe the enhancements made to JConsole in Java SE 6. See Resourcesfor more information on how to start and use JConsole.Attach API supportBeginning in Java SE 6, JConsole implements the new Attach API. This API consists of two packages— com.sun.tools.attach and com.sun.tools.attach.spi — that let implementingapplications dynamically attach to a target virtual machine and run their agents within that JVM.In the past, applications that you wanted to monitor with JConsole needed to be started with the-Dcom.sun.management.jmxremote option; applications no longer need to start with thisoption. Support for dynamic attachment makes JConsole capable of monitoring any application thatsupports the Attach API. Compliant applications are automatically detected when JConsole starts up.Enhanced UI and MBean presentationIn Java SE 6, JConsole has been updated to have a look and feel similar to the Windows® operatingsystem or GNOME desktop, depending on which platform it's running on. The screenshots shownthroughout the rest of this article were taken on Windows XP and show the UI features that havechanged from the previous release.Once started and associated with an application, the JConsole view consists of six tabs, eachrepresenting a different JVM resource or set of resources:• Overview• Memory


• Threads• Classes• VM Summary• MBeansThe Overview tab displays correlated information about memory usage, threads, classes, and CPUusage in a graphical format. The Overview tab displays a set of related information on one page thatwas available previously only by switching among multiple tabs. Figure 1 shows the Overview tab fora sample application:Figure 1. JConsole Overview tab


The Overview tab displays four graphs of VM resource-usage information as well as a pick list foraltering the time range for which you would like to see results. The first graph, Heap Memory Usage,displays the amount of heap memory that has been used in megabytes over time. This graph is useful indetecting memory leaks. If a memory leak is present in your application, the heap memory usagesteadily increases over time.The Threads graph plots the number of live threads over time, and the Classes graph depicts thenumber of classes loaded. The CPU Usage chart depicts the percentage of the CPU your applicationuses at various points in its life cycle.The VM Summary tab, shown in Figure 2, is another new addition to the Java SE 6 release. It providesdetailed information about the JVM, including total uptime, threading information, classes loaded,memory statistics, garbage collection, and operating-system information.Figure 2. JConsole VM Summary tab


The MBeans tab has been improved to allow for easier access to your MBeans' operations andattributes. It displays information about all MBeans registered with the platform. All platform MBeansare accessible through this tab. The tree structure along the left-hand side displays all currently runningMBeans. When you select an MBean, its MBeanInfo and descriptor are displayed on the table to theright, as shown in Figure 3:Figure 3. JConsole MBean tabSelecting the Attributes node displays all the MBean's attributes, as shown in Figure 4 for theThreading MBean:Figure 4. MBean attributes


Note that the attributes and their values shown in the box to the right map to the attribute valuesattainable through the ThreadMXBean API in the java.lang.management package previouslydescribed. You can obtain additional information about a listed attribute by double-clicking on theattribute value. Only attribute values shown in bold can be expanded. For example, double-clicking onthe AllThreadIds value displays the thread IDs of all 22 threads, as shown in Figure 5:Figure 5. Expanded attribute value


Writeable attributes are displayed in blue and you can edit them by clicking on them and entering thenew value. For example, the ThreadContentionMonitoringAvailable attribute shown inFigure 5 can be edited in this manner from the JConsole view.Selecting the Operations node in the left-hand tree structure displays the operations associated with thatMBean. The MBean operations appear as buttons in the right-side display and, when clicked on, invokethe specified method. Figure 6 shows the operations available for ThreadMXBean:Figure 6. MBean operations


The HotSpot Diagnostic MBeanIn Java SE 6, JConsole includes support for the HotSpot Diagnostic MBean. This MBean wasintroduced in this release to allow you to perform on-the-spot diagnostic operations. Its API lets usersperform a heap dump and set other VM options during run time. You can access the HotSpotDiagnostic MBean from the MBean tab by expanding the com.sun.management node andselecting HotSpotDiagnostic. Methods available from the HotSpot Diagnostic MBean are shownin Figure 7:Figure 7. HotSpot Diagnostic MBean


JConsole plug-in supportBeginning in Java SE 6, JConsole includes plug-in support that allows you to build your own plug-insto run with JConsole. For example, you can add a custom tab to the JConsole main view for accessingapplication-specific MBeans and for performing your own monitoring activities.You must extend the abstract com.sun.tools.jconsole.JConsolePlugin class to create acustom JConsole plug-in. You implement two methods for a plug-in to appear properly in the JConsoleview:• newSwingWorker() returns a SwingWorker object that performs the GUI updates foryour plug-in.• getTabs() returns a map of tabs to be added to the JConsole window.JConsole uses its service-provider mechanism to detect and load all plug-in classes. For this reason,you must provide your plug-in class in a JAR file containing a file named META-INF/services/com.sun.tools.jconsole.JConsolePlugin. This file should contain a list of the fullyqualified plug-in class names, one per line. To load the new plug-ins into the JConsole view, runJConsole from the command line with the command:jconsole -pluginpath plugin_pathIn this command, plugin_path refers to the paths to the directory or archive of JConsole plug-ins. You


can specify multiple paths.Java SE 6 comes equipped with a sample JConsole plug-in called JTop. JTop shows the CPU usage ofthe threads running within the current application. To run JConsole with the JTop, execute thecommand:jconsole -pluginpath JAVA_HOME/demo/management/JTop/JTop.jarFigure 8 shows an instance on JConsole with the JTop tab selected. The left-hand column displays thenames of all running threads. For each thread, the CPU usage and thread state are displayed. This viewrefreshes automatically as statistics change. The JTop plug-in is useful for identifying threads with highCPU consumption.Figure 8. JConsole JTop plug-inBack to topMonitoring and troubleshooting toolsIn addition to JConsole, Java SE 6 includes support for a number of other command-line tools. Thesediagnostic tools can attach to any application without requiring that application to start in a specialmode. They enable you to obtain more information about an application to determine if it is behavingas you expect. Note that these tools are listed as experimental and might not be fully supported infuture Java SE releases.Monitoring toolsJava SE 6 includes three command-line utilities, listed in Table 2, that are useful for monitoring JVMperformance statistics:


Table 2. Monitoring toolsToolDescriptionjpsJVM process status tooljstat JVM statistics monitoring tooljstatd JVM jstat daemonThe jps utility lists the virtual machines for the current user on the target system. The utility is usefulin environments where the VM is started using the JNI Invocation API rather than the standard Javalauncher. In these environments, it is not always easy to recognize the Java processes in the process list.The jps tool alleviates this problem.The following example demonstrates the use of the jps utility. Simply enter jps on the commandline, and the utility lists the virtual machines and process IDs for which the user has access rights, asshown in the example in Listing 3:Listing 3. Using the jps utility$ jps16217 MyApplication16342 jpsThe jstat utility uses the JVM's built-in instrumentation to provide information on performance andresource consumption of running applications. The tool is useful for diagnosing performance issues,particularly issues related to heap sizing and garbage collection.The jstatd daemon is a Remote Method Invocation (RMI) server application that monitors thecreation and termination of JVMs and provides an interface to allow remote monitoring tools to attachto JVMs running on the local host. For example, this daemon allows the jps utility to list processes ona remote system.See Resources for additional documentation and usage examples for each of these tools.Troubleshooting toolsJava SE 6 also includes a number of troubleshooting tools, listed in Table 3, that can help you pinpointportions of your application that are behaving unexpectedly:Table 3. Troubleshooting toolsToolDescriptionjinfoConfiguration informationjhatHeap dump browserjmapMemory mapjsadebugd Serviceability agent debug daemonjstack Stack traceThe jinfo command-line utility retrieves configuration information from a running Java process orcrash dump and prints the system properties or the command-line flags that were used to start thevirtual machine.The jhat tool provides a convenient means to browse the object topology in a heap snapshot. Thistool, introduced in Java SE 6 release to replace the Heap Analysis Tool (HAT), is useful in detecting


memory leaks.The jmap command-line utility prints memory-related statistics for a running VM or core file. Theutility can also use the jsadebugd daemon to query a process or core file on a remote machine. Thejmap tool is useful in diagnosing excessive use of finalizers, which can result in anOutOfMemoryError.The Serviceability Agent Debug Daemon (jsadebugd) attaches to a Java process or to a core file andacts as a debug server. This utility is currently available only on Solaris OS and Linux®. Remoteclients such as jstack, jmap, and jinfo can attach to this server using Java RMI.The jstack command-line utility attaches to the specified process or core file and prints the stacktraces of all threads that are attached to the virtual machine, including Java threads and VM internalthreads, and optionally native stack frames. The utility also performs deadlock detection. It can use thejsadebugd daemon to query a process or core file on a remote machine. The jstack tool is usefulfor diagnosing deadlocks.See Resources for additional documentation and usage examples for each of these tools.Back to topConclusionThe Java 6 platform delivers several enhancements in VM instrumentation, management APIs, andJDK tools to help you efficiently identify and diagnose performance and memory problems within Javaapplications. This article describes the improvements made to the Java SE monitoring and managingframework and touches on the diagnostic command-line utilities available to developers.Average Java application speed has steadily increased over time. Now, with the Java SE 6 release, Javaperformance is comparable to that of C or C++. In many cases, Java code runs significantly faster. Andyou can use the tools described here to achieve better performance optimization. Give them a try. Weguarantee you'll find places to optimize your application where you never knew you could.

More magazines by this user
Similar magazines