您可以捐助,支持我们的公益事业。

金额: 1元 10元 50元

姓名:

邮件:

电话:

公司:

说明:

认证码: 验证码,看不清楚?请点击刷新验证码 必填



  要资料 文章 文库 Lib 视频 Code iProcess 课程 认证 咨询 工具 讲座吧   专家招募  
会员   
 
   
 
  
每天15篇文章
不仅获得谋生技能
更可以追随信仰
 
 
     
   
 订阅
  捐助
记 storm-starter 在某知名 IDE 下的悲催调试经历
 
作者:foreach_break 来源:伯乐在线 发布于 2016-7-4
来自于要资料   1701 次浏览     评价:      
 

背景

最近收到这样一个问题:

Storm处理消息时会根据Topology生成一棵消息树,Storm如何跟踪每个消息、如何保证消息不丢失以及如何实现重发消息机制?

虽已回复,但心想还是看下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,然后:

这尼玛,说好不打脸的!

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

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

异常是如何产生的

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

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

(查看大图)

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

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

(查看大图)

注意看调用栈:

JVM_GetClassDelaredMethods是JVM内方法,在找入口函数main的过程中,此方法被调用。
接着,此方法会调用验证字节码的过程:verify_code。
发现有用到backtype.storm.topology.IRichBolt接口,那么找找这个接口所在的.class文件吧:如果我们运行java -cp . xxx,通过-cp或者-classpath参数指定了classpath,那么这个.class就会被找到。然后进入parse的过程。
悲催的是,IDEA的运行或者调试命令f5->run,没有将backtype/storm/topology/IRichBolt所在的jar包storm-core.jar加入classpath,这都是后话了…
那么,既然有个找*.class的过程,这个过程如下:

(查看大图)

对上图做一点简要说明:

执行java -cp . $mainClass .
java程序(这里指java这个程序本身)的入口函数main,会创建虚拟机JVM实例,过程中会初始化JVM本地ClassLoader.
在JVM寻找.class文件时,调用ClassLoader::load_classfile方法,从jar包、zip包、目录中寻找指定的.class文件 .
本文中,木有找到backtype/storm/topology/IRichBolt.class,所以会置一个延时异常__pending_exception,这个异常关联了这个类(接口)、文件名、异常的类型(NoClassDefFound),那这个异常什么时候处理呢?后文再说.
看下这个异常的内容:

异常是如何处理的

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

看下图:

(查看大图)

对上图做下简要说明:

执行java -cp . $mainClass .
java程序的入口函数main,在层层初始化的过程中,会调用到LoadMainClass函数, 结合本文的第一幅图就可以知道,这个函数最终会制造那个NoClassDefFound的异常__pending_exception,然后返回的是一个空的mainClass.
紧跟着LoadMainClass函数,是一个CHECK_EXCEPTION_NULL_LEAVE的宏,这个宏展开后,会处理上面制造的那个异常,然后,打印异常信息。这里就是那个被打脸的异常了。

为什么被打了脸

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

简单的概括下就是:

/* 伪代码 */
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呢?

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

(查看大图)

打脸的理由很简单:

F5->run,先make/compile/build,再运行.
依赖的scope设为了provided,此设置仅在编译阶段将依赖的jar包加入classpath,在运行阶段,不会将jar包加入classpath.
解决的方法也非常简单:

如果不是通过mvn来运行,而是在IDE下调试/运行,赶紧将依赖的jar包的scope选为compile吧,妥妥的不会被打脸!

看下是不是妥妥的呢?

   
 订阅
  捐助
相关文章 相关文档 相关课程



我们该如何设计数据库
数据库设计经验谈
数据库设计过程
数据库编程总结
数据库性能调优技巧
数据库性能调整
数据库性能优化讲座
数据库系统性能调优系列
高性能数据库设计与优化
高级数据库架构师
数据仓库和数据挖掘技术
Hadoop原理、部署与性能调优
 

MySQL索引背后的数据结构
MySQL性能调优与架构设计
SQL Server数据库备份与恢复
让数据库飞起来 10大DB2优化
oracle的临时表空间写满磁盘
数据库的跨平台设计
更多...   

并发、大容量、高性能数据库
高级数据库架构设计师
Hadoop原理与实践
Oracle 数据仓库
数据仓库和数据挖掘
Oracle数据库开发与管理

领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...   
 
 
 
 
 
每天2个文档/视频
扫描微信二维码订阅
订阅技术月刊
获得每月300个技术资源
 
 

关于我们 | 联系我们 | 京ICP备10020922号 京公海网安备110108001071号