【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历
背景
最近收到这样一个问题:
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吧,妥妥的不会被打脸!
看下是不是妥妥的呢?
后记
.
【hello,world 也打脸】记storm-starter在某知名IDE下的悲催调试经历的更多相关文章
- 使用Maven编译运行Storm入门代码(Storm starter)(转)
Storm 官方提供了入门代码(Storm starter),即 Storm安装教程 中所运行的实例(storm-starter-topologies-0.9.6.jar),该入门代码位于 /usr/ ...
- 记一次小团队Git实践(下)
在上篇中,我们已经能基本使用git了,接下来继续更深入的挖掘一下git. 更多的配置自定义信息 除了前面讲的用户名和邮箱的配置,还可以自定义其他配置: # 自定义你喜欢的编辑器,可选 git conf ...
- 【z】Storm - the world's best IDE framework for .NET
http://www.codeproject.com/Articles/42799/Storm-the-world-s-best-IDE-framework-for-NET Storm - the w ...
- [转帖]「白帽黑客成长记」Windows提权基本原理(下)
「白帽黑客成长记」Windows提权基本原理(下) https://www.cnblogs.com/ichunqiu/p/10968674.html 提权.. 之前还在想 为什么 我的 sqlserv ...
- 交易系统使用storm,在消息高可靠情况下,如何避免消息重复
概要:在使用storm分布式计算框架进行数据处理时,如何保证进入storm的消息的一定会被处理,且不会被重复处理.这个时候仅仅开启storm的ack机制并不能解决上述问题.那么该如何设计出一个好的方案 ...
- 记一次java应用cpu利用率过高调试经历
1,现象 写的一个storm应用,主要是通过mysql的binlog来同步表到hbase.运行一段时间后发现,经常会出现cpu使用率飙升到200%以上,然后各种消息堆积报警等等出现各种问题 2,调研过 ...
- 「白帽黑客成长记」Windows提权基本原理(下)
上一篇文章我们介绍了信息收集方法和WMIC,今天我们将跟随作者深入学习Windows提权基本原理的内容,希望通过这两篇文章的讲解,大家能够真正掌握这个技能. 推荐阅读:「白帽黑客成长记」Windows ...
- guitar pro系列教程(二):Guitar Pro主界面之记谱功能的详细解析【下】
本章节我们接着上一章节继续讲解关于guitar pro主界面的记谱功能里的符号功能.有兴趣的朋友可以进来一起学习哦. 首先我们看下图,这是点击按钮便会弹出的一个窗口,进入这个窗口,我们会看到" ...
- 记一次事件委托在 ios 下的兼容 bug
项目中碰到的兼容类 bug,记录一二. 页面上有几个同类型的控件,点击它们会触发一些事件,很显然,事件委托优于批量绑定.为了图方便,我将 click 事件绑定到了 document.body 上(绑定 ...
随机推荐
- 避免jQuery名字冲突--noConflict()方法
众所周知,在jQuery语法中,$符号是jQuery的简写方式.但在某些情况下,可能需要在同一个页面引入其他javascript库(比如Prototype).因为$简短方便,很多的库也是使用$符号.为 ...
- ElasticSearch Filter Aggregations
类似于sql语句中where子句的作用 { "query": { "match_all": {} }, "aggs": { "ag ...
- java 根据 根节点及所有子成员 构造树tree
实体类entity package com.ompa.biz.entity; import java.util.ArrayList; import java.util.List; public cla ...
- (三)openwrt主Makefile解析
本周成胖子每周一博到了第四周^_^ 前言 主Makefile结构 顶层 第二层 尾记 前言 前一篇,我们大概描述了整个镜像文件的生成过程.本周我们来解析主Makefile,看看主要编译过程是怎么产生的 ...
- [转]ASP.NET MVC 4 (九) 模型绑定
本文转自:http://www.cnblogs.com/duanshuiliu/p/3706701.html 模型绑定指的是MVC从浏览器发送的HTTP请求中为我们创建.NET对象,在HTTP请求和C ...
- NOIP2010提高组 关押罪犯 -SilverN
(洛谷P1525) 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”( ...
- docker containerd中的容器操作
containerd的中的各种操作都是通过Task来进行的,因此对于容器的create, start, delete等等操作其实都是一个个的Task而已. Task的数据结构如下所示: type Ta ...
- MATLAB基本命令
eye(n)创建n阶单位矩阵 zeros(n)创建n阶0方阵 rand(m,n)创建m*n阶元素为从0到1的均匀分布的随机数矩阵 round(A)对矩阵A中所有元素进行四舍五入运算 A^-1用幂运算求 ...
- React/React Native 的ES5 ES6写法对照表
//es6与es5的区别很多React/React Native的初学者都被ES6的问题迷惑:各路大神都建议我们直接学习ES6的语法(class Foo extends React.Component ...
- Java语法基础(三)----选择结构的if语句、switch语句
[前言] 流程控制语句: 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说程序的流程对运行结果有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要通过 ...