A useful trick is to send a SIGQUIT signal to the Java process, e.g.
kill -QUIT your_process_id
Which will not kill it, but will tell it to print a thread dump. This will list all the threads, with a backtrace of what they are currently doing. Unfortunately this won't usually contain something as obvious as "conn.setAutoCommit(false)", but it will tell you where each thread is.
You can then find those points in the code and attempt to trace back to see if any are preceeded by transaction begins that are unmatched by commits/rollbacks.
Another thing that is useful when the application is being written is to have a common place where connections are created and controlled (i.e. yet another abstraction layer!). This becomes a good place to put statements for logging when connections are created and assigned to threads, and when a transaction is begun on one of them.