Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java asserts not send to console when called from a runnable

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");
  }
}
like image 688
Dijkstra Avatar asked Jan 15 '13 18:01

Dijkstra


People also ask

Why assert is not working in Java?

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.

Does assert throw an exception Java?

Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError .

How do you fix assertion errors?

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.

When should you use an assertion over an exception?

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.


1 Answers

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.

like image 86
Daniel Kaplan Avatar answered Sep 28 '22 01:09

Daniel Kaplan