0
点赞
收藏
分享

微信扫一扫

intellij中启动jetty出现的类加载问题


背景

简单来说,就是使用intellij启动内嵌jetty的工程,爆出class not found exception,但是用eclipse启动没有问题,并且之前也是一直在eclipse中启动,最近尝鲜换成intellij才出现此问题。以下是具体配置

配置

开发环境

开发工具intellij
项目内嵌jetty+jFinal

问题
使用intellij启动,失败,工程以前都是在eclipse启动,一点问题没有,最近intellij大行其道才切换到intellij。

代码配置

public class MyJFinalConfig extends JFinalConfig{
    public static void main(String[] args) {
        JFinal.start("WebRoot", 8080, "/myproject", 5);
    }

}

web.xml配置

<filter>
        <filter-name>jfinal</filter-name>
        <filter-class>com.jfinal.core.JFinalFilter</filter-class>
        <init-param>
            <param-name>configClass</param-name>
            <param-value>com.mypak.MyJFinalConfig</param-value>
        </init-param>
    </filter>

异常信息class not found com.mypak.MyJFinalConfig

分析

追踪出错的源码

ps:代码大体上就是这样,只是为了表达那个意思。

Object obj = Class.forName("com.mypak.MyJFinalConfig").forInstance;
if(!obj instanceof JFinalFilter){
 throw new Exception("出错了")
}

classloader在捣鬼

我们知道MyJFinalConfigJFinalFilter 子类,它的实例肯定是JFinalFilter 实例,但是实际运行结果来看,居然不是!
第一反应想到可能是ClassLoader在捣鼓,因为ClassLoader不同时,类的上下级关系无从谈起,并且是jetty内嵌启动,不同于以往的正常启动,所以猜测可能跟classloader有关系。debug发现,MyJFinalConfig类加载器是sun.misc.Launcher$AppClassLoader,而JFinalFilter是jetty包中的WebAppClassLoader,果然classloader不一样!原因找到了。

为何eclipse可以work,intellij就不行呢?

搜索文章后发现,jetty的classloader会将WEB-INF/lib和 WEB-INF/classes底下的类,当作app的class,而不委托给父classloader。基于此,将intellij的outputpath设置为webRoot/WEB-INF/classes,让WebAppClassLoader加载MyJFinalConfig这样两个类就都是WebAppClassLoader 了。

修正

设置outputpath,将webRoot下的资源文件排除,否则classes文件夹下也有有页面等资源文件

D:\intellij_workspace\myproject\WebRoot\WEB-INF\classes。

intellij中启动jetty出现的类加载问题_eclipse

intellij中启动jetty出现的类加载问题_eclipse_02

后续

后来在看JFinal手册时,发现同样道理的一句话。此处的 Default out folder 必须要与 WebRoot\WEB-INF\classes 目录完全一致才可以使用 JFinal 集成的 Jetty 来启动项目

intellij中启动jetty出现的类加载问题_jetty_03

并且,作者也说使用重启方式,而不使用热加载方式开发,因为重启速度很快,如果热加载还会出现classnotfoundexception。当然资源文件,比如页面、js修改后,不需要重启。

intellij中启动jetty出现的类加载问题_重启_04


举报

相关推荐

0 条评论