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

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

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

  • Java

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

    3168 引用 • 8207 回帖
  • 反射
    18 引用 • 29 回帖
  • Q&A

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

    6542 引用 • 29405 回帖 • 245 关注

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 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 加载器啊,肯定不再出现这个问题,可能直接就从缓存里找到了。

推荐标签 标签

  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖 • 5 关注
  • Elasticsearch

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

    116 引用 • 99 回帖 • 267 关注
  • sts
    2 引用 • 2 回帖 • 149 关注
  • 周末

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

    14 引用 • 297 回帖 • 1 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    21 引用 • 140 回帖 • 25 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 2 关注
  • 分享

    有什么新发现就分享给大家吧!

    242 引用 • 1747 回帖 • 1 关注
  • gRpc
    10 引用 • 8 回帖 • 54 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    85 引用 • 1201 回帖 • 450 关注
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖 • 1 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 3 关注
  • OnlyOffice
    4 引用 • 26 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    675 引用 • 535 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    53 引用 • 85 回帖
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 17 关注
  • Postman

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

    4 引用 • 3 回帖
  • 百度

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

    63 引用 • 785 回帖 • 253 关注
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    324 引用 • 1395 回帖 • 1 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 685 关注
  • RabbitMQ

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

    49 引用 • 60 回帖 • 395 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 126 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    16 引用 • 53 回帖 • 123 关注
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    20 引用 • 245 回帖 • 229 关注
  • Pipe

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

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

    131 引用 • 1114 回帖 • 152 关注
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 424 关注