I’m attempting to debug a scala project remotely. Both the executing program (built and executed from SBT) and my debugger (Intellij) are local, but since I don’t want to build using Intellij, using a remote debugging session seemed the easiest option for convenient debugging.
The program is started with the following options:
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
It’s successfully suspending on launch, and I can successfully attach my debugger. I can set break points and step through the code, but the problem is that an uncaught exception terminates the debugging session and disconnects the debugger, defeating the purpose of debugging. This being the default behaviour would be asburd, so I have to be doing something wrong.
Intellij’s Console reads:
Connected to the target VM, address: 'localhost:5005', transport: 'socket'
Disconnected from the target VM, address: 'localhost:5005', transport: 'socket'
Is there something I’m missing on either the execution or debugging side of things?
Edit: adding a stack trace where I’m throwing new Exception(“what”) in the main of my class:
[error] java.lang.Exception: what
[error] at travellr.application.prophet.Prophet$.main(Prophet.scala:80)
[error] at travellr.application.prophet.Prophet.main(Prophet.scala)
[error] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[error] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[error] at java.lang.reflect.Method.invoke(Method.java:597)
[error] at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:81)
[error] at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
[error] at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:86)
[error] at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:81)
[error] at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:86)
[error] at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:83)
[error] at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
If the exception is never caught, it will cause your application to close and the JVM to terminate, which obviously ends the debugging session.
You can add an exception breakpoint so that the debugger will suspend execution as soon as the exception is thrown. Click on the “View Breakpoints” button in the debug toolbar, then see the “Exception Breakpoints” tab. It helps to know what type of exception you’re looking for so that you can set the exception breakpoint for that specific type; you should be able to find the appropriate type by examining your stacktrace. Otherwise, you’ll end up suspending on lots of unrelated exceptions. If you know which thread the exception occurs on, it can also be helpful to limit the exception breakpoint to that thread.
Note that both SBT (if you’re not forking a separate VM) and Scala’s runner (if you are forking) catch all exceptions thrown in client code. Therefore, there will be no “uncaught exceptions”, and you will need to suspend on “caught exceptions”.