﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-PS，1880后程序员-随笔分类-我爱内存泄露</title><link>http://www.blogjava.net/amenglai/category/53225.html</link><description>看不完的牙，写不完的程序，跑不完的步。</description><language>zh-cn</language><lastBuildDate>Fri, 18 Jan 2013 07:31:25 GMT</lastBuildDate><pubDate>Fri, 18 Jan 2013 07:31:25 GMT</pubDate><ttl>60</ttl><item><title>内存泄漏 - 开篇 数据库应用</title><link>http://www.blogjava.net/amenglai/archive/2013/01/18/394386.html</link><dc:creator>amenglai</dc:creator><author>amenglai</author><pubDate>Fri, 18 Jan 2013 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/amenglai/archive/2013/01/18/394386.html</guid><wfw:comment>http://www.blogjava.net/amenglai/comments/394386.html</wfw:comment><comments>http://www.blogjava.net/amenglai/archive/2013/01/18/394386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amenglai/comments/commentRss/394386.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amenglai/services/trackbacks/394386.html</trackback:ping><description><![CDATA[最近都在读那个该死的猪小弟写的代码，原因还不是因为压力测试后，发现TMD的内存泄漏啦！<br />边看代码边在心中鄙视这个猪小弟，该死的猪小弟，说你比猪笨，猪觉得这是对自己的侮辱都不乐意，<br />很多心得哦，慢慢整理出来。<br />先说说JDBC吧。<br /><strong>不关闭Connection</strong><br /><div><span class="Apple-style-span" style="font-weight: normal; ">这是最常见的错误，数据库增删改操作后，没有关闭数据库连接，导致占用大量内存，如果是用连接池，那么系统很快就木有可用的数据库连接了；如果是直接连接数据库，很快系统内存就耗尽了，要知道数据库连接很费资源的，否则要连接池干吗？而且这种错误很难查，一个系统上百个DB操作，就一个没关闭，惨了！</span><br /><strong>不关闭Statement,ResultSet</strong><br /><div><div style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">这是另一种错误，数据库连接关闭了，但是Statement,ResultSet没关闭。谁说的关闭了数据库连接其它就不用关闭的。只关闭连接，那些Statement,ResultSet就如同孤坟野鬼一样占据你的Heap，而且还是阴魂不散的说，最后系统耗尽内存气绝身亡。</div></div><div><div style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><strong>频繁数据库连接</strong><br />大多数业务系统，一个业务操作可能会关联多张表的增删改。麻烦不要每操作一张表，就请求一次数据库连接。麻烦把请求数据库连接看做是请你学妹吃饭好不好，小学妹很矜持，请一次也不容易。这样想，你请求数据库连接时，就会谨慎些，尽可能一次数据库连接，对多张表进行操作。<br /><strong>经验</strong><br />不要把代码写成connection.close(); 或者&nbsp;<span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 26px; ">datasource.getConnection();把他们都封装到工具类里面，这样测试的时候加进去debug代码，很容易就找到那个该死的连接没有关闭了。Statement, ResultSet也是这样。<br /><br /></span>最后，猪小弟是谁？<br />呵呵，猪小弟是5年前的我，或者是8年前的我。当年，年幼无知，无知者无畏，犯下无数的错误，感谢老板，感谢客户，你们太有牺牲精神了。<br /></div></div></div><img src ="http://www.blogjava.net/amenglai/aggbug/394386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amenglai/" target="_blank">amenglai</a> 2013-01-18 11:14 <a href="http://www.blogjava.net/amenglai/archive/2013/01/18/394386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Eclipse Memory Analyzer对Tomcat进行内存分析</title><link>http://www.blogjava.net/amenglai/archive/2013/01/17/394346.html</link><dc:creator>amenglai</dc:creator><author>amenglai</author><pubDate>Thu, 17 Jan 2013 02:55:00 GMT</pubDate><guid>http://www.blogjava.net/amenglai/archive/2013/01/17/394346.html</guid><wfw:comment>http://www.blogjava.net/amenglai/comments/394346.html</wfw:comment><comments>http://www.blogjava.net/amenglai/archive/2013/01/17/394346.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amenglai/comments/commentRss/394346.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amenglai/services/trackbacks/394346.html</trackback:ping><description><![CDATA[<div><p><strong><span style="font-size:12.0pt;font-family:宋体;">测试环境</span></strong><strong></strong></p>  <p>Java <span style="font-family:宋体;">：</span> JDK1.6</p>  <p>Tomcat<span style="font-family:宋体;">：</span> Tomcat 5.5</p>  <p>Eclipse Memory Analyzer<span style="font-family: 宋体;">：</span>EMA 1.2.1<span style="font-family:宋体;">（直接去</span>Eclipse<span style="font-family:宋体;">下载，无需安装哈）</span></p>  <p>&nbsp;</p>  <p><strong><span style="font-size:12.0pt;font-family:宋体;">获得</span></strong><strong><span style="font-size:12.0pt">Heap Dump</span></strong><strong><span style="font-size:12.0pt;font-family:宋体;">文件</span></strong><strong></strong></p>  <p>Eclipse Memory Analyzer<span style="font-family: 宋体;">是针对</span>Heap Dump<span style="font-family:宋体;">文件进行分析的，因此第一步就是要获得</span>Heap Dump<span style="font-family:宋体;">文件。</span></p>  <p><strong><span style="font-family:宋体;">步骤：</span></strong></p>  <p style="margin-bottom:9.0pt;line-height:18.75pt;background: white"><strong><span style="font-family:宋体;">获得线程</span>ID</strong><strong><span style="font-family:宋体;">。</span></strong><span style="font-family:宋体;">启动</span>jconsole.exe,<span style="font-family:宋体;">它</span><span style="font-family:宋体;color:#474747">位于</span><span style="font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;;color:#474747">jdk</span><span style="font-family:宋体;color:#474747">目录下的</span><span style="font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;;color:#474747">bin</span><span style="font-family:宋体;color:#474747">目录，</span><span style="font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;;color:#474747;">jconsole</span><span style="font-family:宋体;color:#474747;">是</span><span style="font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;;color:#474747;">jdk</span><span style="font-family:宋体;color:#474747;">自带的一个内存分析工具，它提供了图形界面。可以查看到被监控的</span><span style="font-family:&quot;Verdana&quot;,&quot;sans-serif&quot;;color:#474747;">jvm</span><span style="font-family:宋体;color:#474747;">的内存信息，线程信息，类加载信息，</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;color:#474747;">MBean</span><span style="font-family: 宋体;color:#474747;">信息。<br /><img src="http://www.blogjava.net/images/blogjava_net/amenglai/1.png" border="0" alt="" width="379" height="396" /><br /></span></p>  <p><span style="font-family:宋体;">此处我们可以找到需要检测的</span>Tomcat<span style="font-family:宋体;">的线程</span>ID<span style="font-family:宋体;">。</span></p>  <p><strong><span style="font-family:宋体;">获得</span>Heap Dump</strong><strong><span style="font-family:宋体;">文件。</span></strong><span style="font-family:宋体;">使用</span>jmap<span style="font-family:宋体;">来获得</span>Heap Dump<span style="font-family:宋体;">文件，命令行如下：</span></p>  <p>jmap -dump:format=b,file=heap.bin <span style="color:red">3888</span></p>  <p><span style="font-family:宋体;">此处</span>3888<span style="font-family:宋体;">就是</span>Tomcat<span style="font-family:宋体;">对应的线程</span>ID<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/amenglai/2.png" border="0" alt="" width="633" height="55" /></p>  <p><strong><span style="font-size:12.0pt;font-family:宋体;">生成分析报告</span></strong><strong></strong></p>  <p><span style="font-family:宋体;">启动</span>MemoryAnalyzer.exe<span style="font-family:宋体;">，打开指定的</span>Heap Dump<span style="font-family:宋体;">文件。</span>File -&gt; Open Heap Dump<br /><img src="http://www.blogjava.net/images/blogjava_net/amenglai/3.png" border="0" alt="" width="282" height="122" /><br /></p>  <p>MAT<span style="font-family:宋体;">针对指定的</span>Heap Dump<span style="font-family:宋体;">文件进行分析，生成内存泄露检测报告<br /><img src="http://www.blogjava.net/images/blogjava_net/amenglai/4.png" border="0" alt="" width="528" height="419" /><br /><br /><img src="http://www.blogjava.net/images/blogjava_net/amenglai/5.png" border="0" alt="" width="730" height="477" /><br /></span></p>  <p><strong><span style="font-size:12.0pt;font-family:宋体;">看懂分析报告</span></strong><strong></strong></p>  <p><span style="font-family:宋体;">要想看懂</span>EAT<span style="font-family:宋体;">的报告，与其到网上去找各种神贴，不如老老实实找本书，先简单复习下</span>JVM<span style="font-family:宋体;">的</span>Heap<span style="font-family:宋体;">是怎么工作滴？</span>gc<span style="font-family:宋体;">的大概一个工作机制。否则</span>EAT<span style="font-family:宋体;">的报告就像天书一样。</span>EAT<span style="font-family:宋体;">只是工具，不是目的。</span></p></div><img src ="http://www.blogjava.net/amenglai/aggbug/394346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amenglai/" target="_blank">amenglai</a> 2013-01-17 10:55 <a href="http://www.blogjava.net/amenglai/archive/2013/01/17/394346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>web应用中常出现的内存泄露</title><link>http://www.blogjava.net/amenglai/archive/2013/01/16/394286.html</link><dc:creator>amenglai</dc:creator><author>amenglai</author><pubDate>Wed, 16 Jan 2013 03:32:00 GMT</pubDate><guid>http://www.blogjava.net/amenglai/archive/2013/01/16/394286.html</guid><wfw:comment>http://www.blogjava.net/amenglai/comments/394286.html</wfw:comment><comments>http://www.blogjava.net/amenglai/archive/2013/01/16/394286.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amenglai/comments/commentRss/394286.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amenglai/services/trackbacks/394286.html</trackback:ping><description><![CDATA[企业级管理软件的web应用和普通的web站点，B2C等有很大的不同。内存泄露的检查点也会不同。<br /><strong>检查点一：什么信息需要缓存在session中</strong><br />在各种管理软件中，最常见的是把当前用户的权限等信息缓存在session中。好啦，问题来了，如果系统的权限很复杂：操作权限，管理权限，数据权限，字段权限，巴拉巴拉一大堆的话，那么把这大堆信息放到session中，一个用户就要占掉20M+的内存。访问用户一多，系统就挂了。而且管理软件一般都会把session的timeout设置的很多，除非用户手动的注销，否则即使木有操作也会吊在系统上很久。因此要评估此部分的设计，把不必要的或者访问不频繁的数据拖出session，放过session TA老人家吧。<br /><strong>检查点二：session数据传递<br /></strong><div><span style="font-weight: normal; ">管理系统很多都会采用帧结构，常见的上帧查询条件，下帧显示结果。问题来了，采用帧结构如果传递数据到页面，就要通过session。开发的时候，一般都是后台开发负责业务逻辑，前台开发负责数据展示。前后开发一脱节，后台向前台传递了一个集合对象，前台木有用，也不管清除。这堆垃圾数据全部都驻留内存，所以系统跑着跑着就宕机了。<br /><div><strong>检查点三：不要试图通过页面来实现分页<br /></strong><div style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><span style="font-weight: normal; ">管理系统由于业务复杂性等要求，大家都把注意力首先放在实现业务功能上，有时对数据的量级不是很关注。有的系统刚开始好好的，用着用着不不爽了，原因就是数据量一增加，很多相关的问题都会暴露出来。最常见的是分页处理，先把数据都取过来，在前台分页显示。千万不要这样，100条数据木有问题，1000条，10000条呢，结果就是前台很忙，然后就挂掉了。</span></div></div></span></div><img src ="http://www.blogjava.net/amenglai/aggbug/394286.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amenglai/" target="_blank">amenglai</a> 2013-01-16 11:32 <a href="http://www.blogjava.net/amenglai/archive/2013/01/16/394286.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>