在通过 java 反射调用的方法中,为什么使用 Class.forName() 加载类会出异常?

本贴最后更新于 2407 天前,其中的信息可能已经时移世改

我利用反射执行 insert 方法,在该方法中执行到 Class.forName("org.jsoup.Jsoup")抛异常。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3198 引用 • 8215 回帖 • 1 关注
  • 反射
    20 引用 • 29 回帖
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    9646 引用 • 43853 回帖 • 95 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 860562369 1

    Class.forName(),参数是一个文件路径,要是找不到你传入的路径,可不就得抛出异常

    1 回复
  • nuaa123 1
    作者

    以下是我在众多博客中找到的稍微靠谱点的博文,大概原因就是 Tomcat 有自己的类加载器,必须要把第三方 jar 包放在 tomcat 的 lib 文件夹下面。亲测问题解决。

    在这篇博文中 java 动态加载指定的类或者 jar 包反射调用其方法,介绍动态加载指定的类,当时我是拿 URLClassLoader 介绍的,当然可以自定义一个 ClassLoader 重写对应的方法, 不过这个有现成的比自己重写更强大为何不用。

           话不多说,很久不写博客了,时间太紧了,起因还是一个网友私信我,说他反射创建某个对象时涉及其他 jar 中的类就会报 ClassNotFound 异常。

           其实,我也遇到过这个问题,在项目中反射创建一个 service 也是这样的,涉及到第三方的 jar 可能就出这问题,当时我可是纠结了好久,花了好几天时间去解决,请教过诸多大神和网友,不过还是不行,问题沉溺了有一阵子。

           网上很少又提到这个问题的。最近又请教几个有经验的网友说是没有 findClass 的原因,或是类名或者 service 的原因,应该是我描述问题没描述清楚吧。而且关键这个 jar 呀你不反射创建项目中用的好好的,就和昨天晚上私信我的那个网友一样,按 JVM 的双亲委托模型不应该啊,不熟悉的可以看看这译文个深入分析 Java ClassLoader 原理,自定义或者 URLClassLoader 的父加载器是 App ClassLoader,而这个 jar 或者类肯定它会找到并加载或者提前就加载到 JVM 里呢,怎么回事呢。

           其实你如果这样想,我们都犯了一个严重的错误,就是我们不是单纯依托与 JVM,程序结束就 OK 了,可能你测试的时候没问题,已到项目就有这问题。问题在于我们往往是运行在个应用服务器下,一般都是 tomcat 吧,而 tomcat 有自己的一套加载机制,有自己一些加载器,我们忽略这个因素才是导致了问题发生的根本原因。

           我们忽略了 tomcat 内部自定义的类加载器只想到了 JVM 的那几个加载器,tomcat 有个叫 webApp 的加载器它是先加载 WEB-INF/classes 后在加载 WEB-INF/lib,但它的父加载器是它的 common 加载器,comon 的父加载器是 system 加载器(和 JVM 的应用程序加载器功能差不多,不过指定了其他 tomcat 目录下的加载,大家可以看看官网上的英文文档),但是源码中这个加载器是 URLClassLoader 的子类,而 URLClassLoader 默认父加载 tomcat 下是它的 system 加载器这么设计和 tomcat 的配置有关,默认为无为 false,会直接委托给 tomcat 的 system 加载器加载 system 委托最顶层的 Bootstrap 加载器(差不多是 JVM 里起始加载器和扩展加载器的合并),但不管怎么样,项目在 tomcat 下自定义的或者 URLClassLoader 加载默认父加载器都不会是 tomcat 的 webApp 加载器而是 system 加载器,或者自定义的加载器或 URLClassLoader 和 tomcat 的 webApp 加载器没有上下关系,所以动态创建类时设计到其他类时肯定会报 CNF 异常。

          解决思路就是先获取当前类的 Class,然后获取当前类的加载器,在自定义的加载器或者 URLClassLoader 加载器创建时指定为它们的父加载器,这样问题就会游刃而解了,可能平常我们测试写个简单的例子没遇到这个问题,因为我们那时的 URLClassLoader 或者自定义的加载器的父加载器都是 JVM 的第三次加载器即应用程序加载,它是专门加载 classpath 下边的或者指定的类或者 jar 的,依照双亲委托模型,肯定会找到引入路径的那个类或者 jar 的。

         或者我们使用 Class.forName()的方式来动态加载指定的类,就不会存在这个问题,因为这种方式一方面是能初始化类的静态东西,再就是重要一点,就是采用的加载当前所在类的加载器来加载你指定的类,这样你在 tomcat 下那就是它的 webApp 加载器啊,肯定不再出现这个问题,可能直接就从缓存里找到了。

推荐标签 标签

  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 209 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 3 关注
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 2 关注
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    151 引用 • 257 回帖 • 1 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 368 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 46 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    63 引用 • 289 回帖 • 1 关注
  • Visio
    1 引用 • 2 回帖 • 2 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 547 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 119 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 2 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 343 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 652 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    315 引用 • 547 回帖
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    187 引用 • 318 回帖 • 256 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    494 引用 • 928 回帖
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 29 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    133 引用 • 1124 回帖 • 116 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 99 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖 • 3 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    556 引用 • 675 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖 • 3 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 612 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖