|
July 11, 2000 WELCOME to the Java Developer Connection (JDC) Tech Tips, July 11, 2000. This issue covers:
This issue of the JDC Tech Tips is written by Glen McCluskey. These tips were developed using Java 2 SDK, Standard Edition, v 1.3.
|
import java.io.*;
public class ShutdownDemo {
private FileWriter fw_log;
private BufferedWriter bw_log;
// constructor that opens the log file
public ShutdownDemo() throws IOException {
fw_log = new FileWriter("log.txt");
bw_log = new BufferedWriter(fw_log);
// register the shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
endApp();
}
});;
}
// do some application processing and write to the log file
public void processApp1() throws IOException {
bw_log.write("testing");
bw_log.newLine();
}
// do some application processing resulting in an exception
public void processApp2() {
throw new RuntimeException();
}
// close the log file
public void endApp() {
try {
bw_log.close();
}
catch (IOException e) {
System.err.println(e);
}
}
public static void main(String args[]) throws IOException {
// create an application object
ShutdownDemo demo = new ShutdownDemo();
// do some processing
demo.processApp1();
// do some more processing that results in an exception
demo.processApp2();
}
}
|
This application creates an instance of the ShutdownDemo class, representing
an application. The constructor for the class opens a log file, using FileWriter
and BufferedWriter.
ShutdownDemo then calls processApp1. In its processing,
processApp1 writes an entry to the log file. Then processApp2 is
called. It throws an exception that is not caught by the application. Normally, this
exception would terminate the application; the log file entry previously written would be
lost because the output is sitting in a buffer which has not been flushed to disk.
But in this demo the output is not lost. This is because the application registers a shutdown hook by saying:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
endApp();
}
});;
|
Notice the use of an anonymous inner class. Here an instance of an unnamed class derived
from Thread is created, and a run method that calls endApp is defined for the
class.
All of this means that when the application is about to terminate, the JVM starts the thread
representing by the passed-in thread object. When the thread starts, the run method is
called. The run method calls endApp, which closes the log file. This flushes
the output buffer.
To underscore the effect of the shutdown hook, comment out the addShutdownHook
lines in ShutdownDemo. You'll see that the log file is empty when the program
terminates.
You can register multiple shutdown hooks. In this case, each thread that represents a hook
is started in an unspecified order, and the various threads run simultaneously. You cannot
register or unregister a shutdown hook after the shutdown sequence has started. Doing so
results in an IllegalStateException.
Because shutdown hooks run as threads, you must use thread-safe programming techniques. Otherwise you risk having threads interfere with each other. Also, it's wise to design your application for simple and fast shutdown processing. For example, you might run into trouble if your application uses services during shutdown that are themselves in the processing of being shut down.
There are cases where shutdown processing does not happen even if you have registered shutdown hooks. One example is corrupted native methods, for example, when you dereference a null pointer in C code.
This feature is somewhat similar to the atexit library function in C/C++.
For further information about shutdown hooks, see: http://java.sun.com/j2se/1.3/docs/guide/lang/enhancements.html#hooks
Imagine that you have a Java GUI program written using the AWT and Swing libraries, and you'd like to automate the program. For example, you'd like to automatically supply GUI input events from the keyboard and mouse to the program. In this way, the program could operate without user intervention. This type of automation might be useful for testing purposes, or to produce a self-running demo program.
java.awt.Robot is a new class in JDK 1.3, designed to handle this type of automation. It's
a way to automatically feed input events to a program. The events are generated in the
native input queue of the platform, as if they had actually been generated by the user. For
example, using java.awt.Robot, you can generate an event that is equivalent to a user moving
the mouse to particular (X,Y) coordinates on the screen.
Here's an example of how you can use this class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class RobotDemo {
public static void main(String args[]) throws AWTException {
// set up frames and panels
JFrame frame = new JFrame("RobotDemo");
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3, 1));
// set up fields, labels, and buttons
final JTextField field = new JTextField(10);
final JLabel lab = new JLabel();
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String s = "Length: " +
field.getText().length();
lab.setText(s);
}
});
JButton button = new JButton("Exit");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// add components to panel and display
panel.add(field);
panel.add(lab);
panel.add(button);
frame.getContentPane().add(panel);
frame.setSize(200, 150);
frame.setLocation(200, 200);
frame.setVisible(true);
// create a robot to feed in GUI events
Robot rob = new Robot();
// enter some keystrokes
int keyinput[] = {
KeyEvent.VK_T,
KeyEvent.VK_E,
KeyEvent.VK_S,
KeyEvent.VK_T,
KeyEvent.VK_I,
KeyEvent.VK_N,
KeyEvent.VK_G
};
rob.delay(1000);
rob.keyPress(KeyEvent.VK_SHIFT);
field.requestFocus();
for (int i = 0; i < keyinput.length; i++) {
rob.keyPress(keyinput[i]);
rob.delay(1000);
}
rob.keyRelease(KeyEvent.VK_SHIFT);
rob.keyPress(KeyEvent.VK_ENTER);
// move cursor to exit button
Point p = button.getLocationOnScreen();
rob.mouseMove(p.x + 5, p.y + 5);
rob.delay(2000);
// press and release left mouse button
rob.mousePress(InputEvent.BUTTON1_MASK);
rob.delay(2000);
rob.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
|
The demo sets up a panel containing an input field, a label, and an Exit button. This part of the demo is typical of many Swing applications. Then the demo creates a Robot object, and feeds into it a series of keystrokes. These keystrokes mimic keys typed by a user, that is, the keys T, E, S, T, I, N, and G. There is a delay of 1000 milliseconds between keystrokes; this helps present the animation more clearly. The shift key is held down throughout, so that the letters are entered as capitals. At the end of the text input, Enter is specified. This causes the length of the input to be echoed in the label field. Then the mouse cursor is moved to the Exit button, and the left mouse button is pressed and released. This terminates the program.
Notice that virtual keycodes are used to enter keystrokes; keycodes
are not the same as Java characters. KeyEvent.VK_A corresponds to
pressing the unshifted 'A' key on a keyboard. If you specify 'A' or
'a' instead of KeyEvent.VK_A, you get unexpected results.
Also note that the documentation for Robot says that some platforms require special privileges to access low-level input control. One specific case is X Windows, which requires the XTEST 2.2 standard extension.
For further information about java.awt.Robot, see
http://java.sun.com/j2se/1.3/docs/api/java/awt/Robot.html
For further information about key events, see
http://java.sun.com/j2se/1.3/docs/api/java/awt/event/KeyEvent.html
For further information about mouse events, see
http://java.sun.com/j2se/1.3/docs/api/java/awt/event/MouseEvent.html Note
The names on the JDC mailing list are used for internal Sun MicrosystemsTM purposes only. To remove your name from the list, see Subscribe/Unsubscribe below.
Feedback
Comments? Send your feedback on the JDC Tech Tips to: jdc-webmaster
Subscribe/Unsubscribe
To subscribe to these and other SDN publications:
- Go to the Sun Developer Network - Subscriptions page,
choose the newsletters you want to subscribe to and click
"Submit".
To unsubscribe,
- Go to the Sun Developer Network -
Subscriptions page,
uncheck the appropriate checkbox, and click "Submit".
Copyright
Copyright 2000 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.
This Document is protected by copyright. For more information, see:
http://developer.java.sun.com/developer/copyright.html
This issue of the JDC Tech Tips is written by Glen McCluskey.
JDC Tech Tips
July 11, 2000
* As used in this document, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.
|
| ||||||||||||