In my program I made an assert - which evaluates to false - from a runnable, but never see any console output about the assert. I want to know if my asserts are false, but it seems the runnable is catching all the thrown asserts?
Below is the simplest example program I could write to demonstrate. (Assertions are enabled. The program would behave differently if they weren't and print both lines instead of just the one). The output of the program is.
About to assert False
That's it. After that the assert statement throws and is caught by something and I never know about it. I want to know about it, what am I doing wrong?
import java.nio.ByteBuffer;
import java.util.concurrent.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.FlowLayout;
import javax.swing.*;
class App
{
private static final ScheduledExecutorService sExecutor =
Executors.newSingleThreadScheduledExecutor();
// Main
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() { createAndShowGUI(); } });
}
// Swing GUI
private static void createAndShowGUI()
{
// Just create a swing thing. Boring
JFrame frame = new JFrame("Title String");
JLabel label = new JLabel("Hello World");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label);
frame.getContentPane().setLayout(new FlowLayout());
frame.pack();
frame.setVisible(true);
// ********************************************
// INTERESTING CODE HERE. We schedule a runnable which assert's false
// but we never see a console assert error!
// ********************************************
sExecutor.schedule(new Runnable()
{ @Override public void run() { doAssertFalse(); }}, 0, TimeUnit.SECONDS);
}
public static void doAssertFalse()
{
System.out.println("About to assert False");
assert false;
System.out.println("Done asserting False");
}
}
assert is not a function, its a keyword. Its a build in feature that must be enabled before it can be used. To enable this feature you have to add the command "-ea" to the argument list when initializing your JVM.
Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError .
In order to handle the assertion error, we need to declare the assertion statement in the try block and catch the assertion error in the catch block.
Assertions should be used to check something that should never happen, while an exception should be used to check something that might happen. For example, a function might divide by 0, so an exception should be used, but an assertion could be used to check that the harddrive suddenly disappears.
This will do it:
private static final ScheduledExecutorService sExecutor =
Executors.newSingleThreadScheduledExecutor();
// Main
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGUI();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
} });
}
// Swing GUI
private static void createAndShowGUI() throws ExecutionException, InterruptedException {
// Just create a swing thing. Boring
JFrame frame = new JFrame("Title String");
JLabel label = new JLabel("Hello World");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label);
frame.getContentPane().setLayout(new FlowLayout());
frame.pack();
frame.setVisible(true);
// ********************************************
// INTERESTING CODE HERE. We schedule a runnable which assert's false
// but we never see a console assert error!
// ********************************************
ScheduledFuture<?> future = sExecutor.schedule(new Runnable() {
@Override
public void run() {
doAssertFalse();
}
}, 0, TimeUnit.SECONDS);
future.get();
}
public static void doAssertFalse()
{
System.out.println("About to assert False");
assert false;
System.out.println("Done asserting False");
}
Notice I'm saving the result of schedule
into a ScheduledFuture
variable. The exception isn't returned until you call the get()
method on the future. All exceptions are thrown wrapped in an ExecutionException
.
Unfortunately this blocks, so another way you can get the exception is like this:
// Swing GUI
private static void createAndShowGUI() {
// Just create a swing thing. Boring
JFrame frame = new JFrame("Title String");
JLabel label = new JLabel("Hello World");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label);
frame.getContentPane().setLayout(new FlowLayout());
frame.pack();
frame.setVisible(true);
// ********************************************
// INTERESTING CODE HERE. We schedule a runnable which assert's false
// but we never see a console assert error!
// ********************************************
sExecutor.schedule(new Runnable() {
@Override
public void run() {
try {
doAssertFalse();
} catch (Error e) {
e.printStackTrace();
}
}
}, 0, TimeUnit.SECONDS);
}
public static void doAssertFalse() {
System.out.println("About to assert False");
assert false;
System.out.println("Done asserting False");
}
Notice that I'm catching an Error, not an Exception. I'm doing this because Assertions throw a java.lang.AssertionError, not a *Exception.
I'm having trouble finding any documentation in the Javadoc saying that the ScheduledExecutorService swallows exceptions unless you do these things, but through my tests that appears to be the case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With