美文网首页
消除java异常开销

消除java异常开销

作者: fengjixcuhui | 来源:发表于2017-07-09 00:36 被阅读0次

抛异常的最大开销是异常栈的构建过程,如果你的程序调用很深,特别是用了第三方开源框架,这个开销是不容忽视的

开销在哪

查看jdk源码

    /**
     * Constructs a new throwable with the specified cause and a detail
     * message of {@code (cause==null ? null : cause.toString())} (which
     * typically contains the class and detail message of {@code cause}).
     * This constructor is useful for throwables that are little more than
     * wrappers for other throwables (for example, {@link
     * java.security.PrivilegedActionException}).
     *
     * <p>The {@link #fillInStackTrace()} method is called to initialize
     * the stack trace data in the newly created throwable.
     *
     * @param  cause the cause (which is saved for later retrieval by the
     *         {@link #getCause()} method).  (A {@code null} value is
     *         permitted, and indicates that the cause is nonexistent or
     *         unknown.)
     * @since  1.4
     */
    public Throwable(Throwable cause) {
        fillInStackTrace();
        detailMessage = (cause==null ? null : cause.toString());
        this.cause = cause;
    }

主要的性能瓶颈在fillInStackTrace,这是一个native方法.会构建整个异常栈. 方法签名如下

/**
     * Fills in the execution stack trace. This method records within this
     * {@code Throwable} object information about the current state of
     * the stack frames for the current thread.
     *
     * <p>If the stack trace of this {@code Throwable} {@linkplain
     * Throwable#Throwable(String, Throwable, boolean, boolean) is not
     * writable}, calling this method has no effect.
     *
     * @return  a reference to this {@code Throwable} instance.
     * @see     java.lang.Throwable#printStackTrace()
     */
    public synchronized Throwable fillInStackTrace() {
        if (stackTrace != null ||
            backtrace != null /* Out of protocol state */ ) {
            fillInStackTrace(0);
            stackTrace = UNASSIGNED_STACK;
        }
        return this;
    }

 private native Throwable fillInStackTrace(int dummy);

如何解决

  1. 创建异常类的时候重写fillInStackTrace方法.java7原生支持
protected Throwable(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
        if (writableStackTrace) {
            fillInStackTrace();
        } else {
            stackTrace = null;
        }
        detailMessage = message;
        this.cause = cause;
        if (!enableSuppression)
            suppressedExceptions = null;
    }
  1. 去掉异常.现在很多业务系统用异常实现程序正常业务逻辑.这个对性能影响比较大,尤其是并发比较大的时候.

寻找异常

有时候你无法知道那个异常抛的最多,有些三方包 自己throw Exception 但自己又catch住.

  • brace 跟踪Exception <init> 对异常栈,汇总
  • perf top去看下us的开销,如果_ZN19java_lang_Throwable19fill_in_stack_traceE6HandleP6Thread这个排名很靠前,那就好好检查下.

讨论

用异常实现正常的业务流程有以下优点

  1. 代码比较精炼.增强代码可读性.可以不用对服务方法设计统一的返回值
  2. 可以使用切面技术(拦截器 异常处理器) 对异常做统一的监控 和处理.

缺点:性能
改进:

  • 不构建异常堆栈,而是保存失败原因FailCause或者错误码
  • 重写fillInStackTrace方法进行noop

参考

知乎上有异常作为业务流程控制的讨论.请移步
https://www.zhihu.com/question/21405047

相关文章

  • 消除java异常开销

    抛异常的最大开销是异常栈的构建过程,如果你的程序调用很深,特别是用了第三方开源框架,这个开销是不容忽视的 开销在哪...

  • 已检查异常也可在运行时抛出

    Java 异常处理的一个基本原则是, 必须为所有已检查异常提供一个处理器.不过可以利用泛型消除这个限制 在这里, ...

  • 空指针异常(java.lang.NullPointerExce

    Java空指针异常(java.lang.NullPointerException) Java空指针异常(java....

  • Java 异常分析

    本文是对以下内容的分析: Java异常设计 Java 异常分类 Java异常可以告诉什么问题 Java异常处理最佳...

  • 廖雪峰Java 读书笔记 (二) 异常处理

    1. Java的异常 Java使用异常来表示错误,并通过try ... catch捕获异常; Java的异常是cl...

  • Java异常

    Java异常 java异常分为两大类,Checked异常和Runtime异常,Checked异常都是在编译阶段可以...

  • Java 异常处理-Android面试准备2019-2-10

    异常分类 Java将异常分为两种,Checked异常和Runtime异常。Java认为Checked异常都是可以在...

  • 异常

    Java异常体系 异常的分类 Java的异常分为两大类:Checked异常和Runtime异常(运行时异常)。所有...

  • Java异常简介及其架构

    Java异常简介 Java异常是Java提供的一种识别及响应错误的一致性机制。Java异常机制可以使程序中异常处理...

  • Java异常面试题(总结最全面的面试题)

    Java异常架构与异常关键字 Java异常简介 Java异常是Java提供的一种识别及响应错误的一致性机制。Jav...

网友评论

      本文标题:消除java异常开销

      本文链接:https://www.haomeiwen.com/subject/zatshxtx.html