The problem
Some Scala code I'm working on calls out to a Java library which runs tasks in an executor service. I am trying to debug some code in the runnable that gets submitted (written in Java). I have a single breakpoint within the runnable.
My problem is that when I debug, my breakpoint never seems to be hit and the code within the runnable never executes.
Below you will find an extremely simplified version of the code in question. In this sample, the line on which I set a breakpoint is line 14. If you try and reproduce my issue, you will also notice that he process never terminates (A clue).
Summary of observable behaviour:
No break points
all tasks executed
process runs to completion
Break points on line 14 AND on line 10 (my current workaround)
all tasks executed
- both break points are hit for both tasks
- process runs to completion
Break point ONLY on line 14 (problem case)
-Tasks are submitted
-Neither task runs
-Neither breakpoint hit
-Process doesn't complete
The explanation
When I do a thread dump on the process in the problem case, I can see two threads:
"pool-1-thread-2" prio=6 tid=0x0000000013157800 nid=0x302c at breakpoint[0x00000000156df000]
java.lang.Thread.State: RUNNABLE
…
"pool-1-thread-1" prio=6 tid=0x0000000013155800 nid=0xa10 at breakpoint[0x0000000014b6e000]
java.lang.Thread.State: RUNNABLE
As you can see, Eclipse/Scala IDE has installed the breakpoints and they have triggered. The problem is that the IDE hasn't noticed this and doesn't show the threads suspended.
I suspect that the problem is that two threads are both activating a breakpoint on the same line of the same file at the same time (for some definition of same time). I think that this is confusing the Scala IDE debugger.
The boring bits
Eclipse: 3.8.2
Scala IDE: a slightly customised fork of 4.0
The example code:
Gog.scala – The main to tell Scala IDE to debug:
package d
object Gog extends App{
val magog = new Magog()
magog.submitTasks()
magog.waitExit()
}
Magog.java – The code that uses the executor service and in which breakpoints are to be set
package d;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Magog {
private final ExecutorService exec = Executors.newFixedThreadPool(2);
public void submitTask(){
System.out.println("Going to submit task"); //line 10
exec.submit(new Runnable(){
@Override
public void run() {
System.out.println("Running task"); //line 14
}
});
}
public void submitTasks(){
submitTask();
submitTask();
}
public void waitExit() throws InterruptedException{
exec.shutdown();
System.out.println("Shutdown complete");
}
}
Leave a comment
on 2015-04-01 03:53 *
By Iulian Dragos
Background info: the JVM debug interface requires a class to be loaded in order to set a breakpoint. So the debugger intercepts class load events in order to install "delayed" breakpoints (for line numbers that fall into classes that have not yet been loaded). We seem to miss doing that for anonymous Java classes. At least, this would be my starting point for investigation :)
No file chosen
You have an empty file field. Please select or remove it.
Name | Size |
---|