I never knew how good life could be — at work, mind you — until I spent some quality time with the Eclipse debugger. My days of relying solely on System.out.println() are long gone. Print debugging is only useful if you can change the code. Loggers like Log4j are only marginally better — assuming the code uses it properly in the first place.
And things get more interesting when the code is running on a different or remote machine. Luckily, Java has a great remote debugging facility. Here’s an example of how I enable remote debugging using command-line arguments.
-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n
In this example, the remote application will start and run normally while listening in the background for a debugger to connect on port 8000. For further details on how to enable and configure remote debugging, see Sun’s JPDA Connection and Invocation guide.



I agree, to a point. I think there is still a time and place for trace and sysout statements. But I am getting much more comfortable with the real-time debugger, to the point that I miss it when I’m working in an environment that doesn’t have one (Flash, I’m looking at you…). But I have run into cases where it’s just easier to print it out in the console and see what you’re getting.
Real-time debugging is essential when you have a recursive application. It is also essential in the cases when print statements “fix” the bug. That seems to be more common with C than Java.