jdk中动态代理异常处理分析:UndeclaredThrowableException

当使用 JDK 动态代理时,如果目标方法抛出一个未在代理接口上声明的异常时,会发生 UndeclaredThrowableException 异常。这个异常用于包装仅在运行时可知的受检查异常或 “错误”(Error)类型的异常(例如 java.io.IOExceptionjava.lang.OutOfMemoryError),从而响应于在虚拟机集线器(InvocationHandler)中调用目标方法的异常。下面给出详细的攻略:

JDK中动态代理异常处理分析:UndeclaredThrowableException

当我们使用 JDK 动态代理进行方法调用时,如果目标方法抛出一个未在代理接口上声明的异常,就会发生 UndeclaredThrowableException 异常,如下所示:

interface Foo {
    void foo() throws Exception;
}

class FooImpl implements Foo {
    public void foo() throws Exception {
        throw new Exception();
    }
}

class Main {
    public static void main(String[] args) {
        Handler handler = new Handler(new FooImpl());
        Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler);

        try {
            foo.foo();
        } catch (UndeclaredThrowableException e) {
            System.out.println(e.getCause());
        }
    }
}

class Handler implements InvocationHandler {
    private final Object target;

    public Handler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(target, args);
    }
}

输出结果是:java.lang.Exception

JDK 动态代理在执行方法调用时,是通过 InvocationHandler#invoke 方法进行拦截并进行处理的,但是 method.invoke() 抛出的异常类型只有两种:受检查异常和未经检查的异常。受检查异常需要在接口中声明,而未经检查的异常则不需要。我们可以通过在调用 invoke 方法时设置异常处理程序来处理受检查异常和未经检查的异常。

如果目标方法抛出一个未在代理接口上声明的受检查异常,那么运行时系统将使用 UndeclaredThrowableException 异常,该异常的 getCause() 方法返回由 method.invoke() 抛出的实际异常。

例如,如果上面的 Foo 接口从 Exception 中继承 Throwable,那么上面的代码将打印 java.lang.Exception,而不是 UndeclaredThrowableException

下面再给出一个例子:

interface Bar {
    void bar() throws Exception;
}

class BarImpl implements Bar {
    public void bar() {
        throw new RuntimeException();
    }
}

class Main {
    public static void main(String[] args) {
        Handler handler = new Handler(new BarImpl());
        Bar bar = (Bar) Proxy.newProxyInstance(Bar.class.getClassLoader(), new Class<?>[] { Bar.class }, handler);

        try {
            bar.bar();
        } catch (UndeclaredThrowableException e) {
            System.out.println(e.getCause());
        }
    }
}

class Handler implements InvocationHandler {
    private final Object target;

    public Handler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return method.invoke(target, args);
        } catch (UndeclaredThrowableException e) {
            throw e.getCause();
        }
    }
}

在这个例子中,BarImpl#bar() 抛出一个未经检查的异常。由于未经检查的异常不需要在接口中声明,因此我们无法使用检查异常来处理它们。我们需要在 InvocationHandler#invoke 方法中捕获并重新抛出 UndeclaredThrowableException 异常。此时 UndeclaredThrowableException 异常的 getCause() 方法返回实际抛出的异常,这个例子中就是 RuntimeException

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:jdk中动态代理异常处理分析:UndeclaredThrowableException - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • JDBC Template基本使用方法详解

    JDBC Template基本使用方法详解 JDBC Template简介 JDBC(Java Database Connectivity)是一个Java语言访问数据库的接口,JDBC Template是使用JDBC进行数据库操作的常用工具类,该类能够自动化处理资源申请、资源释放等常规流程,并提供了诸如CRUD、批量操作、分页查询等常用数据库操作方法,使用J…

    Java 2023年6月16日
    00
  • Ubuntu16.04安装部署solr7的图文详细教程

    下面是“Ubuntu16.04安装部署solr7的图文详细教程”的完整攻略: 环境准备 安装Java Solr 7 需要运行在 Java 8 上,所以我们需要先安装 Java 8。 在终端中输入以下命令进行安装: sudo add-apt-repository ppa:webupd8team/java sudo apt update sudo apt ins…

    Java 2023年5月19日
    00
  • 64位Windows2008系统下IIS7和Tomcat7整合共用80端口如何解决

    整合IIS7和Tomcat7共用80端口是一种常见的Web服务器配置,但对于64位的Windows2008系统,由于其内核和系统的一些限制,如果不加以特殊处理,在IIS7和Tomcat7同时运行时会遇到80端口被占用、无法访问、无法共享Session等问题。以下是在64位Windows2008系统下整合IIS7和Tomcat7共用80端口的完整攻略。 步骤一…

    Java 2023年6月15日
    00
  • JSP由浅入深(9)—— JSP Sessions

    下面是关于 JSP Sessions 的完整攻略。 什么是 JSP Sessions 在学习 JSP 开发过程中,我们经常需要存储一些用户的数据,比如用户的登录信息、购物车中的商品、用户的浏览记录等等。这些数据需要在不同的页面之间传递或者在同一个页面中进行共享。而 JSP Sessions 就是一种实现数据共享的技术。 Session 在 JSP 中是一个用…

    Java 2023年6月15日
    00
  • 如何进行Java并发编程?

    下面是关于如何进行Java并发编程的完整使用攻略。 1. 理解Java的并发问题 在开始了解如何进行Java并发编程之前,首先我们需要对Java的并发问题进行了解。Java并发问题主要体现在多线程协同执行的过程中,比如线程间的互斥、同步、等待-通知机制等。 2. Java中的并发编程工具 在Java中处理并发问题常用的工具包括线程、锁、Semaphore等。…

    Java 2023年5月11日
    00
  • Spring Security如何在Servlet中执行

    Spring Security 是 Spring 框架中的一个安全框架,可以用于保护 Web 应用程序的安全,包括身份验证、授权、防止攻击等功能。在 Servlet 中使用 Spring Security 可以有效地保护应用程序的安全,下面是详细的使用攻略。 1. 添加 Spring Security 依赖 首先,需要在项目中添加 Spring Securi…

    Java 2023年5月20日
    00
  • Java实时监控日志文件并输出的方法详解

    Java实时监控日志文件并输出的方法,可以使用Java IO和多线程的知识来完成。主要流程可以分为以下几步: 创建一个文件读取器,用于读取日志文件的内容。 定义一个线程类,用于不断读取文件内容,并输出到控制台或其他存储介质中。 开启线程,开始实时监控日志文件。 具体实现步骤如下: 1、创建一个文件读取器 使用Java IO中的FileReader和Buffe…

    Java 2023年5月26日
    00
  • SpringBoot整合Spring Security过滤器链加载执行流程源码分析(最新推荐)

    下面我来详细讲解一下 SpringBoot 整合 Spring Security 过滤器链加载执行流程源码分析的完整攻略。 1. 概述 Spring Security 是基于 Spring 框架实现的安全框架。它的作用是保护系统的安全性,可以对用户进行身份认证和权限控制。Spring Security 是一个强大而灵活的安全框架,它提供了多种安全特性,包括用…

    Java 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部