上回经分析认为是由于没有关闭输入输出流导致的,但关闭IO流两天后,又出现系统内存溢出。看来,没有从本质上解决问题。 
     
      是什么原因导致此问题的产生的呢?还是验证在其中捣乱:只有USER模块使用的比较频繁,USER模块中首页的访问量是最大的,并且首页验证码功能需要在IO流中操作。 
     
再分析下代码,看看是不是有问题。发现如果其中有问题,只有是在 
    // 在内存中创建图象 
    int width = 88, height = 19; 
    BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB); 
    ServletOutputStream out = response.getOutputStream(); 
    ImageIO.write(image, "JPEG", out);时才可能出问题的。但是要怎么验证这个问题?       使用工具TaskInfo。 
      通过这个工具发现正常情况下会在windows的临时目录中保存验证码图片,当页面显式后马上就删除了,但是当存在用户大量访问页面时,其中保存在临时目录中的图片将不会被删除掉,并且一直有句柄指向,导致没有释放的句柄越来越多,再次生成图片时会出现Too many open files异常,验证码无法正常显示,用户无法登录。 
     
     既然write方法不可能将IO流完全关闭,那我们就自己关闭了。 
            stream = ImageIO.createImageOutputStream(out); 
            ImageIO.write(image, "JPEG", stream); 
     并在finally中显式关闭掉stream流和out流。 
     这样在用TaskInfo观测发现即使有大量用户访问时,在临时目录中生成的临时文件也会马上删除的。 
还不能高兴太早...按上面方法解决,大量用户访问时,过两三天定会出现内存溢出现象。      另谋高就,使用第二种工具Optimizeit. 
     经用Optimizeit工具分析发现,当存在大量并发请求的时候,其中验证码的实现的确有内存溢出的现象,其中有2个对象没有释放: 
     java.awt.image.DataBufferByte 
     java.awt.image.DateBufferInt   经发现是ImageWriter.write()在执行时调用 
     org.apache.coyote.tomcat5.OutputBuffer.doFlush()方法时发生 
     java.net.SocketException: Connection reset by peer: socket write error异常时没有将这2个对象释放掉。       【最终解决方案】: 
      由于是ImageWriter.write()这个方案有问题,那么就换种实现方案。既然是向out流中写图片,那么就直接写吧。 
ServletOutputStream out = null; 
        try 
        { 
            out = response.getOutputStream(); 
            JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(out); 
            encoder.encode(image); 
        } 
        catch (IOException e) 
        { 
            e.printStackTrace(); 
        } 
        finally 
        { 
            if ( null != out ) 
            { 
                try 
                { 
                    out.close(); 
                } 
                catch (IOException e) 
                { 
                    e.printStackTrace(); 
                } 
            } 
        } 
再用TaskInfo和Optimizeit工具测试了下,发现没有生成临时图片,也没有发现内存溢出现象。    一波三折,终于解决问题了。    【经验总结、预防措施和规范建议】 1、网上的代码不一定都是正确的 
     验证码相关代码,网上多的要命。但有些仅仅是提供实现思路,其并没有考虑到性能问题。在使用前,一定要多考虑。 2、善于求助 
     在解决此问题的时候,及时请教有经验的同事,并且获得了很好的帮助,大大减少了定位问题时时间。 3、对于IO流的关闭一定要显式关闭 
     在处理问题时发现,需要在finally中显式的关闭流,这样可以确保流会被正确的关闭,以避免在发生异常导致流没有完全的被关闭,养成良好的编程习惯。