You can dump out tracebacks of a Java process at any time, and see what line of code is being executed by each thread. This is VERY handy for analysing thread problems, like deadlock.
At the NT-DOS prompt, just type control-break (a little used key on the upper-right).
On Unix, send a QUIT signal to the java process group. Here's how to send a QUIT signal:
% kill -QUIT -32352where 32352 is the process group ID (PGID). You must include the minus sign before the PGID. Get the PGID with this command:
% ps -e -o 'pgid user fname args' | grep java |sort -nThe first column will contain the PGID. The QUIT signal is often bound to control-\ (backslash).
I map the QUIT signal to control-A with
% stty quit "^A"
You'll get the tracebacks printed to the screen, without causing the program to exit. This dump is more thorough than you get from an uncaught exception. Read more at http://developer.java.sun.com/developer/onlineTraining/Programming/JDCBook/stack.html
To see uncompiled line numbers, use the option "java -Djava.compiler=NONE com.lgc.stuff" when you launch the process in question.
I have not found a way to send a signal under Cygnus bash on Windows.
Time-consuming code should check Thread.interrupted() regularly. If true, then respond just as if you had caught an InterruptedException.
Do NOT cause an interrupt to be ignored, or no one will be able to stop your Thread.
You will only get an InterruptedException if someone has deliberately called Thread.interrupt(). They want your Thread to clean up and return from the Thread.run() method.
If your utility method is not in a position to clean up, then it should rethrow the InterruptedException. Do not convert and rethrow a different kind of Exception.
If this is too difficult, then at least call Thread.currentThread().interrupt() so that later code can handle the interrupt correctly.
public void foo() { try {Thread.sleep(1000);} catch (InterruptedException e) { Thread.currentThread().interrupt(); } }
There is no other safe way to stop a Thread because Thread.stop() is deprecated.
/** Run many Threads and interrupt if not finished after a time limit. @param thread Start these threads and interrupt if necessary. @param millisWait Milliseconds to wait for threads to complete. If zero, wait forever. @param millisPause Wait this many milliseconds between starting each thread, to avoid clobbering resources. @return Array of booleans for each thread. Element is true if thread was interrupted because of timeout or because this thread was interrupted. */ public static boolean[] run(Thread[] thread, long millisWait, long millisPause) { long end = System.currentTimeMillis() + millisWait; if (millisWait == 0) { end = Long.MAX_VALUE; } boolean interruptedMe = false; for (int i=0; i<thread.length; ++i) { if (thread[i] != null) thread[i].start(); if (millisPause >0) { try { Thread.sleep(millisPause); } catch (InterruptedException e) { interruptedMe = true; } } } boolean allFinished = false; while (!interruptedMe && System.currentTimeMillis() < end && !allFinished) { allFinished = true; for (int i=0; allFinished && i<thread.length; ++i) { if (thread[i] != null && thread[i].isAlive()) allFinished = false; } if (!allFinished) { try { Thread.sleep(200); } catch (InterruptedException e) { interruptedMe = true; } } } boolean[] interrupted = new boolean[thread.length]; for (int i=0; i<thread.length; ++i) { if (thread[i] != null && thread[i].isAlive()) { thread[i].interrupt(); interrupted[i] = true; } else { interrupted[i] = false; } } if (interruptedMe) { Thread.currentThread().interrupt(); } return interrupted; }
public static String[] getThreadNames() { ThreadGroup group = Thread.currentThread().getThreadGroup(); ThreadGroup parent = null; while ( (parent = group.getParent()) != null ) { group = parent; } Thread[] threads = new Thread[group.activeCount()]; group.enumerate(threads); java.util.HashSet set = new java.util.HashSet(); for (int i=0; i < threads.length; ++i) { if (threads[i] != null && threads[i].isAlive()) { try { set.add(threads[i].getThreadGroup().getName()+"," +threads[i].getName()+"," +threads[i].getPriority()); } catch (Throwable e) {e.printStackTrace();} } } String[] result = (String[]) set.toArray(new String[0]); java.util.Arrays.sort(result); return result; }
If you start a java process from the command line,
add the following flag to create a logfile called temp.hprof
:
java -Xrunhprof:cpu=samples,depth=30,file=temp.hprof com.acme.YourClassMainLook at the file graphically with
java -jar PerfAnal.jar temp.hprof
Here's an example Foo.java
:
import java.util.logging.Logger; public class Foo { private static final Logger LOG = Logger.getLogger(Foo.class.getName(), Foo.class.getName()); public static void main(String[] a) { LOG.info("Everything is dandy."); // old way LOG.info("dandy"); // new way } }Create a
Foo.properties
file with this line
dandy=Everything is dandy.in the same directory as
Foo.class
.
You'll see the same message twice.
Or create Foo_hick.properties
with
dandy=Boy howdy.and run
java -Duser.language=hick test.Foo(Real languages use two-letter codes like en, es, ch, fr.)
I often see code where an Exception is caught only to print some general error message and return. That isn't really handling an Exception. The original Exception is being lost, along with the stack trace, and any detailed getMessage(). Nothing has been done to fix the problem so that work can continue.
If the Exception reaches the main(), then it is reasonable to print out error information and return. (Do not call System.exit.)
Best, just pass or rethrow the Exception out of main(). Then the user can see the entire stack trace. It is reasonable for a main() that manipulates files to declare "throws IOException."
Feel free to print out as much debug information as you can before rethrowing an Exception. But don't throw away that Exception unless you've fixed the problem and normal work can continue.
If you feel like converting one type of Exception into another, then use initCause(), so that the original Exception and its stacktrace are not lost:
try { foo(); } catch (TheirException te) { MyException me = new MyException("My bad."); me.initCause(te); throw me; }
-Dswing.volatileImageBufferEnabled=false
or
-Dsun.java2d.noddraw=true
or
-Dsun.java2d.ddoffscreen=false
.
For more information, see
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4527745
Revision: $Id: javatips.html,v 1.9 2005/01/17 22:43:45 harlan Exp $