我使用org.jdom.input.SAXBuilder解析XML文件,Web应用系统中会频繁调用,但是可能因为解析后内存不能及时释放,导致tomcat经常出现OutOfMemory的现象,各位有没有好的办法解决这个问题呢?代码如下:
                           /* 利用SAX建立Document */
SAXBuilder bSAX = new SAXBuilder(false);

/* 生成document对象 */
docJDOM = bSAX.build(listXml);

//System.out.println(System.currentTimeMillis()-start);

/* Document的根 */
root = docJDOM.getRootElement();

/* 查询时间 */
recordElement = root.getChild("time");
                        
                        ......
如果能像C++那样自己主动释放内存就好了,郁闷啊!

解决方案 »

  1.   


    强制调用内存垃圾回收 
    System.gc();
      

  2.   

    如果你确定你的程序没有 问题的前提下,那就只能加大tomcat启动时的虚拟机堆空间。
      

  3.   

    我也加大了tomcat堆空间,现在因为这个问题,造成服务器需要频繁重启,至于System.gc()我还没用,不过听说这个也是系统根据环境情况选择时间回收垃圾内存。真是郁闷啊
      

  4.   

    你也覆盖了 Object 理的  finalize() 方法, 这个确实是不确定每一次都执行的。但是 System.gc() ; 是强制调用执行的。 调用后一定执行。
      

  5.   

    尽量少创建document对象,在一个动作里可以只创建一个对象
      

  6.   

    我试着加了System.gc(),速度慢了很多,不过还是没解决问题。
    主要的代码如下:
    class UserXMLParser implements XMLParser{
       ... ...
       QueryBean parseListXml(InputStream in){
            QueryBean query = new QueryBean();
    QueryBean queryBean = new QueryBean();
    Document docJDOM = null;
    Element root = null;
    Element recordElement = null;
    Element leafElement = null;
    List recordList = null;
    List retList = null;
    int listSize = 0;
    try {
    /* 利用SAX建立Document */
    SAXBuilder bSAX = new SAXBuilder(false);

    /* 生成document对象 */
    docJDOM = bSAX.build(listXml);
    /* Document的根 */
    root = docJDOM.getRootElement();

    /* 查询时间 */
    recordElement = root.getChild("time");
    queryBean.setTime(Long.parseLong(recordElement.getText()));                        ... ...                }catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    return queryBean;
       }
    }
    调用的方法:
                 XMLParser xmlParser = null;      InputStream in = new FileInputStream("product.xml");
         xmlParser = new ProductGroupParser();
              queryBean = xmlParser.parseListXml(in);
            返回值queryBean,主要用来在页面上显示queryBean中的相关数据,我使用JProfiler测了一下,频繁调用这段代码就会造成内存不断增加,我怀疑是页面引用queryBean造成解析的XML不能及时释放,不知道有没有办法解决这个问题。
      

  7.   

    XMLdecoder它的设计是这样的,它要把流中所有数据都读出来,然后读出来的,原因就是,它怕里面的数据只是一个比较的数据,构成一个xml,所以,如果边读边写出去的话,就有机会破坏你要传的object的结构。有一个解决方法,就是用javax.xml.parsers.SAXParser来弄下手脚,
    因为 saxparser解析XML要用的是saxparser.parser(InputStream in, DefaultHandler handler);所以,楼主可以在DefaultHandler handler里做手脚,写一个简单的伪代码:class TestSAX extends DefaultHandler{    @overwrite
        public void startElement(String namespaceURI,String localName,String qName,Attributes atts)
        {
           //这里就是每次读进一个像<object>标识就调用这个方法,这个是parser实现的,你只要跟据你的数据来处理
        }
        @overwrite
        public void endElement(String namespaceURI,String localName,String fullName )throws SAXException{
    //        if(做些判断,判断你的要传输的数据到这里就是一条完整的记录,可以写入数据库)
              {
                //在这里调用xmldecoder.readobject() 读出来的数据,写进数据库,然后xmldecoder.cloes()就可以啦。
              }
        }    @overwrite
        public void characters( char[] chars, int start, int length )throws SAXException{
            //将元素内容累加到StringBuffer中 
            buf.append(chars,start,length);
        }
        }
      

  8.   

    我想楼主的问题十有八九是因为流操作造成的问题,打开的流(InputStream, OutputStream)一定要主动且手工释放:in.close(), out.close(),并且最好放到finally块中,
    值得注意是System.gc()不是万能的,不能回收的资源有:
    网络连接,数据库连接,文件流等。
      

  9.   

    推荐几种方法1.建议你用dom4j进行解析,在解析过程中尽量少new对象【如果太频繁而且xml数据过大也会出现内存溢出】2.建议你把xml转为String,然后用正则去解析,这样可以大大减少内存溢出问题