Ever have a stuck or deadlocked thread in a production application? Use JMX to inspect what’s going on inside your JVM, which includes thread views.  It’ll show you which threads are running, waiting, or blocked and where in the stacktrace they currently are.  I’ve used this information to find blocked threads in strange places.  JMX also shows you the memory usage of your java process, including memory consumed by classloaders in permspace.

The debug options will open your debug ports, naturally, and let you connect your debugger.

All you have to do is run your java process with these startup options:
DEBUG
-Xdebug -Xrunjdwp:transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n
JMX
-Dcom.sun.management.jmxremote.port=$JMX_PORT -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Look in your $JAVA_HOME/bin and you’ll see a jconsole executable. That GUI will let you connect to the machine running your java process on the port specified.

I hope you find these tips useful.  Both have been extremely useful to me (as well as adding optional profiling vars to a JVM!).