当从runnable调用时,Java断言不发送到控制台

当从runnable调用时,Java断言不发送到控制台,java,assert,runnable,Java,Assert,Runnable,在我的程序中,我从runnable中创建了一个断言(其计算结果为false),但从未看到任何有关该断言的控制台输出。我想知道我的断言是否为假,但runnable似乎正在捕获所有抛出的断言 下面是我可以编写的用来演示的最简单的示例程序。 (断言已启用。如果未启用,程序将表现不同,并打印两行而不是一行)。 程序的输出为 即将断言错误 就这样。在那之后,assert语句抛出并被某些东西捕获,我对此一无所知。我想知道,我做错了什么 import java.nio.ByteBuffer; import j

在我的程序中,我从runnable中创建了一个断言(其计算结果为false),但从未看到任何有关该断言的控制台输出。我想知道我的断言是否为假,但runnable似乎正在捕获所有抛出的断言

下面是我可以编写的用来演示的最简单的示例程序。
(断言已启用。如果未启用,程序将表现不同,并打印两行而不是一行)。 程序的输出为

即将断言错误

就这样。在那之后,assert语句抛出并被某些东西捕获,我对此一无所知。我想知道,我做错了什么

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");
  }
}
这可以做到:

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");
}
请注意,我捕获的是一个错误,而不是异常。我这样做是因为断言抛出java.lang.AssertionError,而不是*异常


我在Javadoc中找不到任何文档说明ScheduledExecutorService会接受异常,除非您执行这些操作,但通过我的测试,情况似乎是这样

线程不会对异常执行任何操作(怎么可能?如果不使用STDERR或STDOUT而是登录到数据库,Thread.run()怎么可能知道在哪里记录异常或将异常转发给谁?)

您可以使用Thread.UncaughtExceptionHandler,当您这样做时,您的断言应该可以完成

我认为问题在于Assert的机制使用异常,因此必须遵循预先确定的异常规则。就我个人而言,我不介意Assert只是打印一个堆栈转储并执行一个退出(0),因为您无论如何都不应该捕获该异常——但它就是这样

注意:您也可以对应用程序中的所有线程使用Thread.setDefaultUncaughtExceptionHandler一次(请注意“默认值”)。。。这应该是一个很好的通用解决方案

import java.lang.*; public class ThreadDemo { public static void main(String[] args) { Thread t = new Thread(new adminThread()); t.setUncaughtExceptionHandler(new Thread. UncaughtExceptionHandler() { public void uncaughtException(Thread t2, Throwable e) { System.out.println(t2 + " throws exception: " + e); } }); // this will call run() function t.start(); } } class adminThread implements Runnable { public void run() { assert(false); throw new RuntimeException(); } } 导入java.lang.*; 公共类线程演示{ 公共静态void main(字符串[]args){ 线程t=新线程(新adminThread()); t、 setUncaughtExceptionHandler(新线程)。 UncaughtExceptionHandler(){ 公共无效未捕获异常(线程t2,可丢弃e){ System.out.println(t2+“抛出异常:”+e); } }); //这将调用run()函数 t、 start(); } } 类adminThread实现可运行{ 公开募捐{ 断言(假); 抛出新的RuntimeException(); } }
当我运行这个“正常”时,它显示抛出了RuntimeException。当我使用“-ea”选项运行时,它会显示一个AssertException。试一试。

启动应用程序时是否在命令行上启用了断言?断言已启用。如果没有,程序的行为会有所不同(它将打印两行而不是一行),可能与与线程关联的
UncaughtExceptionHandler
有关。您是否尝试过设置自定义异常,以查看是否可以看到断言异常通过?@Laf:您如何使用执行器实现这一点?执行器为您创建
线程,但不允许您访问它们(afaik),您需要在
线程
实例上放置一个
UncaughtExceptionHandler
。@DanielKaplan我还没有真正测试过它,所以我可能完全错了,
线程
是一个可运行的
线程,因此,您可以使用代码创建自己的
线程
实现,并将自定义
UncaughtExceptionHandler
关联到此线程,然后在调用执行器时将其用作参数。我不知道这是否会有所不同。无论如何,您提供的答案可能比我的建议更有效。没错,断言引发的异常将被捕获并打印。但我的印象是,你可以添加断言,这样程序员就可以知道出了什么问题。我是否必须在我编写的每个断言(或断言方法)周围添加一个try-catch块?从技术上讲,抛出的不是异常,而是错误。这就是您遇到问题的原因。我的思考过程是“嗯,我想确保numApples永远不会为负,所以我将添加一个断言!”assert numApples>=0。但有时,当断言是错误的,我没有得到通知。一个尝试的catch块必须与每一个断言一致吗?我认为这是一个解决办法,而不是问题的答案。@波希米亚,你为什么这么说?这听起来好像应该起作用,但是当我尝试它时,它没有。我希望有一种方法可以将代码块粘贴到注释中,以提供更多细节。我实现了main()的第一行调用
Thread.setDefaultUncaughtExceptionHandler
,impl只是说
e.printStackTrace()。但是仍然没有输出到控制台它没有击中它。这是一种“稻草人”的回答。在他的场景中,他使用了一个预定的执行者。在这种情况下,一切都不同了。在这种情况下,这里的答案会给你一个选项:是的,这是一个类似的场景。我在回答中提到了这个解决方案。
import java.lang.*;

public class ThreadDemo {

   public static void main(String[] args) {

     Thread t = new Thread(new adminThread());

     t.setUncaughtExceptionHandler(new Thread.
     UncaughtExceptionHandler() {
        public void uncaughtException(Thread t2, Throwable e) {
           System.out.println(t2 + " throws exception: " + e);
        }
     });
     // this will call run() function
     t.start();

   }
}

class adminThread implements Runnable {

   public void run() {
      assert(false);
      throw new RuntimeException();
   }
}