• No results found

Java Tools

N/A
N/A
Protected

Academic year: 2021

Share "Java Tools"

Copied!
105
0
0

Loading.... (view fulltext now)

Full text

(1)

Chapter - 1

Java Tools Terminology

Certificate: A digitally signed statement from the issuer saying that the public key of the subject has

some specific value.

Certificate Chain: A series of certificates that one certificate signs the public key of the issuer of the

next certificate. Usually the top certificate (the first certificate) is self-signed, where issuer signed its own public key.

JAR (Java Archive): A platform-independent file format that aggregates many files into one. Multiple

Java applets and their requisite components (.class files, images and sounds) can be bundled in a JAR file and subsequently downloaded to a browser in a single HTTP transaction, greatly improving the download speed. The JAR format also supports compression, which reduces the file size, further improving the download time. In addition, the applet author can digitally sign individual entries in a JAR 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 package

from Sun.

"java": The Java launcher - A command line tool to launch Java applications. "java" is distributed as

part of the JDK package from Sun.

"javac": The Java compier - A command line tool to compile Java source files. "javac" is distributed as

part of the JDK package from Sun.

"javap": The Java Class File Disassembler - A command line tool that reads Java bytecode class files

and disassembles them.

"jdb": The Java Debugger - A command line tool to debug Java applications. "jdb" is distributed as

part of the JDK package from Sun.

"JDI (Java Debug Interface)": A high level Java API providing information useful for debuggers and

similar 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-user

debugger applications. It includes the following three-layered APIs:

• Java Debug Interface (JDI), a high-level Java programming language interface, including support for remote debugging;

• Java Debug Wire Protocol (JDWP), which defines the format of information and requests transferred 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 the services a Java virtual machine provides for tools, including debugging. JVM TI is new in J2SE 5.0 and replaces JVMDI and JVMPI, both of which are deprecated and will be removed in a future release.

"JVM (Java Virtual Machine)": A software that simulates a central process unit (Virtual Machine) to

run compiled Java code.

"keystore": A database used by JDK "keytool" command and KeyStore class to store your own private

keys, and public key certificates you received from someone else. "keystore" supports the following features.

(2)

"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 a number functions through the following major command options.

native2ascii: Native-to-ASCII Encoding Converter - A command line tool that reads a text file stored

in a non-ASCII encoding and converts it to an ASCII text file. All non-ASCII characters will be converted 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 more

files that have been compressed or stored.

The format was originally designed by Phil Katz for PKZIP. However, many software utilities other than 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 ZIP support (under the name "compressed folders") in later versions of its Windows operating system.

(3)

Chapter - 2

Installing J2SE 1.6.0 on Windows

This chapter provides tutorial notes on installing Java SE (JDK) on your own Windows system to allow you 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 Windows

Testing J2SE 1.6.0 Installation

Downloading and Installing J2SE 1.6.0 on Windows

To learn JDBC, you have to a copy of JDK (Java Development Kit) installed on your machine. The latest version of JDK is JDK 6u2 (Java(TM) SE Development Kit 6 Update 2), which is also called Java SE 6 (Java Standard Edition 6). Here is what I did to download and install JDK 6u2 on my local machine.

• 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 different

download 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 links to 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 the following output, your installation was ok:

C:\>\progra~1\java\jdk1.6.0_02\bin\java -version java 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 Installation

When JDK is installed on your machine, it provides two commands for you to compile and run Java programs.

• "javac class_name.java" - Compiles a Java program stored a file named with the program class name.

• "java -cp . class_name" - Runs a compiled Java program. "-cp ." specifies the current directory as the class path.

(4)

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.java

To execute the program, use the java command:

C:\>\progra~1\java\jdk1.6.0_02\bin\java Hello Hello world!

(5)

Chapter - 3

Installing J2SE 1.5.0 on Windows

Downloading and Installing J2SE 1.5.0 on Windows

Here 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 working directory 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 File Explorer.

5. Follow the instruction on the installation window to finish the installation. Remember to specify the target directory as: \j2sdk1.5.0.

6. Open a command window to try the java command. If you are getting the following output, you know your installation is done correctly:

C:\>\j2sdk1.5.0\bin\java -version java 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 Installation

Now 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:\herong 3. Then compile this program in a command window with the javac command:

C:\>cd \herong

C:\herong> \j2sdk1.5.0\bin\javac Hello.java

3. Finally, execute the program using the java command:

C:\herong>\j2sdk1.5.0\bin\java -cp . Hello Hello world!

(6)

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

(7)

Chapter - 4

'javac' - The Java Program Compiler

This 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 Options Compiling Hello.java - My First Java Program Option '-classpath' - Specifying Class Path Option '-sourcepath' - Specifying Source Path Option '-d' - Specifying Output Directory Two Types of 'import' Statements

'import' Statements Processed by 'javac'

Option "-g" - Controlling Debugging Information Conclusions:

• "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.exe program 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 for compiled type definitions. If "-classpath" is not specified, the current directory will be used as the class path.

• "-sourcepath sourcepath" - Specifies a list of path names where the compiler will search for source type definitions. If "-source" is not specified, the current directory will be used as the source path.

(8)

"-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 or

generates no debugging information at all.

If you run the "javac" command without any options, you will get the quick usage information as shown below:

C:\>\j2sdk1.5.0\bin\javac

Usage: javac <options> <source files> where possible options include:

-g Generate all debugging info -g:none Generate no debugging info

-g:{lines,vars,source} Generate only some debugging info -nowarn Generate no warnings

-verbose Output messages about what the compiler is doing

-deprecation Output source locations where deprecated APIs are used

-classpath <path> Specify where to find user class files -cp <path> Specify where to find user class files -sourcepath <path> Specify where to find input source files -bootclasspath <path> Override location of bootstrap class files -extdirs <dirs> Override location of installed extensions -endorseddirs <dirs> Override location of endorsed standards path -d <directory> Specify where to place generated class files -encoding <encoding> Specify character encoding used by source files

-source <release> Provide source compatibility with specified release

-target <release> Generate class files for specific VM version -version Version information

-help Print a synopsis of standard options -X Print a synopsis of nonstandard options -J<flag> Pass <flag> directly to the runtime system

Compiling Hello.java - My First Java Program

To 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:\herong

Here is what I did in a command window to compile Hello.java with the 'javac' Java compiler tool. The output of the compilation is a Java class file called Hello.class:

C:\>cd \herong

C:\herong>\j2sdk1.5.0\bin\javac Hello.java C:\herong>dir Hello.*

(9)

116 Hello.java

As 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 Path

The most commonly used "javac" option is "-classpath", which specifies a list of path names where the compiler will search for compiled type definitions. If "-classpath" is not specified, the current directory will be used as the class path.

When compiler encounters an unknown type in the source file, it will try to find the type definition by searching 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.java

EchoerTest.java:7: cannot resolve symbol symbol : class Echoer

location: class EchoerTest Echoer 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 for the 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);

(10)

char[] a = r.toCharArray(); int n = a.length;

for (int i=0; i<n/2; i++) { char t = a[i];

a[i] = a[n-1-i]; a[n-i-1] = t; }

res = new String(a); }

public String getRes() { return res;

} }

Then I compiled the Echoer.java and provided Echoer.class to the class path to compile EchoerTest.java:

C:\herong>javac Echoer.java

C:\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 olleH Note that:

• I used "-classpath ." to specify the current directory as the class path for the compiler to search for 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 Path

If you use a new type, and you don't have the class definition of that type, but you have its source definition, you can use the "-sourcepath sourcepath" option to tell compiler to get that source definition.

Let's use the same source files, Echoer.java and EchoerTest.java, to test this:

C:\herong>del Echoer.class C:\herong>del EchoerTest.class

C:\herong>javac -verbose -sourcepath . EchoerTest.java [parsing started EchoerTest.java]

(11)

[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.java]

[parsing started .\Echoer.java] [parsing completed 0ms] [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] [checking Echoer] [loading \j2sdk1.5.0\jre\lib\rt.jar(java/lang/StringBuffer.class)] [wrote .\Echoer.class] [total 230ms] C:\herong>java EchoerTest !dlrow olleH Note that:

• I used "-sourcepath ." to specify the current directory as the source path for the compiler to search for the source definition of "Echoer".

• The compiler loaded .\Echoer.java correctly, when Echoer definition was needed. • The compiler finished EchoerTest compilation first, then continued to compile Echoer.

Option '-d' - Specifying Output Directory

If you are writing a real Java application, you will organize your Java classes into packages. The Java source files must be stored in a directory with the path names match the package names. For example, if a source file, Some.java, is defined in a package name as: "com.herong.util", it must be stored in a directory named as: .\com\herong\util\Some.java.

By default, "javac" will output the class file in the same directory as the source file. But you can change this default behavior by using the "-d" option. It will make "javac" to output the class files into the specified directory.

To test this option, I wrote the following Java source file: PackagedHello.java

/**

* PackagedHello.java

* Copyright (c) 2006 by Dr. Herong Yang, http://www.herongyang.com/ */

package com.herong.util; public class PackagedHello {

public static void main(String[] a) {

System.out.println("Packaged: Hello world!"); }

}

Test 1 - Storing PackagedHello.java in the wrong directory:

C:\herong>dir PackagedHell.* 264 PackagedHello.java

(12)

C:\herong>javac PackagedHello.java C:\herong>dir PackagedHell.*

459 PackagedHello.class 264 PackagedHello.java

C:\herong>java -cp . PackagedHello

Exception in thread "main" java.lang.NoClassDefFoundError: PackagedHello (wrong name: com/herong/util/PackagedHello)

This proves that packaged classes can not be stored in any directory. Test 2 - Storing PackagedHello.java in the right directory:

C:\herong>mkdir .\com

C:\herong>mkdir .\com\herong C:\herong>mkdir .\com\herong\util

C:\herong>copy PackagedHello.java .\com\herong\util C:\herong>del PackagedHell.* C:\herong>javac .\com\herong\util\PackagedHello.java C:\herong>dir .\com\herong\util 459 PackagedHello.class 264 PackagedHello.java C:\herong>java -cp . com.herong.util.PackagedHello Packaged: Hello world!

As you can see, the compiler outputs the class file in the same directory as the source file by default. Test 3 - Outputing PackagedHello.class to a new directory:

C:\herong>mkdir .\cls

C:\herong>javac -d .\cls .\com\herong\util\PackagedHello.java C:\herong>dir .\cls\com\herong\util

459 PackagedHello.class

C:\herong>java -cp .\cls com.herong.util.PackagedHello Packaged: Hello world!

This time, the compiler outputs the class file under a directory path: .\cls.

Two Types of 'import' Statements

Java offers two types of "import" statements:

1. Single Type Import: "import TypeName;" - It loads the definition of a single type immediately from the specified package.

2. On-Demand Type Import: "import PackageName.*;" - It tells JVM to search this package for any missing type.

(13)

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();

} }

(14)

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 .\com

C:\herong>mkdir .\com\herong C:\herong>mkdir .\com\herong\util

C:\herong>copy ClsA.java .\com\herong\util C:\herong>copy ClsB.java .\com\herong\util C:\herong>javac ImportTestA.java

ImportTestA.java:8: cannot access ClsA bad class file: .\ClsA.java

file does not contain class ClsA

Please remove or make sure it appears in the correct subdirectory of the classpath.

ClsA a = new ClsA(); ^

1 error

What's wrong with ImportTestA.java, which uses the "On-demand type import" statement? The answer is 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 ClsA bad class file: .\ClsA.java

file does not contain class ClsA

Please remove or make sure it appears in the correct subdirectory of the classpath.

ClsA a = new ClsA(); ^

[total 230ms] 1 error

C:\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]

(15)

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 its package 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 current directory. "javac" will continue to search for the ClsA in the package specified in "import

com.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 Information

As we see earlier, the "-g" compiler option can be used to control how much debugging information should be generated into the class files. Here are the choices on how to use this option:

Choice Option Information generated in class 1 -g:none No debug information

2 -g:lines Line number only

3 -g:lines,source Line number & source file 4 (default) Same as #3

5 -g:lines,source,vars Line number, source file & variables 6 -g Same as #5

Of course, the more debugging information you generate in a class file, the more debugging power you will get when you debug this class. However, once your source code is fully debugged, you should recompile your code with "-g:none", so that you don't distribute you class file will any debugging information.

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.

(16)

Chapter - 5

'java' - The Java Program Launcher

This chapter describes the Java launch tool 'java'. Topics include listing of 'java' options, specifying class path with '-classpath', specifying an executable JAR file with '-jar', specifying non-standard options with '-X', launching Java programs without the console window.

'java' - Java Launching Command and Options Launching Hello.java - My First Java Program Option "-classpath" - Specifying Class Path Option '-jar' - Specifying Executable JAR Files Option '-X' - Specifying Non-Standard Options 'javaw' - Launching Java Programs without Console Conclusions:

• "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 the specified 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 for compiled type definitions. If "-classpath" is not specified, the current directory will be used as the class path.

(17)

• "-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 shown below:

C:\>\j2sdk1.5.0\bin\java

Usage: 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 <class search path of directories and zip/jar files>

-classpath <class search path of directories and zip/jar files> A ; separated list of directories, JAR archives, and ZIP archives to search for class files. -D<name>=<value>

set a system property -verbose[:class|gc|jni]

enable verbose output

-version print product version and exit -version:<value>

require the specified version to run -showversion print product version and continue

-jre-restrict-search | -jre-no-restrict-search include/exclude user private JREs in the version search

-? -help print this help message

-X print help on non-standard options -ea[:<packagename>...|:<classname>] -enableassertions[:<packagename>...|:<classname>] enable assertions -da[:<packagename>...|:<classname>] -disableassertions[:<packagename>...|:<classname>] disable assertions -esa | -enablesystemassertions

enable system assertions -dsa | -disablesystemassertions

disable system assertions -agentlib:<libname>[=<options>]

load native agent library <libname>, e.g. -agentlib:hprof see also,

-agentlib:jdwp=help and -agentlib:hprof=help -agentpath:<pathname>[=<options>]

load native agent library by full pathname -javaagent:<jarpath>[=<options>]

load Java programming language agent, see java.lang.instrument

Launching Hello.java - My First Java Program

(18)

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.java C:\herong>dir Hello.* 416 Hello.class 116 Hello.java C:\herong>java Hello Hello world!

As you can see, launching a simple Java application is easy - Run the 'java' command without any options.

Option "-classpath" - Specifying Class Path

The most commonly used "java" option is "-classpath", which specifies a list of path names where the launcher will search for compiled type definitions. If "-classpath" is not specified, the current directory will 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<n/2; i++) { char t = a[i];

a[i] = a[n-1-i]; a[n-i-1] = t; }

res = new String(a); }

public String getRes() { return res;

} }

I also wrote the following testing class, EchoerTest.java:

/**

(19)

* 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 echo

C:\herong>copy Echoer.java echo C:\herong>mkdir test

C:\herong>copy EchoerTest.java test C:\herong>cd test

C:\herong>javac -classpath ..\echo EchoerTest.java >java EchoerTest

Exception in thread "main" java.lang.NoClassDefFoundError: Echoer at EchoerTest.main(EchoerTest.java:7)

C:\herong>java -classpath ..\echo EchoerTest

Exception in thread "main" java.lang.NoClassDefFoundError: EchoerTest C:\herong>java -classpath .;..\echo EchoerTest

!dlrow olleH

Note 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 find both "EchoerTest" and "Echoer".

Option '-jar' - Specifying Executable JAR Files

In order to use the "-jar" option, we need to create a JAR file with a "Main-Class" attribute in the manifest 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: Hello

(20)

C:\herong>javac Hello.java

C:\herong>jar -cvmf hello.fs hello.jar Hello.class added manifest

adding: 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.jar Hello 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 be launched.

-Xmsn -Xmxn

where "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.java C:\herong>java ShowMemory Free memory: 1896232 Total memory: 2031616 C:\herong>java -Xms32M -Xmx128M ShowMemory Free memory: 33222440 Total memory: 33357824 C:\herong>java -Xms64M -Xmx128M ShowMemory Free memory: 66514728 Total memory: 66650112

(21)

'javaw' - Launching Java Programs without Console

If you launch a Java application with "java" in a command window, JVM will use that command window as the console. If you launch a Java application with "java" in a different way, "java" will create 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 created this 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 still running?

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 my previous 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, no console 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 and server applications.

(22)

Chapter - 6

'jdb' - The Java Debugger

This chapter provides tutorial notes on the Java debugger 'jdb'. Topics include starting 'jdb' to debug an application, running 'jdb' separately from the application, debugging remote application, debugging multi-thread application, listing and switching execution threads.

'jdb' - Java Debugger Command and Options Starting a Debugging Session with 'jdb'

Debugging Applications with Separate 'jdb' Sessions Debugging Java Applications Remotely

Listing Debugging Commands with 'help' Command PrimeNumberSeeker.java - Multi-Thread Sample Program Starting Debugging Session on a Multi-Thread Application Stepping through Statements of the Child Thread

Checking Variable Values in a Debugging Session

Debugging the Main Thread of a Multi-Thread Application Switching Execution Threads in a Debugging Session Suspending Main Thread to Debug Child Thread Conclusions:

• "jdb" is a nice debugging tool. But it only offers a command line interface, not so easy to use. It is 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 a

command line mode. "javac" is distributed as part of the Sun JDK package. It has the following syntax:

jdb [options] main_class_name jdb [options] -attach <address>

where "options" is a list of options, "main_class_name" is a the name of the main class of a Java application, and "address" is the debugging connection address of a running Java application.

(23)

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 that application.

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 for compiled 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 option

removes the need for using the run command. The target application is launched and then stopped just before the initial application class is loaded. At that point you can set any necessary breakpoints 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 local variables, 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.java C:\herong>jdb Hello

Initializing jdb ... > stop in Hello.main

Deferring breakpoint Hello.main.

It will be set after the class is loaded. > run

run Hello

Set uncaught java.lang.Throwable

Set deferred uncaught java.lang.Throwable >

VM Started: Set deferred breakpoint Hello.main

Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0 3 System.out.println("Hello world!");

main[1] next Hello world!

(24)

>

Step completed: "thread=main", Hello.main(), line=4 bci=8 4 }

main[1] cont >

The application exited

Notice that:

• Once started, "jdb" offers you command prompt to allow you to run debugging commands interactively.

• 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 next

section 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 Task

Manager, 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 Hello Set uncaught java.lang.Throwable

Set deferred uncaught java.lang.Throwable Initializing jdb ...

>

VM Started: No frames on the current call stack main[1] cont

> Hello world!

The application has been disconnected

As we expected, "jdb -launch" command launches the target application immediately, and stops at the beginning of the main() method.

Debugging Applications with Separate 'jdb' Sessions

If 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 Platform Debugger Architecture) technology to give you the following options:

Debugger Target Option jdb java 1 Shared memory client Shared memory server 2 Shared memory server Shared memory client 3 Socket client Socket server 4 Socket server Socket client

The shared memory options requires that the debugger and the target application to be on the same machine. Of course, the socket options allow you to run them remotely.

(25)

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 Hello

Listening for transport dt_shmem at address: MyHello

The target application is launched in "shared memory server" mode. Its execution is suspended. Now open another command window and run:

C:\herong>jdb -attach MyHello Set uncaught java.lang.Throwable

Set deferred uncaught java.lang.Throwable Initializing jdb ...

>

VM Started: No frames on the current call stack main[1] stop in Hello.main

Deferring breakpoint Hello.main.

It will be set after the class is loaded. main[1] cont

> Set deferred breakpoint Hello.main

Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0 3 System.out.println("Hello world!");

main[1] list

1 public class Hello {

2 public static void main(String[] a) { 3 => System.out.println("Hello world!"); 4 }

5 }

main[1] cont >

The application exited

As you can see, the debugger successfully connected to the target application. I used "next" command to let the target application to execute the current statement.

Debugging Java Applications Remotely

As we can see from the previous section, we can run a Java application and the 'jdb' debugger separately in shared memory mode. But this requires that the Java application and the 'jdb' debugger must be running on the same machine.

If you have a large application that you need to run a big server machine, you can debug that

application by running the 'jdb' debugger on your own desktop machine using the socket debugging communication 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 Hello Listening for transport dt_socket at address: 8888

(26)

The target application is launched in "socket server" mode. Its execution is suspended. Now open another command window and run:

C:\herong>jdb -connect com.sun.jdi.SocketAttach:hostname=localhost, port=8888

Set uncaught java.lang.Throwable

Set deferred uncaught java.lang.Throwable Initializing jdb ...

>

VM Started: No frames on the current call stack main[1] stop in Hello.main

Deferring breakpoint Hello.main.

It will be set after the class is loaded. main[1] cont

> Set deferred breakpoint Hello.main

Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0 3 System.out.println("Hello world!");

main[1] quite

Cool. 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:8888

java.io.IOException: shmemBase_attach failed: The system cannot find the file specified

at com.sun.tools.jdi.SharedMemoryTransportService.attach0(... ...

My guess is that the Windows version of "jdb" assumes "shared memory" as the default transport mode.

Listing Debugging Commands with 'help' Command

Ok, I think we did enough excises about launching the debugger and connecting to the target application. 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 debugging prompt.

C:\herong>jdb > run

...

run [class [args]] -- start execution of an application threads [threadgroup] -- list threads

thread <thread id> -- set default thread

suspend [thread id(s)] -- suspend threads (default: all) resume [thread id(s)] -- resume threads (default: all) where [<thread id> | all] -- dump a thread's stack

up [n frames] -- move up a thread's stack down [n frames] -- move down a thread's stack

(27)

kill <thread id> <expr> -- kill a thread with the given exception interrupt <thread id> -- interrupt a thread

print <expr> -- print value of expression dump <expr> -- print all object information

eval <expr> -- evaluate expression (same as print) set <lvalue> = <expr> -- assign new value to a variable locals -- print all local variables classes -- list currently known classes class <class id> -- show details of named class methods <class id> -- list a class's methods fields <class id> -- list a class's fields threadgroups -- list threadgroups

threadgroup <name> -- set current threadgroup stop in <class id>.<method>[(argument_type,...)]

-- set a breakpoint in a method stop at <class id>:<line> -- set a breakpoint at a line clear <class id>.<method>[(argument_type,...)]

-- clear a breakpoint in a method clear <class id>:<line> -- clear a breakpoint at a line clear -- list breakpoints

catch [uncaught|caught|all] <class id>|<class pattern>

-- break when specified exception occurs ignore [uncaught|caught|all] <class id>|<class pattern>

-- cancel 'catch' watch [access|all] <class id>.<field name>

-- watch access/modifications to a field unwatch [access|all] <class id>.<field name>

-- discontinue watching

trace methods [thread] -- trace method entry and exit

untrace methods [thread] -- stop tracing method entry and exit step -- execute current line

step up -- execute until the current method returns stepi -- execute current instruction

next -- step one line (step OVER calls) cont -- continue execution from breakpoint list [line number|method] -- print source code

use (or sourcepath) [source file path]

-- display or change the source path classpath -- print classpath info from target VM monitor <command> -- execute specified command at stop time monitor -- list monitors

unmonitor <monitor#> -- delete a monitor

read <filename> -- read and execute a command file lock <expr> -- print lock info for an object threadlocks [thread id] -- print lock info for a thread

disablegc <expr> -- prevent garbage collection of an object enablegc <expr> -- permit garbage collection of an object !! -- repeat last command

(28)

help (or ?) -- list commands

version -- print version information exit (or quit) -- exit debugger

PrimeNumberSeeker.java - Multi-Thread Sample Program

To help me practice debugging commands, I wrote the following simple multi-thread application, PrimeNumberSeeker.java:

1 /**

2 * PrimeNumberSeeker.java

3 * Copyright (c) 2003 by Dr. Herong Yang, www.herongyang.com 4 */

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<current/2 && isPrime) { 34 isPrime = current % 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 }

(29)

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.java C:\herong>java PrimeNumberSeeker

Period, Current int, # primes 1, 2, 0 2, 12, 5 3, 22, 8 4, 32, 11 5, 42, 13 6, 52, 15 7, 62, 18 8, 72, 20 9, 82, 22 10, 92, 24 11, 102, 26 12, 112, 29 13, 122, 30 ... 53, 521, 98 54, 531, 99 55, 541, 100 56, 541, 100 57, 541, 100 ...

The output seems to be fine. But I want to use "jdb" to exam the calculation and to practice the debugging commands. I will show my debugging session in multiple parts with my comments in sections below.

Starting Debugging Session on a Multi-Thread Application

1. Setting up breakpoints and getting the debugging session going:

C:\herong>jdb PrimeNumberSeeker Initializing jdb ...

> stop in PrimeNumberSeeker.main

Deferring breakpoint PrimeNumberSeeker.main. It will be set after the class is loaded. > run

run PrimeNumberSeeker

Set uncaught java.lang.Throwable

Set deferred uncaught java.lang.Throwable >

(30)

Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=13 13 System.out.println("Period, Current int, # primes"); main[1] stop in PrimeNumberSeeker.run

Set breakpoint PrimeNumberSeeker.run main[1] cont

Period, Current int, # primes 1, 2, 0

>

Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=28 28 primes = new int[ceiling];

Thread-0[1] threads Group system:

(java.lang.ref.Reference$ReferenceHandler)0xe2 Reference Handler (java.lang.ref.Finalizer$FinalizerThread)0xe1 Finalizer (java.lang.Thread)0xe0 Signal Dispatcher Group 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 the sub thread.

• Then I issued the "cont" command. My application continued with the sub thread created stopped 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 inform you 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" shows two threads: "main" (my monitoring thread) and "Thread-0" (my sub thread working on the calculation).

• Thread "Thread-0" status shows "running (at breakpoint)". But the word "running" is referring to 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 is stopped, all other threads are stopped also.

Stepping through Statements of the Child Thread

2. Stepping through statements in the sub thread:

Thread-0[1] where all Signal 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)

(31)

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] next 2, 2, 0 >

Step completed: "thread=Thread-0", PrimeNumberSeeker.run(), line=29 29 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] next 3, 2, 0 > 30 current++; Thread-0[1] next 4, 3, 0 > 31 int j = 2; Thread-0[1] next > 5, 3, 0

32 boolean isPrime = true; Thread-0[1] next

6, 3, 0 >

33 while (j<current/2 && isPrime) { Thread-0[1] list

29 while (count < ceiling) { 30 current++;

31 int j = 2;

32 boolean isPrime = true;

33 => while (j<current/2 && isPrime) { 34 isPrime = current % j > 0; 35 j++;

36 }

37 if (isPrime) { 38 count++; Thread-0[1] print current current = 3

What 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 from line 28 to line 29.

(32)

• The next "where all" command showed me that the main thread went through an entire iteration of 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. At the same time, the main thread went through a couple of iterations, printed some output messages.

• Then I used "print" to check the current value of variable "current". Value 3 is correct.

Checking Variable Values in a Debugging Session

3. Checking local variables:

Thread-0[1] next 7, 3, 0

>

37 if (isPrime) { Thread-0[1] print isPrime isPrime = true Thread-0[1] next 8, 3, 0 > 38 count++; Thread-0[1] next 9, 3, 0 > 39 primes[count-1] = current; Thread-0[1] print count

count = 1 Thread-0[1] next > 10, 3, 1 42 sleep(delay); Thread-0[1] list 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 }

Thread-0[1] print primes[0] primes[0] = 3

What 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

(33)

the "primes" array.

Debugging the Main Thread of a Multi-Thread Application

4. Going back to the main thread:

Thread-0[1] stop at PrimeNumberSeeker:19 Set breakpoint PrimeNumberSeeker:19 Thread-0[1] cont

>

Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 bci=25 19 System.out.println( i+", "+t.current+", "+t.count); main[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] print i

i = 11

main[1] print t.current t.current = 3

main[1] print t.count t.count = 1

What 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 command prompt is changed back to "main[1]".

• Then I used "where all" to check where the execution are stopped in all threads. It is interesting to 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 all correct.

Switching Execution Threads in a Debugging Session

5. Switching threads:

main[1] cont >

Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 bci=25 19 System.out.println( i+", "+t.current+", "+t.count); main[1] print t.current

t.current = 14

main[1] print t.count t.count = 6

main[1] where all ...

(34)

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 280

Thread-0[1] list

Current method is native Thread-0[1] step out 11, 22, 8

>

Step completed: "thread=Thread-0", PrimeNumberSeeker.run(), line=45 45 } Thread-0[1] list 41 try { 42 sleep(delay); 43 } catch (InterruptedException e) { 44 System.out.println("Runner interrupted."); 45 => } 46 } 47 } 48 }

Thread-0[1] print count count = 8

What I have done here:

• I let the main thread executed a full period stopping at line 19 again. Of course, the sub thread execute 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 thread to check local variable there. The manual says to use "thread n", where n is the thread index to change the current thread. But where can I to get the thread index? I tried to search the Web and did not get any clear answer.

• However I got the answer from the output of the threads output. The thread index was listed as a hex number next to the class name. For example, "(PrimeNumberSeeker)0x118" means thread 0x118 = 280.

• So I used "thread 280" to switch to the sub thread as the current thread. Notice that the command 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()" and back to the caller, run().

Suspending Main Thread to Debug Child Thread

(35)

Thread-0[1] stop at PrimeNumberSeeker:39 Set breakpoint PrimeNumberSeeker:39 Thread-0[1] cont

>

Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current;

Thread-0[1] cont >

Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 19 System.out.println( i+", "+t.current+", "+t.count); main[1] cont

> 12, 23, 9

Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current;

Thread-0[1] cont >

Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 19 System.out.println( i+", "+t.current+", "+t.count); main[1] suspend 1

main[1] cont >

Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current;

Thread-0[1] cont >

Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current;

Thread-0[1] cont >

Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current;

Thread-0[1] print current current = 41

Thread-0[1] print count count = 13

What I have done here:

• After check different areas of the code, I wanted to only the break the execution when a new prime 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 same time, 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 to concentrate 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 does have a calculation error. I want to leave it to you to find out.

(36)

Chapter - 7

'jconsole' - Java Monitoring and Management Console

This chapter provides tutorial notes on the Java monitoring and management console, jconsole. Topics include description of JMX technology, list of 'jconsole' command options, turning on JMX agent for local 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 Agent

Conclusions:

• 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 be connected by jconsole.

• jconsole displays monitoring diagrams for heap memory usage, counts on loaded classes, counts on threads, and CPU usages.

JMX Technology and 'jconsole' Tool

"JMX (Java Management Extensions)": A Java standard API for management and monitoring of resources such as applications, devices, services, and the Java virtual machine. The JMX technology was developed through the Java Community Process (JCP) as Java Specification Request (JSR) 3, Java Management Extensions, and JSR 160, JMX Remote API.

JMX has been implemented into JDK 5 now. You can set out-of-the-box JMX monitoring and management properties when you start the JVM to run your Java application. This allows you to use local or remote JMX connectors to monitor your application.

JDK 5 offers a graphical user interface called "jconsole" that uses the JMX technology to monitor your Java application locally or remotely. The picture below shows you how "jconsole" works with your Java application:

(37)

'jconsole' Command Options and Connection Window

"jconsole": A graphical user interface tool that enables you to monitor and manage Java applications and 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 -help

Usage: jconsole [ -interval=n ] [ -notile ] [ -pluginpath <path> ] [ -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 the

plugins

-version Print program version

connection = pid || host:port || JMX URL (service:jmx:<protocol>://...) pid The process id of a target process host A remote host name or IP address

port The port number for the remote connection

-J Specify the input arguments to the Java virtual machine on which jconsole is running

If you run the "jconsole" command without any option in JDK 1.6, you will get the connection window as shown below:

(38)

This connection window allows you to specify the connection information from UI instead of the command line.

'com.sun.management.jmxremote' - JMX Agent for Local Connection

Since JDK 1.5, JMX has been included the Sun JVM. You can turn on the out-of-the-box JMX agent when you launch the JVM to run your application. This enables "jconsole" to connect to the JMX agent to 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 need to 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 of 1000000 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 {

References

Related documents

State change diagram showing the change in state after a command to sell seat 22H is given to a concert object KEY IDEA A Java programmer writes a class by specifying the attributes

The command option “ –C class/ .” tells jar command to search the *.class files on this folder (since our compiling step mentioned “–d class“ for the output location in

 Add a New Java Application Project(Leave the main class option unchecked)  Add a new Swing Frame Form and drag a table control.  Make sure that the Java DB or any database

To enable even easier maintenance of business areas, the Java command line introduces a wildcard option that supports both the % and _ syntax familiar to Oracle Database users.

All Java programs contain the definition of at least one class, and within this class at least one method is defined — the method that first executes when the program begins. The

We will now create a Java class called “HelloWorld” that will have a single main method, and this method will simply print out “Hello World” to the

Attaching subscriptions to a system requires specifying the individual product or subscription to attach, using the --pool option.. The options for the attach command are listed in

We will now create a Java class called “HelloWorld” that will have a single main method, and this method will simply print out “Hello World” to the