Home > Articles > Programming > Java

  • Print
  • + Share This
This chapter is from the book

Debugging Techniques

Suppose you wrote your program and made it bulletproof by catching and properly handling all exceptions. Then you run it, and it does not work right. Now what? (If you never have this problem, you can skip the remainder of this chapter.)

Of course, it is best if you have a convenient and powerful debugger. Debuggers are available as a part of professional development environments such as Eclipse, NetBeans, or JBuilder. However, if you use a new version of Java that is not yet supported by development environments or if you work on an unusual platform, you will need to do a great deal of debugging by the time-honored method of inserting logging statements into your code.

Useful Tricks for Debugging

Here are some tips for efficient debugging if you have to do it all yourself.

  1. You can print or log the value of any variable with code like this:

    System.out.println("x=" + x);


    Logger.global.info("x=" + x);

    If x is a number, it is converted to its string equivalent. If x is an object, then Java calls its toString method. To get the state of the implicit parameter object, print the state of the this object.

    Logger.global.info("this=" + this);

    Most of the classes in the Java library are very conscientious about overriding the toString method to give you useful information about the class. This is a real boon for debugging. You should make the same effort in your classes.

  2. One seemingly little-known but very useful trick is that you can put a separate main method in each class. Inside it, you can put a unit test stub that lets you test the class in isolation.

    public class MyClass
       methods and fields
       . . .
       public static void main(String[] args)
          test code

    Make a few objects, call all methods, and check that each of them does the right thing. You can leave all these main methods in place and launch the Java virtual machine separately on each of the files to run the tests. When you run an applet, none of these main methods are ever called. When you run an application, the Java virtual machine calls only the main method of the startup class.

  3. If you liked the preceding tip, you should check out JUnit from http://junit.org. JUnit is a very popular unit testing framework that makes it easy to organize suites of test cases. Run the tests whenever you make changes to a class, and add another test case whenever you find a bug.

  4. A logging proxy is an object of a subclass that intercepts method calls, logs them, and then calls the superclass. For example, if you have trouble with the setBackground method of a panel, you can create a proxy object as an instance of an anonymous subclass:

    JPanel panel = new
          public void setBackground(Color c)
             Logger.global.info("setBackground: c=" + c);

    Whenever the setBackground method is called, a log message is generated. To find out who called the method, generate a stack trace—see the next tip.

  5. You can get a stack trace from any exception object with the printStackTrace method in the Throwable class. The following code catches any exception, prints the exception object and the stack trace, and rethrows the exception so it can find its intended handler.

       . . .
    catch (Throwable t)
       throw t;

    You don't even need to catch an exception to generate a stack trace. Simply insert the statement


    anywhere into your code to get a stack trace.

  6. Normally, the stack trace is displayed on System.err. You can send it to a file with the void printStackTrace(PrintWriter s) method. Or, if you want to log or display the stack trace, here is how you can capture it into a string:

    StringWriter out = new StringWriter();
    new Throwable().printStackTrace(new PrintWriter(out));
    String trace = out.toString();

    (See Chapter 12 for the PrintWriter and StringWriter classes.)

  7. It is often handy to trap program errors in a file. However, errors are sent to System.err, not System.out. Therefore, you cannot simply trap them by running

    java MyProgram > errors.txt

    In UNIX and Windows NT/2000/XP, this is not a problem. For example, if you use bash as your shell, simply capture the error stream as

    java MyProgram 2> errors.txt

    To capture both System.err and System.out in the same file, use

    java MyProgram 2>&1 errors.txt

    Some operating systems (such as Windows 95/98/Me) do not have such a convenient method. Here is a remedy. Use the following Java program:

    import java.io.*;
    public class Errout
       public static void main(String[] args) throws IOException
          Process p = Runtime.getRuntime().exec(args);
          BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
          String line;
          while ((line = err.readLine()) != null)

    Then run your program as

    java Errout java MyProgram > errors.txt

    A more efficient way of getting the same result in Windows is to compile this C program into a file, errout.exe:

    #include <io.h>
    #include <stdio.h>
    #include <process.h>
    int main(int argc, char* argv[])
       dup2(1, 2); /* make stderr go to stdout */
       execvp(argv[1], argv + 1);
       return 0;

    Then you can run

    errout java MyProgram > errors.txt
  8. To watch class loading, launch the Java virtual machine with the -verbose flag. You get a printout such as:

    [Opened /usr/local/jdk5.0/jre/lib/rt.jar]
    [Opened /usr/local/jdk5.0/jre/lib/jsse.jar]
    [Opened /usr/local/jdk5.0/jre/lib/jce.jar]
    [Opened /usr/local/jdk5.0/jre/lib/charsets.jar]
    [Loaded java.lang.Object from shared objects file]
    [Loaded java.io.Serializable from shared objects file]
    [Loaded java.lang.Comparable from shared objects file]
    [Loaded java.lang.CharSequence from shared objects file]
    [Loaded java.lang.String from shared objects file]
    [Loaded java.lang.reflect.GenericDeclaration from shared objects file]
    [Loaded java.lang.reflect.Type from shared objects file]
    [Loaded java.lang.reflect.AnnotatedElement from shared objects file]
    [Loaded java.lang.Class from shared objects file]
    [Loaded java.lang.Cloneable from shared objects file]

    This can occasionally be helpful to diagnose class path problems.

  9. If you ever looked at a Swing window and wondered how its designer managed to get all the components to line up so nicely, you can spy on the contents. Press CTRL+SHIFT+F1, and you get a printout of all components in the hierarchy:

  10. If you design your own custom Swing component and it doesn't seem to be displayed correctly, you'll really love the Swing graphics debugger. And even if you don't write your own component classes, it is instructive and fun to see exactly how the contents of a

    component are drawn. To turn on debugging for a Swing component, use the setDebugGraphicsOptions method of the JComponent class. The following options are available:


    Flashes each line, rectangle, and text in red before drawing it


    Prints a message for each drawing operation


    Displays the operations that are performed on the off-screen buffer


    Turns graphics debugging off

    We have found that for the flash option to work, you must disable "double buffering," the strategy used by Swing to reduce flicker when updating a window. The magic incantation for turning on the flash option is:

    ((JComponent) getContentPane()).setDebugGraphicsOptions(DebugGraphics.FLASH_OPTION);

    Simply place these lines at the end of your frame constructor. When the program runs, you will see the content pane filled in slow motion. Or, for more localized debugging, just call setDebugGraphicsOptions for a single component. Control freaks can set the duration, count, and color of the flashes—see the on-line documentation of the DebugGraphics class for details.

  11. JDK 5.0 adds the -Xlint option to the compiler for spotting common code problems. For example, if you compile with the command

    javac -Xlint:fallthrough

    then the compiler reports missing break statements in switch statements. (The term "lint" originally described a tool for locating potential problems in C programs, and is now generically applied to tools that flag constructs that are questionable but not illegal.)

    The following options are available:

    -Xlint or -Xlint:all

    Carries out all checks


    Same as -deprecation, checks for deprecated methods


    Checks for missing break statements in switch statements


    Warns about finally clauses that cannot complete normally


    Carries out none of the checks


    Checks that all directories on the class path and source path exist


    Warns about serializable classes without serialVersionUID (see Chapter 12)


    Warns of unsafe conversions between generic and raw types (see Chapter 13)

  12. JDK 5.0 adds support for monitoring and management of Java applications, allowing the installation of agents in the virtual machine that track memory consumption, thread usage, class loading, and so on. This feature is particularly important for large and long-running Java programs such as application servers. As a demonstration of these capabilities, the JDK ships with a graphical tool called jconsole that displays statistics about the performance of a virtual machine (see Figure 11-4). To enable monitoring, start the virtual machine with the -Dcom.sun.management.jmxremote option. Then find out the ID of the operating system process that runs the virtual machine. In UNIX/Linux, run the ps utility; in Windows, use the task manager. Then launch the jconsole program:

    java -Dcom.sun.management.jmxremote MyProgram.java
    jconsole processID

    11fig04.jpgFigure 11-4 The jconsole Program

  13. If you launch the Java virtual machine with the -Xprof flag, it runs a rudimentary profiler that keeps track of the methods in your code that were executed most often. The profiling information is sent to System.out. The output also tells you which methods were compiled by the just-in-time compiler.

The -X options of the compiler are not officially supported and may not be present in all versions of the JDK. Run java -X to get a listing of all nonstandard options.

Using a Console Window

If you run an applet inside a browser, you may not be able to see any messages that are sent to System.out. Most browsers will have some sort of Java Console window. (Check the help system for your browser.) For example, Netscape Navigator has one, as does Internet Explorer 4 and above. If you use the Java Plug-in, check the Show Java Console box in the configuration panel (see Chapter 10).

Moreover, the Java Console window has a set of scrollbars, so you can retrieve messages that have scrolled off the window. Windows users will find this a definite advantage over the DOS shell window in which the System.out output normally appears.

We give you a similar window class so you can enjoy the same benefit of seeing your debugging messages in a window when debugging a program. Figure 11-5 shows our ConsoleWindow class in action.

11fig05.jpgFigure 11-5 The console window

The class is easy to use. Simply call:


Then print to System.out or System.err in the normal way.

Example 11-5 lists the code for the ConsoleWindow class. As you can see, the class is quite simple. Messages are displayed in a JTextArea inside a JScrollPane. We call the System.setOut and System.setErr methods to set the output and error streams to a special stream that adds all messages to the text area.

Example 11-5. ConsoleWindow.java

 1. import java.awt.*;
 2. import java.awt.event.*;
 3. import javax.swing.*;
 4. import java.io.*;
 6. /**
 7.    A window that displays the bytes sent to System.out
 8.    and System.err
 9. */
10. public class ConsoleWindow
11. {
12.    public static void init()
13.    {
14.       JFrame frame = new JFrame();
15.       frame.setTitle("ConsoleWindow");
16.       final JTextArea output = new JTextArea();
17.       output.setEditable(false);
18.       frame.add(new JScrollPane(output));
19.       frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
20.       frame.setLocation(DEFAULT_LEFT, DEFAULT_TOP);
21.       frame.setFocusableWindowState(false);
22.       frame.setVisible(true);
24.       // define a PrintStream that sends its bytes to the
25.       // output text area
26.       PrintStream consoleStream = new PrintStream(new
27.          OutputStream()
28.          {
29.             public void write(int b) {} // never called
30.             public void write(byte[] b, int off, int len)
31.             {
32.                output.append(new String(b, off, len));
33.             }
34.          });
36.       // set both System.out and System.err to that stream
37.       System.setOut(consoleStream);
38.       System.setErr(consoleStream);
39.    }
41.    public static final int DEFAULT_WIDTH = 300;
42.    public static final int DEFAULT_HEIGHT = 200;
43.    public static final int DEFAULT_LEFT = 200;
44.    public static final int DEFAULT_TOP = 200;
45. }

Tracing AWT Events

When you write a fancy user interface in Java, you need to know what events AWT sends to what components. Unfortunately, the AWT documentation is somewhat sketchy in this regard. For example, suppose you want to show hints in the status line when the user moves the mouse over different parts of the screen. The AWT generates mouse and focus events that you may be able to trap.

We give you a useful EventTrace class to spy on these events. It prints out all event handling methods and their parameters. See Figure 11-6 for a display of the traced events.

11fig06.jpgFigure 11-6 The EventTracer class at work

To spy on messages, add the component whose events you want to trace to an event tracer:

EventTracer tracer = new EventTracer();

That prints a textual description of all events, like this:

public abstract void java.awt.event.MouseListener.mouseExited(java.awt.event.MouseEvent):
java.awt.event.MouseEvent[MOUSE_EXITED,(408,14),button=0,clickCount=0] on javax.swing
   public abstract void java.awt.event.FocusListener.focusLost(java.awt.event.FocusEvent):
   java.awt.event.FocusEvent[FOCUS_LOST,temporary,opposite=null] on javax.swing.JButton[,0

You may want to capture this output in a file or a console window, as explained in the preceding sections.

Example 11-6 is the EventTracer class. The idea behind the class is easy even if the implementation is a bit mysterious.

  1. When you add a component to the event tracer in the add method, the JavaBeans introspection class analyzes the component for methods of the form void addXxxListener(XxxEvent). (See Chapter 8 of Volume 2 for more information on JavaBeans.) For each matching method, an EventSetDescriptor is generated. We pass each descriptor to the addListener method.

  2. If the component is a container, we enumerate its components and recursively call add for each of them.

  3. The addListener method is called with two parameters: the component on whose events we want to spy and the event set descriptor. The getListenerType method of the EventSetDescriptor class returns a Class object that describes the event listener interface such as ActionListener or ChangeListener. We create a proxy object for that interface. The proxy handler simply prints the name and event parameter of the invoked event method. The getAddListenerMethod method of the EventSetDescriptor class returns a Method object that we use to add the proxy object as the event listener to the component.

    This program is a good example of the power of the reflection mechanism. We don't have to hardwire the fact that the JButton class has a method addActionListener whereas a JSlider has a method addChangeListener. The reflection mechanism discovers these facts for us.

The proxy mechanism makes this program dramatically easier. In prior editions of this book, we needed to define a listener that simultaneously implements the MouseListener, ComponentListener, FocusListener, KeyListener, ContainerListener, WindowListener, TextListener, AdjustmentListener, ActionListener, and ItemListener interfaces and a couple of dozen methods that print the event parameter. The proxy mechanism is explained at the end of Chapter 6.

Example 11-7 tests the event tracer. The program displays a frame with a button and a slider and traces the events that these components generate.

Example 11-6. EventTracer.java

 1. import java.awt.*;
 2. import java.awt.event.*;
 3. import java.beans.*;
 4. import java.lang.reflect.*;
 6. public class EventTracer
 7. {
 8.    public EventTracer()
 9.    {
10.       // the handler for all event proxies
11.       handler = new
12.          InvocationHandler()
13.          {
14.             public Object invoke(Object proxy, Method method, Object[] args)
15.             {
16.                System.out.println(method + ":" + args[0]);
17.                return null;
18.             }
19.          };
20.    }
22.    /**
23.       Adds event tracers for all events to which this component
24.       and its children can listen
25.       @param c a component
26.    */
27.    public void add(Component c)
28.    {
29.       try
30.       {
31.          // get all events to which this component can listen
32.          BeanInfo info = Introspector.getBeanInfo(c.getClass());
34.          EventSetDescriptor[] eventSets = info.getEventSetDescriptors();
35.          for (EventSetDescriptor eventSet : eventSets)
36.             addListener(c, eventSet);
37.       }
38.       catch (IntrospectionException e) {}
39.       // ok not to add listeners if exception is thrown
41.       if (c instanceof Container)
42.       {
43.          // get all children and call add recursively
44.          for (Component comp : ((Container) c).getComponents())
45.             add(comp);
46.       }
47.    }
49.    /**
50.       Add a listener to the given event set
51.       @param c a component
52.       @param eventSet a descriptor of a listener interface
53.    */
54.    public void addListener(Component c, EventSetDescriptor eventSet)
55.    {
56.       // make proxy object for this listener type and route all calls to the handler
57.       Object proxy = Proxy.newProxyInstance(null,
58.          new Class[] { eventSet.getListenerType() }, handler);
60.       // add the proxy as a listener to the component
61.       Method addListenerMethod = eventSet.getAddListenerMethod();
62.       try
63.       {
64.          addListenerMethod.invoke(c, proxy);
65.       }
66.       catch(InvocationTargetException e) {}
67.       catch(IllegalAccessException e) {}
68.       // ok not to add listener if exception is thrown
69.    }
71.    private InvocationHandler handler;
72. }

Example 11-7. EventTracerTest.java

 1. import java.awt.*;
 2. import java.awt.event.*;
 3. import javax.swing.*;
 5. public class EventTracerTest
 6. {
 7.    public static void main(String[] args)
 8.    {
 9.       JFrame frame = new EventTracerFrame();
10.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
11.       frame.setVisible(true);
12.    }
13. }
15. class EventTracerFrame extends JFrame
16. {
17.    public EventTracerFrame()
18.    {
19.       setTitle("EventTracerTest");
22.       // add a slider and a button
23.       add(new JSlider(), BorderLayout.NORTH);
24.       add(new JButton("Test"), BorderLayout.SOUTH);
26.       // trap all events of components inside the frame
27.       EventTracer tracer = new EventTracer();
28.       tracer.add(this);
29.    }
31.    public static final int DEFAULT_WIDTH = 400;
32.    public static final int DEFAULT_HEIGHT = 400;
33. }

Letting the AWT Robot Do the Work

Version 1.3 of the Java 2 Platform adds a Robot class that you can use to send keystrokes and mouse clicks to any AWT program. This class is intended for automatic testing of user interfaces.

To get a robot, you need to first get a GraphicsDevice object. You get the default screen device through the sequence of calls:

GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice screen = environment.getDefaultScreenDevice();

Then you construct a robot as:

Robot robot = new Robot(screen);

To send a keystroke, tell the robot to simulate a key press and a key release:


For a mouse click, you first need to move the mouse and then press and release a button:

robot.mouseMove(x, y); // x and y are absolute screen pixel coordinates.

The idea is that you simulate key and mouse input and afterwards take a screen snapshot to see whether the application did what it was supposed to. You capture the screen with the createScreenCapture method:

Rectangle rect = new Rectangle(x, y, width, height);
BufferedImage image = robot.createScreenCapture(rect);

The rectangle coordinates also refer to absolute screen pixels.

Finally, you usually want to add a small delay between robot instructions so that the application can catch up. Use the delay method and give it the number of milliseconds to delay. For example:

robot.delay(1000); // delay by 1000 milliseconds

The program in Example 11-8 shows how you can use the robot. A robot tests the button test program that you saw in Chapter 8. First, pressing the space bar activates the leftmost button. Then the robot waits for two seconds so that you can see what it has done. After the delay, the robot simulates the tab key and another space bar press to click on the next button. Finally, we simulate a mouse click on the third button. (You may need to adjust the x and y coordinates of the program to actually press the button.) The program ends by taking a screen capture and displaying it in another frame (see Figure 11-7).

11fig07.jpgFigure 11-7 Capturing the screen with the AWT robot

As you can see from this example, the Robot class is not by itself suitable for convenient user interface testing. Instead, it is a basic building block that can be a foundational part of a testing tool. A professional testing tool can capture, store, and replay user interaction scenarios and find out the screen locations of the components so that mouse clicks aren't guesswork. At the time of this writing, the robot is brand new and we are not aware of any sophisticated testing tools for Java user interfaces. We expect these tools to materialize in the future.

Example 11-8. RobotTest.java

 1. import java.awt.*;
 2. import java.awt.event.*;
 3. import java.awt.image.*;
 4. import javax.swing.*;
 6. public class RobotTest
 7. {
 8.    public static void main(String[] args)
 9.    {
10.       // make frame with a button panel
12.       ButtonFrame frame = new ButtonFrame();
13.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
14.       frame.setVisible(true);
16.       // attach a robot to the screen device
18.       GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
19.       GraphicsDevice screen = environment.getDefaultScreenDevice();
21.       try
22.       {
23.          Robot robot = new Robot(screen);
24.          run(robot);
25.       }
26.       catch (AWTException e)
27.       {
28.          e.printStackTrace();
29.       }
   30.    }
   32.    /**
   33.       Runs a sample test procedure
   34.       @param robot the robot attached to the screen device
   35.    */
   36.    public static void run(Robot robot)
   37.    {
   38.       // simulate a space bar press
   39.       robot.keyPress(' ');
   40.       robot.keyRelease(' ');
   42.       // simulate a tab key followed by a space
   43.       robot.delay(2000);
   44.       robot.keyPress(KeyEvent.VK_TAB);
   45.       robot.keyRelease(KeyEvent.VK_TAB);
   46.       robot.keyPress(' ');
   47.       robot.keyRelease(' ');
   49.       // simulate a mouse click over the rightmost button
   50.       robot.delay(2000);
   51.       robot.mouseMove(200, 50);
   52.       robot.mousePress(InputEvent.BUTTON1_MASK);
   53.       robot.mouseRelease(InputEvent.BUTTON1_MASK);
   55.       // capture the screen and show the resulting image
   56.       robot.delay(2000);
   57.       BufferedImage image = robot.createScreenCapture(new Rectangle(0, 0, 400, 300));
   59.       ImageFrame frame = new ImageFrame(image);
   60.       frame.setVisible(true);
   61.    }
   62. }
   64. /**
   65.    A frame to display a captured image
   66. */
   67. class ImageFrame extends JFrame
   68. {
   69.    /**
   70.       @param image the image to display
   71.    */
   72.    public ImageFrame(Image image)
   73.    {
   74.       setTitle("Capture");
   75.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
   77.       JLabel label = new JLabel(new ImageIcon(image));
   78.       add(label);
   79.    }
   81.    public static final int DEFAULT_WIDTH = 450;
   82.    public static final int DEFAULT_HEIGHT = 350;
   83. }
   java.awt.GraphicsEnvironment 1.2
  • static GraphicsEnvironment getLocalGraphicsEnvironment()

    returns the local graphics environment.

  • GraphicsDevice getDefaultScreenDevice()

    returns the default screen device. Note that computers with multiple monitors have one graphics device per screen—use the getScreenDevices method to obtain an array of all screen devices.

   java.awt.Robot 1.3
  • Robot(GraphicsDevice device)

    constructs a robot that can interact with the given device.

  • void keyPress(int key)

  • void keyRelease(int key)

    simulate a key press or release.



    The key code. See the KeyStroke class for more information on key codes

  • void mouseMove(int x, int y)

    simulates a mouse move.


    x, y

    The mouse position in absolute pixel coordinates

  • void mousePress(int eventMask)

  • void mouseRelease(int eventMask)

    simulate a mouse button press or release.



    The event mask describing the mouse buttons. See the InputEvent class for more information on event masks

  • void delay(int milliseconds)

    delays the robot for the given number of milliseconds.

  • BufferedImage createScreenCapture(Rectangle rect)

    captures a portion of the screen.



    The rectangle to be captured, in absolute pixel coordinates

  • + Share This
  • 🔖 Save To Your Account

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information

To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.


Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.


If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information

Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.


This site is not directed to children under the age of 13.


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information

If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information

Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents

California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure

Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact

Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice

We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020