`
Garfield.Geng
  • 浏览: 39044 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JCrazySuite--检测内存泄露的神器,持续构建的加速器。

阅读更多
00)最重要的功能是啥?
1 Memory-Leak Detector。重复跑千万次TestCases,检查:内存泄露点/死锁点/源码质量/测试源码质量。
2 Auto-Test Accelerator。分组并行跑TestCases,充分发挥多核CPU威力,加快几倍几十倍build速度。
前者需要:全覆盖率的TestCases。
02)最典型的样例和用法是啥?
新建AllTest0.java,把光标移动到此method范围里,
Eclipse/ NetBeans/ Intellij IDEA的右键菜单Test File/ Run Focused Test/ Run As JUnit Test都能带动的。
public class AllTest0 throws Exception { // do NOT care any exception
  public static Test suite() {
    int rounds = 3, bigRounds = 1300, sleepTimePerBigRound = 24/* seconds */;
    CrazySuite suite0 = new CrazySuiteForJUnit(MyClass.class, true, rounds, "*Test");
    CrazySuite suite1 = new CrazySuiteForTestng(MyClass.class, true, rounds, "*Test3");
    CrazySuite suite2 = new CompositeCrazySuite(suite0, suite1);
    //
    CrazySuite suite6 = new CrazySuiteForJUnit(Xxx.class, true, rounds, "*Test");
    //
    CrazySuite multiThreadCrazySuite =
          new CompositeCrazySuiteWithMultiThreads(suite2, suite6);
    //
    CrazySuite allCrazySuite = new CrazySuiteForBigRounds(
            new CrazySuiteParams(bigRounds, sleepTimePerBigRound),
            multiThreadCrazySuite,
            new CrazySuiteListener.DefaultHeapListener());
    return allCrazySuite.build();
  }
}

05)有人说:测试组有压力测试的,可以搞定内存泄露。让他们去搞。
有人说:这个在嵌入式方面可能好些,做服务器开发,内存条那么便宜。
有人说:每隔几天restart就行了,不用搞TestCase,更不用搞JCrazySuite。
网络支付业的某技术负责人:我们不需要Auto Test,更不需要Coverage。
如果生产环境真的发生了内存泄露,通知一声,再去找就是了。
他们的说法很适合于:低质量的项目或中国式的混事型的项目。请关闭这张网页。
06)我已经用某工具对典型案例测试了千万遍,足够证明没有内存泄露了。
假设这个项目有9000行,“用某工具对典型案例测试了千万遍”也只是覆盖了其中的1000行,那么,还有8,000行没有覆盖到。这就明显标志着:很可能有内存泄露。另外,“某工具”,真的适合Java Developer吗?符合这些条件吗:
a. 是开源免费的吗?
b. 是纯Java的吗?
c. 容易控制吗?(软件工具本身是有很多毛病的,兼容性也差)
d. 容易学习吗?需要学个新脚本语言?
e. 和你的Java程序集成得好吗?(最好都在一个进程里,即:一个JVM里)
f. 和Java IDE集成得好吗?
g. 能直接在命令行上轻松的用一条指令启动吗?
以上的多项指标,JCrazySuite都实现了。
07)某工程有5000行,TestCases总共只有70行,用JCrazySuite能做什么?
无法有效的使用JCrazySuite。
如果你是个真正的重视质量的程序员,那么针对这工程的各种TestCase应该有10000+行才对。
经过了Code Coverage Tools的多次检查后,还会增加,应该有30000+行才对。
10)如何用JCrazySuite精确检查内存泄露点?
如果有全覆盖率的TestCases,源码的每行都会被执行到。内存泄露点,肯定是在某几行上。
按照Code/Branch Coverage最小的来计算,普遍是:1。
如果把全覆盖率的TestCases重复跑千万次,那么内存泄露的空间就会放大千万倍。
那么在jconsole/jvisualvm/jmc/jprofiler绘制的图形上,就容易观察到:波形的低点总在逐渐升高。
这时得到结论:肯定有内存泄露。
如何找到那几行呢?JCrazySuite用两种排除法帮你找内存泄露:
排除法(A),重复的单独的跑某个package及其child package,例如:跑基于Xxx.class所在的package
new CrazySuiteForJUnit(Xxx.class, isRandom, 300, JUnit, "*Test");

如果结论是这个package的TestCases有内存泄露,就把TestCases分成2堆(二分法),分别跑每堆。
new CrazySuiteForJUnit(Xxx.class, isRandom, 300, JUnit, "AbcTest", "XxxTest");

排除法(B),针对整个工程的测试源码,每次跑符合某规则的:A*Test, B*Test
// 会生成符合英文字母顺序的{"A*Test", "B*Test", ……"G*Test"}
String[] suffixPattern = buildTestClassNameFromAtoG("*Test");
new CrazySuiteForJUnit("myclassesdir" …… 300, JUnit, suffixPattern);
跑完了,结果正常,就跑下面的2轮:
buildTestClassNameFromHtoN("*Test")
buildTestClassNameFromOtoZ("*Test")

如果找到了,再逐渐缩小范围:
new CrazySuiteForJUnit("myclassesdir" …… 300, JUnit, "O*Test", "P*Test");

符合{"O*Test", "P*Test"}的class正规名字,每次都会打印出来,也能帮助你快速缩小范围。
new CrazySuiteForJUnit("myclassesdir" …… 300, JUnit, "Obj*Test");

得到结论:ObjectXxxTest跑过的行,泄露了内存。
最后,ignore掉ObjectXxxTest的某些test method,再继续重复跑。
再最后,找出了某个test method,再跑,用VisualVM查看。
在内存泄露较多的时候,在DefaultHeapListener提醒后,dump几次,
结合此TestCase走过的源码路径,对比dump data,找最主要的Type,随机查看几十项,就能发现毛病根源了。
12)JCrazySuite基本理论是啥?还有些啥好处?
1 基于TestFramewok、Code Coverage Tool,用排除法检测工程里全部的memory leak。
2 要跑JCrazySuite,先要有足够的TestCase,这就促进了你写TestCase,而此过程又促进了Refactory。
4 促进了“持续集成+性能测试”。把JUnit、TestNG等等的多种多个TestCase集中在一个TestSuite里跑。
在同一个JVM内,用单线程或多线程,跑多个TestCase,定时GC,定时assert JVM message,All-In-A-JVM。
再配上JDK自带的jconsole/jvisualvm/jmc,实现了完美。你可以扔掉其它性能测试工具了。
6 从跑的行为(动态的,而非静态的评审源码的行为)上检验源码和测试源码质量如何。
跑的过程,将会出很多毛病,促进你优化code。
实际上,我已经用它从"跑"的行为上,检验出Ant-1.9.3、JUnit-4.10、Spring-3.1.2等多个毛病了。
7 JCrazySuite的监听器有多种,还提供接口实现自定义的功能。
例如:从跑的过程中记录超过N秒的TestCase,促使你精简code。
15)检测内存泄露,具体用哪些class?
用CrazySuiteForBigRounds,它是不收集测试结果的,避免了和真正的内存泄露搞混淆。
注意:只能用这个,不能用别的。
因为别的(CrazySuiteForJUnit/ CrazySuiteForTestng/ CompositeCrazySuite)在跑的过程中,既收集测试结果,
也有listener收集信息,这会消耗小部分内存,会和工程本身的内存泄露点混在一起,导致无法分辨。
20)如果不用或者忘记打开了jconsole/jvisualvm/jmc,如何检查内存泄露?
内存泄露检测有啥算法?

0.3.0版本后,完全没有算法了。new CrazySuiteListener.DefaultHeapListener(); 看 48)
24)某工程有4000行,某行泄露内存,一次执行只泄露一个byte,怎么办?
JCrazySuite主要就是重复千万次的跑TestCase,放大所有的内存泄露点,参数里有iterations、bigRounds。
把虫虫变成大象,就容易找到了。
27)JCrazySuite和啥软件重复了?
通过baidu、google、sourceforge、google code可以得到结论:JCrazySuite没有重复。
这符合软件原则:Don't re-invent the wheel.
30)JCrazySuite和Ant、Maven结合,有自己的插件吗?
JCrazySuite创建的的都是junit3的TestSuite,Ant、Maven都认识的。
兼容全部BuildTool(Ant、Maven……)
兼容全部Java IDE(Eclipse、NetBeans、Intellij IDEA、JDeveloper……),
兼容全部Java TestFramework(JUnit、Testng……)。
针对上述的全部做插件,还要持续维护版本兼容性,太麻烦了。我没有时间。
我一直遵循着某些软件原则:
Don't Write Code
Write Less Code
Keep It Simple and Stupid
45)关于JCrazySuite的搭配,推荐啥TestFramework?推荐啥Coverage Tool?
JUnit,简单易用,最好了。
Testng,本身过度复杂,在各大IDE上的版本都不同,本身也有内存泄露,新版本久不更新,不推荐。
Cobertura、JaCoco都支持Java5、Java7编译级别。
47)有啥著名的内存泄露的例子?
Testng,MethodHelper,有3个static Map,会导致严重的内存泄露。
既然如此,为什么JCrazySuite还能基于Testng跑呢?
因为JCrazySuite针对MethodHelper有特别处理:
在每个new TestNG().run()后,用reflection makeAccessible执行了map.clear()。
48)如果不用JCrazySuite的排除法,只用VisualVM的多次dump,还不要总盯着看,
还要为了避免dump多余的数据而把时间点掐得很准很准,如何快速查找内存泄露点?
就算能熟练操作VisualVM,dump出来的东东太多,难以从大量数据中分辨内存泄露点,怎么办?

跑300组,每次同时跑CompositeCrazySuiteWithMultiThreads一组内的多条线程(能快速暴露毛病),
等一组跑完,强行gc,再sleep(40秒),这就是个纯净的时间段了,没有任何CPU和内存消耗。
这是最最精确的可dump的时间点了,dump出来的东东是最最小的。很爽!!!
这时JCrazySuite用默认的3种方式提醒你在VisualVM里搞dump:
(1)默认的提示:控制台,字幕提示
(2)从视觉上提示:弹出个几行字的网页,提示你搞dump
(3)从听觉上提示:连续搞40秒toolkit.beep()

这样搞几组后,用VisualVM对比几个dump的东东,就能在最小的差距范围里看出些毛病了。
通常的内存泄露点是:static Map & Collection、file.deleteOnExit(),zombie thread,non-closed stream,ThreadLocal
还会附带的消耗些String、char[]、Object类型的内存。
49)CrazySuiteForBigRounds弹出来的网页是啥样?
CrazySuiteForBigRounds不会弹出网页,而是DefaultHeapListener弹出的网页,可以自定义的。
这是跑JCrazySuite自身的例子,每次bigRound跑完,gc 3次,就会新增一行数值并弹出网页,提示dump。
Dump jvm heap quickly with VisualVM. 2014-03-12T07:33:11 Used Memory= 12 MB
Dump jvm heap quickly with VisualVM. 2014-03-12T07:40:51 Used Memory= 9 MB
Dump jvm heap quickly with VisualVM. 2014-03-12T07:48:30 Used Memory= 9 MB
Dump jvm heap quickly with VisualVM. 2014-03-12T07:55:43 Used Memory= 9 MB
Dump jvm heap quickly with VisualVM. 2014-03-12T08:03:02 Used Memory= 8 MB
Dump jvm heap quickly with VisualVM. 2014-03-12T08:10:27 Used Memory= 8 MB
Dump jvm heap quickly with VisualVM. 2014-03-12T08:17:34 Used Memory= 8 MB
53)在用JCrazySuite内存泄露模式跑之前,需要做什么?
先把整套TestCases全部跑2轮,串行的方式,非并行的方式,确保它们全部正确。
54)用JCrazySuite的多线程模式跑全部TestCase,开启全部的jconsole/jvisualvm/jmc,
JVM总crash,为什么?

JVM无法承受,CPU太忙了。
建议:开一个jconsole就行了,重点关注PS Old Gen项。如果它长久的持续升高,就是泄露内存了。
58)JCrazySuite和大家的app、junit/testng的层级关系如何?
你的程序---->JCrazySuite---->Your JUnit/TestNG Test class
60)5个子工程,共有30,000个TestCases。用JCrazySuite能做啥?
对于超大型的工程,JCrazySuite更加有效果。
把5个子工程按照package和4核/6核/8核CPU情况拆为大约20份,确认这20份的运行没有互相影响,
每份都做个CrazySuite,都放在CompositeCrazySuiteWithMultiThreads(suite01,suite02, ....suite20)里,
suite01/suite02/…都将作为单独的线程启动,同时跑TestCases,加速了几倍几十倍,这会节省程序员大量时间。
65)将来有了别的测试框架,能兼容吗?
JCrazySuite站在时代的高点上,兼容了Testng,并提供接口实现用别的测试框架跑TestCases。
72)为啥叫做CrazySuite?
Suite,本身就是多个TestCase。
Crazy,意味着:不是跑1次,而是跑千百次。几个class,都有iterations参数。
junit3有TestSuite,CrazySuite就是TestSuite的加强版。
75)作者是谁?源码有多少?源码在哪里?
我。 src core在24KB内,做得足够简单,是那种“很容易找出是否有毛病的东东”。
http://sourceforge.net/p/jcrazysuite/
80)某工程有600个class,800个TestCases,需要自定义几个CrazySuite来带动?
一个就够了。就像本文开头的code片段一样,只有几行。
因为这种风格足够足够简单,以至于不需要别的风格了。
例如:junit4的@风格,就是多余的。

90)口号?
跑,跑,跑,疯狂的跑!把毛病都跑没了,让测试组郁闷去吧。
99)欢迎批评
  • 大小: 41 KB
5
2
分享到:
评论
2 楼 Garfield.Geng 2014-02-26  
yangshangchuan 写道
楼主是否能写篇博文讲讲JCrazySuite中的内存泄露检测算法?是否能进一步提供一个windows下的可执行文件,我指定源代码目录后,点击检测,然后输出存在内存泄露的代码所在的文件行数等详细信息?


具体算法,我修改了文档,参考:20)

百度:“JProfiler 内存泄露”,
业界最领先的成名多年的商业软件JProfiler,也没有做到你说的“一键式”功能。
总还是需要人花时间操作和分析的。
我的JCrazySuite也需要搭配类似于JProfiler的但能免费开源的东东:
jconsole/jvisualvm/jmc。

对于“一次执行只泄露一个byte”,这种情况,JProfiler也是没法的。
JCrazySuite就能找出来。请参考:24)
1 楼 yangshangchuan 2014-02-26  
楼主是否能写篇博文讲讲JCrazySuite中的内存泄露检测算法?是否能进一步提供一个windows下的可执行文件,我指定源代码目录后,点击检测,然后输出存在内存泄露的代码所在的文件行数等详细信息?

相关推荐

Global site tag (gtag.js) - Google Analytics