By default, Eclipse breakpoints are suspending only one thread. This causes application continues to run when I am thinking on breakpoint.
The is another mode for breakpoint - to suspend entire VM. This stops all thread but apparently I am unable to resume an execution or execution behaves differently on resume.
Is it possible to do normal suspend on breakpoints in Eclipse?
UPDATE
There is definitely not my problem, but Eclipse/JVM/other human bug. I made a simple example without any thread interaction:
package tests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Try_EclipseMultithreadedBreakpoint {
private static final Logger log = LoggerFactory.getLogger(Try_EclipseMultithreadedBreakpoint.class);
public static class Thread1 extends Thread {
public Thread1() {
setName("Thread1");
}
#Override
public void run() {
for(int i=0; i<10; ++i) {
log.info("tick {}", i);
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
}
}
}
}
public static class Thread2 extends Thread {
public Thread2() {
setName("Thread2");
}
#Override
public void run() {
for(int i=0; i<15; ++i) {
log.info("tick {}", i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
}
then I put an exception into second thread (Thread2):
then I have few breakpoint hits and resumes, then removed breakpoint and resumed, and application hanged.
Below is it's hung state:
as you see by output, thread 1 was not resumed. It printed only one tick and stopped. And it is not waiting for some monitor as reported by Eclipse, it is suspended.
Note, that I didn't set any breakpoints in thread 1, I set them only in thread 2.
Simultaneously, some "Finalizer" thread is waiting for some internal resource.
Also, I noticed, that after breakpoint hit, I was required to press resume several times before it actually resumed.
Select the item as shown on the screenshot and press F8
Related
I'm trying to diagnose convoluted multithreading operations in java.
I want to use the debug perspective to do so, but I encounter the following issue :
Expected behavior :
When pausing a thread (through the Debug view), the "Variables" view should show the variables
as seen by the thread I paused.
Using the Step over / step into operation multiple times should not modify variables in the thread.
Code (Using java 17):
package fr.fgoux.debugbugdemo;
public class DebugDemoMain
{
public int t;
public DebugDemoMain()
{
this.t = 0;
}
public static void main(final String[] args)
{
final DebugDemoMain demo = new DebugDemoMain();
final Thread t1 = new Thread(new Runnable() {
#Override
public void run()
{
for (int i = 0; i < 100; i++)
{
try
{
Thread.sleep(5);
} catch (final InterruptedException e)
{
e.printStackTrace();
}
demo.t++;
}
System.out.println("Write terminated");
}
});
final Thread t2 = new Thread(new Runnable() {
#Override
public void run()
{
while (demo.t != 100)
{
}
System.out.println("READ terminated");
}
});
t1.start();
t2.start();
try
{
t1.join();
t2.join();
} catch (final InterruptedException e)
{
e.printStackTrace();
}
System.out.println("END");
}
}
Behavior :
When I run this in debug mode, I get the output :
Write terminated
And the other thread keeps running.
If I pause the running thread, the debugger shows me it's stuck at "while (demo.t != 100)".
But the "variables" tab shows me t=100.
If I resume / pause this thread, it stays at the "while (demo.t != 100)" and keeps running.
If I press a step by step button, the thread execution line jumps out of the while loop, and then If I resume execution, the thread terminates with "READ terminated".
Personnal interpretation :
The reading thread that does the "demo.t != 100" caches the variable demo.t so that it does not notice that the other thread changed demo.t value (which is expected since there is no synchronization). It cannot make progress.
The "Variables" view does not show locally cached variables of the thread, but only some global representation of the variables (maybe in the shared memory).
The step by step operations cause the thread to update it's cache from the shared memory.
Question :
Is there a better debugging tool that would allow me to show these cached variables and diagnose these issues ?
I have a simple test program (garage simulation) with several threads (Vehicle, MysteryVehicle, Observer objects) instantiated and started. Only the Observer object is a daemon thread running an infinite loop.
After all non-daemon threads terminate, Observer thread never does and the loop is executed infinitely (so this isn't some buffered output after the daemon thread really terminates - it does go on forever).
All of the non-daemon threads print something to the console just before exiting their run() methods, and it clearly shows all of them really terminated. I also didn't call join() on the daemon thread. When printing out all currently running threads, observer is listed as well, so my guess is that this daemon thread isn't terminating properly.
The complete code can be found on this commit.
Below you can see all threads created, started and where exactly is join() called.
Main.java
package garage;
import java.util.Set;
import garage.model.*;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Platform platform = new Platform();
Vehicle.platform = platform;
platform.print();
Vehicle[] vehicles = new Vehicle[30];
for (int i = 0; i < 30; i++) {
vehicles[i] = new Vehicle();
}
for (int i = 0; i < 30; i++) {
vehicles[i].start();
}
Observer observer = new Observer();
observer.platform = platform;
observer.start();
MysteryVehicle mysteryVehicle = new MysteryVehicle();
mysteryVehicle.start();
try {
mysteryVehicle.join();
} catch (Exception exception) {
exception.printStackTrace();
}
try {
for (int i = 0; i < 30; i++)
vehicles[i].join();
} catch (Exception exception) {
exception.printStackTrace();
}
System.out.println("before");
platform.print();
System.out.println("after");
synchronized (Platform.lock) {
System.out.println("END");
System.out.println(platform.flag); // checks whether wait() was called anytime
}
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread t : threads) {
System.out.println(t.getName());
}
}
public static void main(String[] args) {
launch(args);
}
}
Observer.java
package garage.model;
public class Observer extends Thread {
public Platform platform;
static int count = 0;
{
setName("observer");
setPriority(MIN_PRIORITY);
setDaemon(true);
}
#Override
public void run() {
while (true) {
synchronized (Platform.lock) {
try {
System.out.println(++count);
platform.print();
Platform.lock.wait(5000); // hack for when there is no meaningful loop condition
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
Platform.lock.notifyAll();
}
}
}
}
}
Vehicle run() method - relevant part
public void run() {
...
System.out.println("done");
}
MysteryVehicle run() method - relevant part
public void run() {
synchronized (Platform.lock) {
System.out.println("And the vehicle disappears!");
...
}
}
All of the relevant thread messages are printed out to the console.
done - 30 times, And the vehicle disappears!, before, after, END, true
This is the list of all of the running threads:
Attach Listener
main
Common-Cleaner
JavaFX Application Thread
Signal Dispatcher
Finalizer
InvokeLaterDispatcher
Reference Handler
QuantumRenderer-0
observer
Thread-2
JavaFX-Launcher
Since the program doesn't terminate and the print() function the run() method of observer calls is executed infinitely, what is it that prevents the daemon thread from terminating?
What am I missing here?
I suspect main() never returns, so the main thread (and perhaps some of those FX threads) are still running.
From the Application doc:
The launch method does not return until the application has exited,
either via a call to Platform.exit or all of the application windows
have been closed.
The posted code has no window to close nor is Platform.exit() invoked.
As far as I know, calling join on daemon thread is a bad idea.The idea behind using daemon thread is it will not halt JVM from exiting. What you can do is send an interrupt to that thread and call join after that.
I'd like to check to see if a Thread is Interrupted, from some other Thread, without polling this to check - i.e. some kind of monitor.
Specifically, what I am trying to do is force-kill (Stop) a Thread when it is Interrupted. I will include a code example below of a trivial example of what I have done so far - it works, but polling to check if the Thread is interrupted is sub-optimal and I would like to avoid this.
public class ThreadTest
{
public static void main(final String[] args) throws InterruptedException
{
final Thread outerThread = new Thread()
{
#Override
public void run()
{
// Need to externally monitor the thread to detect and process interrupts (for cancellation)
final Thread thread = Thread.currentThread();
new Thread()
{
#Override
public void run()
{
while (true)
{
try
{
Thread.sleep(500);
}
catch (final InterruptedException e)
{}
if (thread.isInterrupted())
{
// Then kill it
thread.stop();
return;
}
}
}
}.start();
uninterruptibleForever();
}
};
outerThread.start();
// Ensure the thread has time to start up
Thread.sleep(500);
outerThread.interrupt();
// The thread should terminate at this point and not continue.
}
/** Some arbitrary task that runs forever and ignores interrupts */
public static void uninterruptibleForever()
{
while (true)
{
System.out.println(MessageFormat.format("I''m still running at {0}", new Date().toLocaleString()));
}
}
}
I can't recommend strongly enough that you don't use Thread#stop().
It should never have existed, was deprecated very quickly and frankly should have been removed about 20 years ago.
You have no idea what the thread is doing when you stop it and it is very easy to corrupt shared objects and leave external resources (e.g. files) in an invalid state.
Suppose the thread is in the middle of resizing a shared ArrayList<> there's risk the object will be corrupted and your whole program fails intermittently in ways you cannot fix.
Do not use Thread#stop() it is broken and cannot be fixed.
It's a terrible feature of Java that it leads people into invalid techniques regarding threads.
Caveat over - how about just overriding interrupt() in a sub-class?
public void interrupt(){
this.stop();
}
You've decided to sub-class Thread (rather than Runnable) so this will "work". "work" in the sense of what you're doing. Not actually work or anything.
The only valid way to solve this is have the thread you want to terminate co-operate by responding to interrupt() as an instruction to come to a suitable point and then terminate cleanly.
Or you can create another flag indicating the thread should end.
I don't know why you need to monitor the thread externally. But here is a small sample how you could do it if you really need it:
import java.util.LinkedList;
import java.util.List;
public abstract class MonitoredCallable implements Runnable {
private final List<InterruptedHandler> interruptedHandlers = new LinkedList<>();
protected abstract void runInternal() throws Exception;
#Override
public final void run() {
try {
runInternal();
} catch(Exception ex) {
}
for (InterruptedHandler interruptedHandler : interruptedHandlers) {
interruptedHandler.threadInterrupted(this);
}
}
public void addInterruptedHandler(InterruptedHandler interruptedHandler) {
this.interruptedHandlers.add(interruptedHandler);
}
public static interface InterruptedHandler {
void threadInterrupted(Thread t);
}
}
Now just use it like this:
MonitoredThread mt = new MonitoredThread() {
#Override
protected void runInternal() throws Exception {
//dosomething
}
};
mt.addInterruptedHandler(t->t.stop());
I tested a multi-thread program in JUnit and main function, source code as follows:
public class TestDaemon {
#Test
public void test() {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("hello");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// default false
thread.setDaemon(false);
thread.start();
}
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("hello");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// default false
thread.setDaemon(false);
thread.start();
}
}
It didn't print hello string in the JUnit test example.
In the main function example, it could print hello in the console, but when I set the thread.setDaemon(true), it also can't print hello.
I know this is related to Daemon thred and User thread, but I don't know how to explain it.
A daemon thread is a thread that does not prevent the JVM from exiting when the program finishes but the thread is still running. An example for a daemon thread is the garbage collection.
When you run your code from main it creates both beans, thus two threads - daemon and non-daemon. As long as non-daemon thread is running, your application won't exit. So it works.
It's different when run from JUnit. As soon as JUnit test method completes (and it completes immediately after the Spring context is up), JUnit assumes your tests are done. Thus it kills all your threads and basically the whole JVM.
Remember your Waitor1 bean spawns a background thread which JUnit doesn't care about. As soon as you leave #Test method JUnit will just stop everything.
We can analyze the source code of JUnit, part of junit.textui.TestRunner as follows:
public static final int SUCCESS_EXIT = 0;
public static final int FAILURE_EXIT = 1;
public static final int EXCEPTION_EXIT = 2;
...
public static void main(String args[]) {
TestRunner aTestRunner = new TestRunner();
try {
TestResult r = aTestRunner.start(args);
if (!r.wasSuccessful()) {
System.exit(FAILURE_EXIT);
}
System.exit(SUCCESS_EXIT);
} catch (Exception e) {
System.err.println(e.getMessage());
System.exit(EXCEPTION_EXIT);
}
}
/**
* Returns whether the entire test was successful or not.
*/
public synchronized boolean wasSuccessful() {
return failureCount() == 0 && errorCount() == 0;
}
/**
* Gets the number of detected failures.
*/
public synchronized int failureCount() {
return fFailures.size();
}
/**
* Gets the number of detected errors.
*/
public synchronized int errorCount() {
return fErrors.size();
}
In this source code, we can conclude that the TestRunner excutes the Unit Test method, no need to wait it finish their tasks, then calls System.exit() method, so that terminates the program. So, it couldn't print hello in the console.
In the main function, because the new thread is not daemon thread, the main program will wait it finishing their tasks, then teminates the program. So,hellostring could be seen in the console.
I'm about to learn the java threading facility.
I have 2 classes:
public class Main {
public static void main(String[] arg) throws Exception {
Timer timer = new Timer();
timer.schedule(new ExecuteTimer(Thread.currentThread()), 2000);
try {
Thread.currentThread().join();
} catch (InterruptedException ex) {
System.out.println("timer stopped");
}
System.out.println("try block executed");
}
}
and the timer class:
public class ExecuteTimer extends TimerTask {
public ExecuteTimer(Thread thread) {
creatingThread = thread;
}
private Thread creatingThread;
#Override
public void run() {
System.out.println("I'm executed!");
creatingThread.interrupt();
}
}
When I debug the code. I have following output:
I'm executed!
timer stopped
try block executed
Everything seems to be final except the app didn't exit after I have the output above. The eclipse remain in debug mode and no exception has been thrown.
After you no longer need the Timer to run tasks, you should call timer.cancel() to release its thread.
Use thread.setDaemon(true) to tell the JVM to make the thread a daemon thread. Daemon threads do not prevent the program from exiting.