文档章节

关于JFinal中Jetty的类加载器问题

33号小人物
 33号小人物
发布于 2015/09/21 15:04
字数 908
阅读 81
收藏 0

1、问题描述

首先是我遇到的问题现象是:前文1 前文2 前文3 前文4

经过一个星期得顺藤摸瓜,最后找到了问题得根源是,ClassLoader不同的问题。引用别人博文的话:

Java中,一个类用其完全匹配类名(fully qualified class name)作为标识,这里指的完全匹配类名包括包名和类名。但在JVM一个类用其全名和一个加载类ClassLoader的实例作为唯一标识,不同类加载器加载的类将被置于不同的命名空间。

因此,在JFinal中的modelToTableMap和modelToConfigMap,虽然Map中都保存着名字相同的类对象,但是由于使用了不同的ClassLoader,也是无法从Map中get到值,每次都是返回Null。

在我的项目中,使用了ServletContextListener来执行一个定时任务,这里使用的ClassLoader是WebAppClassLoader。而在JFinal初始化配置的时候,却使用了AppClassLoader。

另外就是,我使用了Maven来进行了Jar包的管理。

2、ClassLoader的相关知识

首先,AppClassLoader是属于JVM的ClassLoader体系中的一个,属于系统类加载器,另外两个是ExtClassLoader和Bootstrap Loader。三者之间存在的父类委托机制,就是子类接受类加载的请求时,先向父类进行类进行委托加载,如果父类有,则使用父类的加载器,如果没有,才使用子类自身类加载器。


  1. Bootstrap ClassLoader,负责加载java基础类,主要是 %JRE_HOME/lib目录下的jar和class

  2. Extension ClassLoader,负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class

  3. App ClassLoader,负责加载当前java应用的classpath中的所有类。

然后再说WebAppClassLoader,它是属于特殊的加载机制,它先试图自己载入类(在ContextPath/WEB-INF/lib和classes中载入类),如果无法载入,再请求父ClassLoader完成。 于WEB APP线程,它的contextClassLoader是WebAppClassLoader 。对于Tomcat Server线程,它的contextClassLoader是CatalinaClassLoader  。

根据以上的知识,大概可以把问题解释清楚了。

JFinal的jar包是通过Maven添加到项目中,虽然是添加到了classpath当中,但是并没有放到WEB-INF/lib目录下面。因此,在使用ServletContextListener启动的定时任务时,使用的类加载器是WebAppClassLoader。JFinal进行初始化时,默认也是优先从WebAppClassLoader的目录下寻找相应的类文件,但是由于lib下没有,因此转而向AppClassLoader发出请求,这时就遵循父类委托机制。最后,在ClassPath中找到,也就是Maven中,所以就使用了AppClassLoader。

3、问题

方法一:把定时任务,也放到JFinal中去启动,而不是使用ServletContext,这样就保证了定时任务和JFinal的对象都是在同一个ClassLoader中,就是AppClassLoader。

方法二:把JFinal-1.9.jar包放到WEB-INF/lib目录下,这样就能够保证两者的对象在同一个ClassLoader中,这时就是WebAppClassLoader。

其实,这也是在开发调试中才会遇到的问题,如果打包成war包,放到Tomcat中运行的话,也是不会出现这个问题的。因为,所有使用的jar包都会导出到WEB-INF/lib目录下。

以上就是我个人在该问题中的经验总结,希望能够帮助到大家,谢谢~



© 著作权归作者所有

33号小人物
粉丝 1
博文 3
码字总数 2040
作品 0
广州
高级程序员
私信 提问
加载中

评论(2)

33号小人物
33号小人物 博主

引用来自“JFinal”的评论

有这种钻研精神,任何问题都可以解决。另外既然是 maven 管理项目,就让所有 jar 全用 maven 来管理, WEB-INF/lib 下保持干净,就能避免这类问题的发生
谢谢zhan大神的支持和鼓励。其实我几乎所有的包都用Maven管理了,包括Jetty,但是ServletContextListener是属于Web容器的东西,它的加载会默认使用WebAppClassLoader,而其他的jar由于不在WEB-INF/lib下,就会使用系统类加载器AppClassLoader。
JFinal
JFinal
有这种钻研精神,任何问题都可以解决。另外既然是 maven 管理项目,就让所有 jar 全用 maven 来管理, WEB-INF/lib 下保持干净,就能避免这类问题的发生
JFinal 3.5 发布,将能上的菜先上了

jfinal 新功能经过 6 个月的酝酿、开发,在大幅度的创新来临之前,jfinal 3.5 这一版先稳一稳,趁着国庆长假,将能上的菜先上了。 jfinal 3.5 这一版针对这 6 个月以来用户反馈最强烈、最频繁...

JFinal
2018/10/08
1.2W
101
JFinal如何调整jetty启动的jvm参数

jfinal像tomcatplug那样利用工作空间作为部署目录。并且检测类文件变化实现动态加载部署。 由于类信息在jvm的永生区存放,并且每次重启是不会释放永生区的内存的,所有不断修改类之后会导致永...

绝望的八皮
2012/07/04
9.7K
5
OSC上关于Jfinal的提问整理(一)

看见Jfinal很火,就手痒痒了,想学一下,无奈入门较慢,没有找到比较全的文档。于是就经常看讨论区大家的提问与解答。后来就忽然萌生了整理下来的想法。其中的问题如果是@Jfinal 回答的,那我...

木川瓦兹
2013/04/23
7.9K
21
最近在做的一件事件编写JFinal教程《Jfinal极速开发实战》

从8月1号开始,整整一个月,初稿完成,朋友帮我第一次文字校对完成,现在正在根据波总的意见修改一些jfinal的设计原则说明 Jfinal、JfinalUIB学习交流QQ群:309647612 已经完成,前四章免费阅...

littleant
2015/08/20
2.6K
12
关于JFinal的JFinalFilter的一个小建议

@JFinal 之前有个朋友说他的Tomcat下有多个Web工程,都是使用JFinal,所以想把JFinal的包统一放在Tomcat的lib下去,发现启动的时候报异常说JFinalFilter在初始化的时候找不到他Webapp这边自定...

逝水fox
2013/09/29
1.4K
5

没有更多内容

加载失败,请刷新页面

加载更多

如何在PHP中获取字符串的最后一个字符?

我需要获取字符串的最后一个字符。 假设我有“测试人员”作为输入字符串,并且我希望结果为“ s”。 如何在PHP中做到这一点? #1楼 请记住,如果有一个字符串使用fgets()函数从文本文件中读取...

javail
30分钟前
56
0
DaY07方法重写的面试题

方法重写的面试题 * Override和Overload的区别?Overload能改变返回值类型吗? * overload可以改变返回值类型,只看参数列表 * 方法重写:子类中出现了和父类中方法声明一模一样的方法。与返回值...

Lao鹰
33分钟前
43
0
用Markdown编程之类型

类型就是约定。而现有的类型是单纬度的。用标注法编程好处就是可以多维度。 类型基础分为: 虚 实 在此之上分为: 根 寄存器级 联 内存级 外 网络级 虚:说白了就是指针或索引之类的概念。之...

dwcz
51分钟前
66
0
每天AC系列(四):四数之和

1 题目 Leetcode第18题,给定一个数组与一个target,找出数组中的四个数之和为target的不重复的所有四个数. 2 暴力 List<List<Integer>> result = new ArrayList<>();if (nums.length == 4 &......

Blueeeeeee
今天
70
0
git clone --mirror和git clone --bare有什么区别

git clone帮助页面上有关于--mirror : 设置远程存储库的镜像。 这意味着--bare 。 但没有详细介绍--mirror克隆与--bare克隆--mirror不同。 #1楼 克隆将从远程服务器复制参考,并将其填充到名...

技术盛宴
今天
86
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部