# Chapter 13

# The Net and Debug Class Libraries

### CONTENTS

- Introduction to the Net Class Library
  - The ContentHandler Class
  - The DatagramPacket Class
  - The DatagramSocket Class
  - The InetAddress Class
  - Java Socket Handlers
  - Java URL-Related Classes
  - The URL Class
- Introducing the sun.tools.debug Library
  - The DebuggerCallback Interface
  - Methods that Deal with Remote Objects
  - The RemoteStackFrame Class
  - The RemoteStackVariable Class
  - The RemoteDebugger Class
  - The StackFrame Class
- Summary

A discussion of the API for the Internet's premier programming language would not be complete without a look at the class library that makes networking possible-`java.net`. Although `java.net` is the final class library in the original Java API, new class libraries that extend the functionality of the Java programming language are continually being introduced. One such class library is the `sun.tools.debug` library, which was added to give Java built-in debugging support. Whenever you use the Java debugger, you are accessing this library.

## Introduction to the Net Class Library

The Net class library, `java.net`, provides a high-level interface for connections over the Internet or any other kind of TCP/IP network. Using these interfaces makes it possible for a Java application to connect to existing network services, provide its own network services, and even allow for multiuser, network-aware games over the Internet. Whereas these can be quite complicated to program in other languages, the `java.net` package allows the basics of socket connection to be set up in as little as 10 lines of code. That's power!

The following sections describe the classes in the `java.net` package.

### The `ContentHandler` Class

`ContentHandler` is used to read a stream of data that is generated by a network connection and produce an object. The exact content handler called depends on the MIME type of the remote data.

`ContentHandler` should not be called directly. This task is much better performed by `URL.getContent()` or `URLConnection.getContent()`, which simplify the process of reading a stream of data.

### The `DatagramPacket` Class

`DatagramPacket` is used to both send and receive datagram packets. A datagram packet is a segment of data containing packet data, packet length, Internet address, and port. This allows programming at the IP packet level.

`DatagramPacket` methods are used to determine the address, length, and port of the datagram packet, as well as retrieve the data itself. See the online documentation for details.

### The `DatagramSocket` Class

`DatagramSocket` is used for creating UDP-based connections over a network. Services such as Sun's Network File System (NFS) use UDP as the underlying protocol. Java applications can also create and/or use UDP-based network connections by making use of this class. Only the advanced programmer will use this class. See the online documentation for details.

### The `InetAddress` Class

`InetAddress` makes an object of Internet addresses. This makes them able to be manipulated as `String` objects or within other network classes.

Listing 13.1 is an example of using the `InetAddress` class.

> Listing 13.1. An example of class `InetAddress`.

> `/* Notes:
> The main example simply accepts a hostname as an argument and
> prints out the following information.
> Hostname and IP address of system application is running on.
> IP address of hostname
> Additional IP addresses associated with hostname
> (try www.microsoft.com)
> Syntax:
> MyMain <hostname>
> */
> import java.net.*;
> public class MyMain {
> public static void main (String args[]) {
> InetAddress inetAddr, inetAddrs[];
> int i;
> try {
> inetAddr = InetAddress.getLocalHost();
> System.out.println("Local System:");
> System.out.println(" " + inetAddr);
> // print out hostname and IP address of local host
> inetAddr = InetAddress.getByName(args[0]);
> // create an InetAddress object from a given hostname
> System.out.println(inetAddr.getHostName() + ":");
> System.out.println(" " + inetAddr);
> // print out hostname and IP address in inetAddr
> System.out.println("Additional addresses:");
> inetAddrs = InetAddress.getAllByName(args[0]);
> // get all addresses associated with a give hostname
> for (i=1; i < inetAddrs.length; i++) {
> // loop through printing out all addresses
> System.out.println(" " + inetAddrs[i]);
> }
> }
> catch (UnknownHostException e) {
> // handle unknown host exceptions
> System.err.println("ERROR: Hostname cannot be resolved");
> System.err.println(" hostname = " + args[0]);
> }
> }
> }`

### Java Socket Handlers

Java has classes within its `java.net` package to govern the use of sockets. Sockets are a network-specific utility. Those of you who are familiar with UNIX network programming are probably well versed in sockets.

Sockets are network processes that connect two hosts and create a two-way "pathway" to carry data between the server and the client. Sockets communicate on a specific port (but which port is up to the programmer). The application notifies the operating system that it is listening for activity on a certain port. The application then goes into a waiting state until it is requested to wake up due to activity on the port. It is not necessary for it to constantly query the port; the operating system notifies the application when there has been activity. The application then wakes up, completes the connection, and does whatever the programmer told it to do.

Sockets are useful in Java for implementing communication streams between programs. Sockets are the primary method of communication on the Internet. Web pages, file transfers, and electronic mail all communicate with each other using sockets. Because of the Java socket interface, it is easy to create Java applications that can participate in this network connectivity.

Java uses three classes in `java.net` for sockets: `ServerSocket`, `Socket`, and `SocketImpl`. The first two are the classes most likely to be used by a programmer. The last, `SocketImpl`, is generally implemented by the Java-enabled operating system. In other words, most programmers will not have to delve into the inner workings of `SocketImpl`.

#### The `ServerSocket` Class

`ServerSocket` is the socket created for the server side. `ServerSocket` listens for a connection request from a client and accepts the connection for a port on the server side.

Two of the methods associated with `ServerSocket` are `accept` and `close`. `accept` is used to create the socket and attach it to a port on the server end. `close` is used to shut down the connection at the end of its useful life. It is best to manually shut down the socket as opposed to waiting for the Java garbage collector to shut it down.

Listing 13.2 shows the source code for a generic socket server.

> Listing 13.2. A Java-based generic socket server or daemon.

> `/* Notes:
> This example implements a java based generic socket server or daemon.
> It uses a socket to communicate with a socket client It can be used as
> the basis for almost any type of socker server based application. This
> particular example includes logging of the connections accepted and
> will accept a filename as part of the constructor which will be used
> for this logging capability.
> To better demonstrate it's use, a prototype of a POP server has been
> implemented. The POP server does not actually retrieve mail, but
> does accept a connection on port 110 and will respond to a quit
> command.
> The main program simply creates a new JPop object and then executes
> its start method. JPop will then loop waiting for and processing
> connections. MyMain accepts a filename as an command line arguement.
> This is used for logging of the connections.
> Syntax:
> MyMain <logfile name>
> */
> import java.io.*;
> import java.net.*;
> import java.util.*;
> public class MyMain {
> public static void main (String args[]) {
> int i;
> JPop jp; // declare JPop object
> jp = new JPop(args[0]); // create JPop instance
> jp.start(); // starts the JPop daemon
> }
> }
> class Daemon { // declare Daemon class
> public DataInputStream is; // declare input stream variable
> public PrintStream os; // declare output stream variable
> public String remoteHost; // declare variable to hold remote hostname
> Socket s; // declare socket object
> ServerSocket ss; // declare server socket object
> PrintStream lf; // declare printstream object
> String logFile; // declare logfile name variable
> int port; // declare port number variable
> String name; // declare application name variable
> // constructor for class Daemon
> public Daemon(int port, String name, String logFile) {
> this.port = port; // save port number
> this.name = name; // save application name
> this.logFile = logFile; // save logfile name
> try {
> lf = new PrintStream(new FileOutputStream(logFile)); // open logfile
> }
> // handle file not found exceptions
> catch(FileNotFoundException e) {
> System.err.println("ERROR: File not found");
> System.err.println(" File = " + logFile);
> System.exit(5);
> }
> catch(IOException e) {System.exit(6);} // handle IO exceptions
> writeLogEnt("daemon started"); // write daemon started log entry
> }
> void start() { // method to start daemon
> try {
> ss = new ServerSocket(port); // create server socket
> s = ss.accept(); // wait for incoming connection
> // get name of remote host for logging
> remoteHost = (s.getInetAddress()).getHostName();
> // write log entry
> writeLogEnt("connection accepted: port = " + s.getLocalPort() + ",
> Âhost = " + remoteHost);
> // open a data input stream using the socket getInputStream method
> is = new DataInputStream(s.getInputStream());
> // open an output PrintStream using the socket getOutputStream method
> os = new PrintStream(s.getOutputStream());
> }
> catch(IOException e) { // handle exceptions
> System.err.println("ERROR: IOexception(1) encountered");
> this.exit(7);
> }
> }
> void stop() { // declare stop method
> writeLogEnt("daemon stopped"); // log daemon stopped message
> try {
> if (is != null) // test input stream is not null
> is.close(); // explicitly close input stream
> if (os != null) { // test if output stream is not null
> os.flush(); // explicitly flush output stream
> os.close(); // explicitly close output stream
> }
> if (s != null) // test if socket is null
> s.close(); // explicitly close socket
> }
> catch(IOException e) { // handle exceptions
> System.err.println("ERROR: IOexception(2) encountered");
> this.exit(8);
> }
> }
> String date() { // declare method for getting todays date
> Date d = new Date();
> return(d.getMonth()+"/"+d.getDate()+" "+d.getHours()+":
> Â"+d.getMinutes()+":"+d.getSeconds());
> }
> void writeLogEnt(String entry) { // delcare method for writing log entries
> lf.println(date() + " " + name + ": " + entry);
> }
> void exit(int errCode) { // declare common exit method
> // log exit message
> writeLogEnt("daemon exited with error code " + errCode);
> if (s != null) { // test socket is not null
> try {s.close();} // close socket
> catch(IOException e) {
> System.err.println("ERROR: IOexception(3) encountered");
> }
> }
> System.exit(errCode); // exit application
> }
> }
> class JPop { // declare Java POP class
> Daemon d; // declare Daemon object
> public JPop(String logFile) { // constructor for class JPop
> d = new Daemon(110, "JPop", logFile); // create new Daemon instance
> }
> void start() { // declare start method
> int i;
> String resp; // variable to hold response from client
> while (true) { // loop forever handling incoming connections
> d.start(); // start daemon
> // send response to remote host
> write("+OK " + d.remoteHost + " JPOP server ready");
> procConnection(); // process POP connection
> }
> }
> // declare method to process POP connecitons
> public void procConnection() {
> // variable to hold response from client
> String resp;
> String cmd = "";
> // process commands until quit received
> while (! cmd.equalsIgnoreCase("quit")) {
> resp = read(); // read response from client
> // tokenize client response for processing
> StringTokenizer st = new StringTokenizer(resp);
> cmd = st.nextToken(); // get command
> if (cmd.equalsIgnoreCase("quit")) { // test for quit command
> // send server shutdown message to client
> write("+OK " + d.remoteHost + " JPOP server shutdown");
> d.stop(); // stop connection to client
> continue; // go to top of loop
> }
> // send error message to client
> write("-ERR Invalid command; valid commands: QUIT");
> }
> }
> void write(String cmd) { // declare method to write string to client
> d.os.println(cmd); // send string to client
> }
> String read() { // declare method to read string from client
> String resp = "";
> try {resp = d.is.readLine();} // read response from client
> catch(IOException e) { // handle exceptions
> System.err.println("ERROR: read IOException");
> this.exit(10);
> }
> return(resp); // return exit code
> }
> void exit(int errCode) { // declare exit method
> d.stop(); // close connection to client
> System.exit(errCode); // exit application
> }
> }`

When you start this program, on the command line, you must pass the name of the file that you want to log socket messages as an argument. You can do this as follows:

> `java MyMain socket.txt`

In the example, the filename `socket.txt` is the name of the file that will log socket messages. While the program is running, you can test the socket connection and logging. To do this, start your browser and point to the IP address of your local system using port 110. If you are on a network-capable machine such as UNIX or Windows NT, you can use the local loopback IP address of 127.0.0.1 for testing. For example, the URL `http://127.0.0.1:110` could be used to test port 110.

If you are able to start the program and test the socket connection, the text file will have entries similar to the following:

> `daemon started
> connection accepted: port = 110,host = ppp-5.ts-4.dc.idt.net`

#### The `Socket` Class

`Socket` is the class used to create network connections and processes. `Socket` is used in conjunction with `SocketImpl` to implement the actual socket operations. `Socket` and `SocketImpl` are separated so that the implementation can be changed depending on the kind of firewall being used. See Listing 13.3 for an example of using `Socket`.

> Listing 13.3. A `Socket` usage example.

> `/* Notes:
> This example implements a java based version of the Unix "biff" utility.
> It uses a socket to communicate with a POP server to determine if there
> is any mail for the user.
> The main program simply calls the JBiff class methods every 60 seconds
> to determine if there is new mail present on the server or not. It
> accepts three command line arguments specifying the host to connect
> to, the username to use, and the password to use Note that this
> is intended as an example only. Specifying passwords on command
> lines is never recommended. To make this fully functional, a separate
> dialogue box should be implemented to prompt for the password.
> That is beyond the scope of this chapter however.
> Syntax:
> MyMain <hostname> <username> <password>
> Historical note:
> Where does "biff" come from? A program for checking mail was
> written many years ago for Unix systems. The programmer
> decided to simply name it after his or her dog "biff". Many other
> "biff" type programs have been written since then and many
> of these have carried on the historical fun of the "biff"
> name. For this reason, the class implementing the "biff"
> functionality was called jbiff for Java biff. On another
> note, I had thought about naming the class after one
> of our dogs, spot or buffy, but decided that a program that
> was constantly giving out false alarms was not a good idea.
> */
> import java.io.*;
> import java.net.*;
> import java.util.*;
> public class MyMain {
> public static void main (String args[]) {
> int i;
> JBiff jb; // declare jbiff object
> // create jbiff instance
> jb = new JBiff(args[0], args[1], args[2]);
> // loop forever checking mail
> while(true) {
> // check for new mail
> if (jb.chkMail()) {
> // print out have NEW mail message
> System.out.println("You have NEW mail");
> }
> else {
> // print out have mail message
> System.out.println("You have mail");
> }
> try {Thread.sleep(60000);} // sleep for 60 seconds
> catch(InterruptedException e){}; // handle exceptions
> }
> }
> }
> class JBiff {
> Socket s; // declare socket object
> DataInputStream dis; // declare data input stream object
> PrintStream dos; // declare printstream object
> // variables for hostname, username, and password
> String hostname, user, pass;
> int mailBoxCnt; // variable to hold last count of mail messages
> boolean mailBoxFlg = false; // variable to hold status of New mail flag
> // constructor for class jbiff
> public JBiff(String hostname, String user, String pass) {
> mailBoxCnt = 0; // initialize mail message count to zero
> this.hostname = hostname; // save hostname
> this.user = user; // save username
> this.pass = pass; // save password
> }
> // declare method for open socket connection to pop server
> void openMailBox() {
> String resp; // variable to hold response from server
> try {
> // open new socket connection to hostname on port 110
> s = new Socket(hostname, 110);
> // open a data input stream using the socket getInputStream method
> dis = new DataInputStream(s.getInputStream());
> // open an output PrintStream using the socket getOutputStream method
> dos = new PrintStream(s.getOutputStream());
> }
> // handle file not found errors
> catch(UnknownHostException e) {
> System.err.println("ERROR: Host not found");
> System.err.println(" Host = " + hostname);
> System.exit(2);
> }
> catch(IOException e){}; // catch general IO exceptions
> resp = read(); // read first line from pop server
> resp = write("USER " + user); // send username command to pop server
> resp = write("PASS " + pass); // send password command to pop server
> }
> // declare method to check for mail on pop server
> public boolean chkMail() {
> // variable to hold response from server
> String resp;
> // variable to hold current mail message count on server
> int cnt;
> // return code for method
> boolean rcode;
> // call method to open new connection to pop server
> openMailBox();
> // use STAT command to get count of mail messages on server
> resp = write("STAT");
> // tokenize server response for processing
> StringTokenizer st = new StringTokenizer(resp);
> // skip leading OK/ERR token
> st.nextToken();
> // get count of messages on server
> cnt = (new Integer(st.nextToken())).intValue();
> // send QUIT to close connection to pop server
> write("QUIT");
> // if more mail messages since last time, set new mail flag
> if (cnt > mailBoxCnt) {
> mailBoxFlg = true;
> }
> // if fewer mail messages since last time, clear new mail flag
> if (cnt < mailBoxCnt) {
> mailBoxFlg = false;
> }
> mailBoxCnt = cnt; // save number of messages for next comparison
> return(mailBoxFlg); // return status of new mail flag
> }
> String write(String cmd) { // declare method to write string to pop server
> dos.println(cmd); // send string command to pop server
> return(read()); // return string returned from read of pop server
> }
> String read() { // declare method to read string from pop server
> String resp = ""; // initialize response variable
> try {
> resp = dis.readLine(); // read response from pop server
> if (! resp.startsWith("+OK")) { // test for acceptable response
> // report error returned by pop server
> System.err.println("ERROR: err returned by pop server");
> System.err.println(" resp = " + resp);
> System.exit(7);
> }
> }
> catch(IOException e) { // handle exceptions
> System.err.println("ERROR: read socket error");
> System.exit(6);
> }
> return(resp); // return string read from pop server
> }
> }`

Note
If you cannot access your host using the IP address, try the fully qualified domain and hostname, such as `www.tvp.com`.

#### The `SocketImpl` Class

`SocketImpl` is an abstract class, which means the programmer must subclass it to make it work. `SocketImpl` is used in conjunction with `Socket` to successfully adapt to different environments. One of the main reasons this is an abstract class is that the actual socket communications via Java are platform or firewall specific.

`SocketImpl` can be used with either streams or datagrams. It contains methods that can set a boolean as to whether the socket data is in a stream or a datagram.

The class defines other methods that accept, connect, close, and bind sockets to a port. These methods manipulate and control the socket. Of course, because they are part of an abstract class, the programmer must fill in the necessary details like IP address, port, and hostname.

### Java URL-Related Classes

Java has classes in the `java.net` package that allow manipulation and connection to other locations on the Internet. These locations are denoted by a unique Uniform Reference Locator (URL).

The URL is set up to perform certain activities when a connection is made to it, such as loading a Web page or downloading a file. You can include these interfaces in a Java applet or application.

These URL classes are similar to sockets in that they allow easy integration of network applications into a program. URLs are a bit more user-friendly to work with than are sockets.

Note
Many of the examples in Chapter 10, "The `java.lang` and `java.applet` Class Libraries," use URLs to access files. Check out Listing 10.3, which shows a program that reads an audio file based on a URL.

### The `URL` Class

The `URL` class transforms a URL string into an object that can then be manipulated using associated methods. These methods serve purposes such as getting the filename, protocol, and hostname.

`URL` also has methods that can open and maintain the data connection of an input stream. This is much easier to use than the socket classes.

#### The `URLConnection` Class

`URLConnection` is another abstract class used to create and control a connection to a platform- and firewall-specific location. It is a simplified version of connection interface for the `URL` class. See the online documentation for a full list of its methods.

#### The `URLEncoder` Class

`URLEncoder` takes a string of text and turns it into the into `x-www-form-urlencoded` format, which is a MIME format. This can then be used in conjunction with the `URL` class.

#### The `URLStreamHandler` Class

`URLStreamHandler` is an abstract class. Its purpose is to create a format for opening a stream connection to a specific URL. This class is concerned with the protocol of the URL. If a programmer wants to create a new URL stream protocol, it is necessary to implement the methods specified in this abstract class. This is most definitely only for advanced programmers.

## Introducing the `sun.tools.debug` Library

The `sun.tools.debug` library provides the necessary framework for debugging Java programs. Whenever you use the Java debugger, you are accessing this library. If you accessed its classes directly, you could create your own debugger. Because most Java developers will not need to create their own debugger, this section provides only an overview of the classes the library contains to give you insight into the debugging process.

### The `DebuggerCallback` Interface

The `DebuggerCallback` interface is a template for implementing communications between an application and a debugger. The basic syntax for the interface is as follows:

> `public interface DebuggerCallback {
> …
> }`

All communications between client applications and a debugger are asynchronous. Asynchronous communications are rather like the way you and I use e-mail: We send a message and the receiver responds to the message when he gets a chance. The sections that follow look at the abstract methods in the `DebuggerCallback` interface.

One of the key methods in this interface is `breakpointEvent()`, which is used to report when a breakpoint has been reached. The method accepts a `RemoteThread` object-the thread that reached the breakpoint-as a parameter. You use breakpoints during advanced debugging to help determine the behavior and state of the program at a certain point in the program's execution.

See Chapter 23, "Advanced Debugging and Troubleshooting" for more information on breakpoints.

Other key methods in this class include `exceptionEvent()`, `printToConsole()`, `quitEvent()`, and `threadDeathEvent()`. The `exceptionEvent()` method is used to report that an exception has occurred. It accepts a `RemoteThread` object and a `String` object as parameters.

The `printToConsole()` method is used whenever the `DebuggerCallback` interface prints messages to the console-which, as you will see when you use the Java debugger, is quite often. The `printToConsole()` method accepts a `String` object as a parameter.

The `quitEvent()` method is used to tell the debugger that the client has exited. Generally, clients exit either by returning from the main thread or by calling `System.exit()`.

The `threadDeathEvent()` is used to report that a thread has died. This method accepts a `RemoteThread` object, which is the thread that died, as a parameter.

### Methods that Deal with Remote Objects

As you might expect, most of the classes in a debugging library for an object-oriented programming language are designed to handle the debugging methods associated with objects. A complete listing of the types of remote objects handled by the debugger is as follows: arrays, booleans, bytes, characters, classes, doubles, fields, floats, integers, longs, shorts, strings, threads, thread groups, and variable values.

Each of these object types is handled in a separate class. These classes include

> `RemoteArray
> RemoteBoolean
> RemoteByte
> RemoteChar
> RemoteClass
> RemoteDouble
> RemoteField
> RemoteFloat
> RemoteInt
> RemoteLong
> RemoteShort
> RemoteString
> RemoteThread
> RemoteThreadGroup
> RemoteValue`

Most of the methods used with specific objects types are similar to the methods used in the `RemoteObject` class. For example, the `RemoteArray` class is one of many classes in the `sun.tools.debug` package that allow remote debugging of specific object types. As you can probably tell by the name of the class, the `RemoteArray` class allows remote debugging of arrays.

What you probably cannot tell from the class name is that the `RemoteArray` class uses an extensive list of methods that handle every facet of debugging array objects. Still, the methods in the `RemoteArray` class are similar to the methods in the more generic `RemoteObject` class. Therefore, by examining the methods in the `RemoteObject` class, you can gain an understanding of most of the other classes in the `sun.tools.debug` package.

Table 13.1 is a summary of the methods in the `RemoteObject` class.

Table 13.1. Methods in the `RemoteObject` class.

Method | Purpose
`description()` | Returns a description of the object
`finalize()` | Performs this code when garbage collection is run
`getClass()` | Returns the object's class
`getField()` | Returns an instance variable
`getFields()` | Returns the non-static fields of an object
`getFieldValue()` | Returns the value of an object's instance variable
`getId()` | Returns the ID of an object
`setField()` | Sets an instance variable, specified by slot or name
`toString()` | Returns the object as a string
`typeName()` | Returns the object type

### The `RemoteStackFrame` Class

Using the `RemoteStackFrame` class, the debugger can examine a suspended thread's stackframe. As a Java developer, you will often use the debugger to call the methods of this class.

The stackframe provides a frame of reference for everything related to a thread's stack. You can think of it as a snapshot of a thread's internals, including the thread's program counter, local variables, referenced methods, referenced classes, and the current line number of execution. The methods used to retrieve this information follow a very basic syntax. For example, when you call the `getLineNumber()` method, the method returns the current line number of execution. This and other methods in this class are shown in Table 13.2.

Table 13.2. Methods in the `RemoteStackFrame` class.

Method | Purpose
`getLineNumber()` | Returns the current line number of execution
`getLocalVariable()` | Returns a named stack variable in the current stackframe
`getLocalVariables()` | Returns an array of all valid local variables and method arguments for the stackframe
`getMethodName()` | Returns the method name that the stackframe references
`getpc()` | Returns the program counter that the stackframe references
`getRemoteClass()` | Returns the class that the stackframe references

### The `RemoteStackVariable` Class

The `RemoteStackVariable` class is similar to the `RemoteStackFrame` class. Using this class, the caller can obtain information about a specific stack variable.

The class has three methods: `getName()`, `getValue()`, and `inScope()`. The `getName()` method is used to get the name of a variable on the stack. The `getValue()` method is used to get the value of a variable on the stack. The `inScope` method is used to tell whether the variable is accessible.

### The `RemoteDebugger` Class

Because the `RemoteDebugger` class can instantiate a connection with the Java interpreter session being debugged, client applications use this class as an interface to the Java debugging classes. To create a client interface, you use a constructor. The `RemoteDebugger` class provides an overloaded constructor interface that allows for the two different ways the debugger can be instantiated.

The first constructor is used to attach the debugger to a current interpreter session. As you will learn in Chapter 23, you do this by first starting the Java interpreter with the `-debug` option. The interpreter passes back a password, which is then passed to the debugger when it is invoked. In addition to accepting the password as a parameter, the constructor accepts a `String` object that identifies

- The host running the current interpreter session
- The client using the `DebuggerCallback` interface to receive messages from the debugger
- A `verbose` flag to turn on internal debugger message text

Here is the syntax for the first constructor:

> `public RemoteDebugger(String host,
> String password,
> DebuggerCallback client,
> boolean verbose) throws Exception`

The second constructor is used to create a remote debugger that will start a client interpreter session. When you start the debugger directly, it in turn starts the Java interpreter with any parameters you passed on the command line. For this reason, the second constructor accepts arguments that are to be passed on to the interpreter. Other parameters allow the client using the `DebuggerCallback` interface to receive messages from the debugger, and others set a `verbose` flag to turn on or off internal debugger message text.

The syntax for the second constructor follows:

> `public RemoteDebugger(String javaArgs,
> DebuggerCallback client,
> boolean verbose) throws Exception`

Methods in the `RemoteDebugger` class enable debugging techniques you will use when you debug your programs. These methods are shown in Table 13.3.

Table 13.3. Methods in the `RemoteDebugger` class.

Method | Purpose
`addSystemThread()` | Adds a system thread
`close()` | Closes the connection to the remote debugger
`findClass()` | Finds a specified class
`freeMemory()` | Gets a report of the free memory available to the Java interpreter being debugged
`gc()` | Frees all objects referenced by the debugger
`get()` | Gets an object from the remote object cache
`getExceptionCatchList()` | Gets the list of the exceptions on which the debugger will stop
`getSourcePath()` | Gets the source file path the client is currently using
`itrace()` | Turns instruction tracing on or off
`listBreakpoints()` | Gets a list of the current breakpoints
`listClasses()` | Gets a list of the currently known classes
`listThreadGroups()` | Gets a list of the currently known thread groups
`run()` | Loads and runs a runnable Java class
`setSourcePath()` | Sets the search path for source files
`totalMemory()` | Obtains a report of the total memory used by the Java interpreter being debugged
`trace(boolean)` | Turns method call tracing on or off

### The `StackFrame` Class

The `StackFrame` class provides a wrapper for the stackframe of a suspended thread. This class has a very basic constructor and a single method, called `toString()`, that returns an object as a string.

## Summary

The `java.net` package contains classes that provide an easy-to-use interface to basic network programming. By using these classes, you can enable your Java application or applet to participate in the world of network connectivity. Some classes provide an abstract framework for protocol-specific programming. These abstract classes may be implemented in the Java-enabled operating-system interface.

The `sun.tools.debug` class library adds built-in debugging support to the Java programming language. Examining the classes in this library should have given you insight into the debugging process.

The mail server and mail client examples in this chapter are good demonstrations of how easy it can be to write complex network programs in Java, enabling even novice programmers to develop working network applications. This is yet another example of the power that has been built into Java, making it the programming language to use today!