前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊ElasticsearchUncaughtExceptionHandler

聊聊ElasticsearchUncaughtExceptionHandler

原创
作者头像
code4it
发布2019-05-29 22:29:03
5870
发布2019-05-29 22:29:03
举报
文章被收录于专栏:码匠的流水账

本文主要研究一下ElasticsearchUncaughtExceptionHandler

ElasticsearchUncaughtExceptionHandler

代码语言:javascript
复制
class ElasticsearchUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    private static final Logger logger = LogManager.getLogger(ElasticsearchUncaughtExceptionHandler.class);
​
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (isFatalUncaught(e)) {
            try {
                onFatalUncaught(t.getName(), e);
            } finally {
                // we use specific error codes in case the above notification failed, at least we
                // will have some indication of the error bringing us down
                if (e instanceof InternalError) {
                    halt(128);
                } else if (e instanceof OutOfMemoryError) {
                    halt(127);
                } else if (e instanceof StackOverflowError) {
                    halt(126);
                } else if (e instanceof UnknownError) {
                    halt(125);
                } else if (e instanceof IOError) {
                    halt(124);
                } else {
                    halt(1);
                }
            }
        } else {
            onNonFatalUncaught(t.getName(), e);
        }
    }
​
    static boolean isFatalUncaught(Throwable e) {
        return e instanceof Error;
    }
​
    void onFatalUncaught(final String threadName, final Throwable t) {
        logger.error(() -> new ParameterizedMessage("fatal error in thread [{}], exiting", threadName), t);
    }
​
    void onNonFatalUncaught(final String threadName, final Throwable t) {
        logger.warn(() -> new ParameterizedMessage("uncaught exception in thread [{}]", threadName), t);
    }
​
    void halt(int status) {
        AccessController.doPrivileged(new PrivilegedHaltAction(status));
    }
​
    static class PrivilegedHaltAction implements PrivilegedAction<Void> {
​
        private final int status;
​
        private PrivilegedHaltAction(final int status) {
            this.status = status;
        }
​
        @SuppressForbidden(reason = "halt")
        @Override
        public Void run() {
            // we halt to prevent shutdown hooks from running
            Runtime.getRuntime().halt(status);
            return null;
        }
​
    }
​
}
  • ElasticsearchUncaughtExceptionHandler实现了Thread.UncaughtExceptionHandler接口
  • uncaughtException方法首先判断throwable是否是Error类型,是的话则执行onFatalUncaught(logger.error),然后执行halt方法,不是则执行onNonFatalUncaught(logger.warn)
  • halt方法AccessController.doPrivileged来执行对应status的PrivilegedHaltAction,该action执行的是Runtime.getRuntime().halt(status)

Bootstrap.init

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java

代码语言:javascript
复制
final class Bootstrap {
​
    private static volatile Bootstrap INSTANCE;
    private volatile Node node;
    private final CountDownLatch keepAliveLatch = new CountDownLatch(1);
    private final Thread keepAliveThread;
    private final Spawner spawner = new Spawner();
​
    //......
​
    static void init(
            final boolean foreground,
            final Path pidFile,
            final boolean quiet,
            final Environment initialEnv) throws BootstrapException, NodeValidationException, UserException {
        // force the class initializer for BootstrapInfo to run before
        // the security manager is installed
        BootstrapInfo.init();
​
        INSTANCE = new Bootstrap();
​
        final SecureSettings keystore = loadSecureSettings(initialEnv);
        final Environment environment = createEnvironment(pidFile, keystore, initialEnv.settings(), initialEnv.configFile());
​
        LogConfigurator.setNodeName(Node.NODE_NAME_SETTING.get(environment.settings()));
        try {
            LogConfigurator.configure(environment);
        } catch (IOException e) {
            throw new BootstrapException(e);
        }
        if (environment.pidFile() != null) {
            try {
                PidFile.create(environment.pidFile(), true);
            } catch (IOException e) {
                throw new BootstrapException(e);
            }
        }
​
        final boolean closeStandardStreams = (foreground == false) || quiet;
        try {
            if (closeStandardStreams) {
                final Logger rootLogger = LogManager.getRootLogger();
                final Appender maybeConsoleAppender = Loggers.findAppender(rootLogger, ConsoleAppender.class);
                if (maybeConsoleAppender != null) {
                    Loggers.removeAppender(rootLogger, maybeConsoleAppender);
                }
                closeSystOut();
            }
​
            // fail if somebody replaced the lucene jars
            checkLucene();
​
            // install the default uncaught exception handler; must be done before security is
            // initialized as we do not want to grant the runtime permission
            // setDefaultUncaughtExceptionHandler
            Thread.setDefaultUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler());
​
            INSTANCE.setup(true, environment);
​
            try {
                // any secure settings must be read during node construction
                IOUtils.close(keystore);
            } catch (IOException e) {
                throw new BootstrapException(e);
            }
​
            INSTANCE.start();
​
            if (closeStandardStreams) {
                closeSysError();
            }
        } catch (NodeValidationException | RuntimeException e) {
            // disable console logging, so user does not see the exception twice (jvm will show it already)
            final Logger rootLogger = LogManager.getRootLogger();
            final Appender maybeConsoleAppender = Loggers.findAppender(rootLogger, ConsoleAppender.class);
            if (foreground && maybeConsoleAppender != null) {
                Loggers.removeAppender(rootLogger, maybeConsoleAppender);
            }
            Logger logger = LogManager.getLogger(Bootstrap.class);
            // HACK, it sucks to do this, but we will run users out of disk space otherwise
            if (e instanceof CreationException) {
                // guice: log the shortened exc to the log file
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                PrintStream ps = null;
                try {
                    ps = new PrintStream(os, false, "UTF-8");
                } catch (UnsupportedEncodingException uee) {
                    assert false;
                    e.addSuppressed(uee);
                }
                new StartupException(e).printStackTrace(ps);
                ps.flush();
                try {
                    logger.error("Guice Exception: {}", os.toString("UTF-8"));
                } catch (UnsupportedEncodingException uee) {
                    assert false;
                    e.addSuppressed(uee);
                }
            } else if (e instanceof NodeValidationException) {
                logger.error("node validation exception\n{}", e.getMessage());
            } else {
                // full exception
                logger.error("Exception", e);
            }
            // re-enable it if appropriate, so they can see any logging during the shutdown process
            if (foreground && maybeConsoleAppender != null) {
                Loggers.addAppender(rootLogger, maybeConsoleAppender);
            }
​
            throw e;
        }
    }
​
    //......
}
  • Bootstrap的init静态方法使用Thread.setDefaultUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler())来给线程设置defaultUncaughtExceptionHandler

小结

  • ElasticsearchUncaughtExceptionHandler实现了Thread.UncaughtExceptionHandler接口;uncaughtException方法首先判断throwable是否是Error类型,是的话则执行onFatalUncaught(logger.error),然后执行halt方法,不是则执行onNonFatalUncaught(logger.warn)
  • halt方法AccessController.doPrivileged来执行对应status的PrivilegedHaltAction,该action执行的是Runtime.getRuntime().halt(status)
  • Bootstrap的init静态方法使用Thread.setDefaultUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler())来给线程设置defaultUncaughtExceptionHandler

doc

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ElasticsearchUncaughtExceptionHandler
  • Bootstrap.init
  • 小结
  • doc
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档