背景

最近收到这样一个问题:

虽已回复,但心想还是看下storm这块的源码吧.那看静态多不爽啊,那总得调试吧,好吧,造个本地环境来调吧。

先看看maven的build过不过:

mvn -f pom.xml clean install

搞定storm的编译打包,接着是storm-starter的编译打包,一切很顺利啊,跑一下看看:

${STORM_HOME}/bin/storm jar ${STORM_JAR} ${STORM_STARTER_JAR} storm.starter.WordCountTopology

顺利出结果了,不就是个hello world嘛!

接着造本地环境吧,将storm-starter的源码按maven方式导入Intellij IDEA,注意,从这时候悲催就开始了。


hello,world 打脸了

导入IDE后,兴致勃勃的点了F5,然后:

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP

这尼玛,说好不打脸的!

看了又看依赖“都合适”啊,ClassPath“都合适”啊,否则编译不通过啊,为毛跑!不!起!来!

这同样的操作,在eclipse里妥妥的啊,各种能跑啊,为毛在Intellij IDEA里出错了呢?


异常是如何产生的

好吧,既然打脸了,又是知名IDE的粉丝,坚决要知耻而后勇的。

那么,看下异常如何产生的吧。

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP

上面的图,基本概括了异常NoClassDefFound产生的路径。

更细节的异常产生情况如下:

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP

注意看调用栈:

那么,既然有个找*.class的过程,这个过程如下:

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP

对上图做一点简要说明:


异常是如何处理的

好了,异常的产生清楚了,还有个问题,那个__pending_exception是何时被处理呢?

看下图:

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP

对上图做下简要说明:


为什么被打了脸

这里,异常产生的本质和异常处理,清楚了。

简单的概括下就是:

   /* 伪代码 */
main /* java这个程序的main */
-> createJVM() /* 创建JVM */
-> loadMainClass() /* 加载我们指定的$mainClass文件,这是个class文件 */
-> findMethod("main") /* 在$mainClass中找main方法,java写的程序的main */
-> getMethodFromJVM() /* 没缓存,问JVM要 */
-> classLoader.loadFromFile() /* 在classpath中找.class文件 */
-> 没找到,置异常NoClassDefFound.

但是,Intellij IDEA为何在运行时不将storm-core.jar包含进classpath呢?

换句话说:为啥被打脸??

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP

打脸的理由很简单:

  1. F5->run,先make/compile/build,再运行.
  2. 依赖的scope设为了provided,此设置仅在编译阶段将依赖的jar包加入classpath,在运行阶段,不会将jar包加入classpath.

解决的方法也非常简单:

看下是不是妥妥的呢?

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP


后记

【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历-LMLPHP

.

05-02 06:29