问题实质上是这样的,我从数据库中一次性取了3W多条数据,这就直接导致了jvm的内存溢出,异常如下:
java.lang.OutOfMemoryError: Java heap space ;
由于业务需要,我要把数据一次取出来做折线图(走势图),所以我没办法使用存储过程分页,只能一次性把数据全取出来,用列表和图两种展现方式显示,列表使用标签分页;
我使用的是struts1.2+spring2.0+jdbc,数据一次性出来后就如标题所说,把3W个对象塞到了一个list中。哪位大哥给指点下,怎么样才能可以把数据全取出来,而不发生内存溢出,我现在正在寻找修改jvm配置的方法,知道的大哥也给说下,谢谢!当然,除了修改jvm这条思路,有其他思路更好!

解决方案 »

  1.   

    在Windows操作系统中修改catalina.bat文件:
    rem ----- Execute The Requested Command ---------------------------------------
    //在上面一行下面加入:
    set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m
      

  2.   

    我知道一个tomcat\bin\catalina.bat
    加入标红那一行可以修改一下tomcat的
    rem   JPDA_OPTS       (Optional) Java runtime options used when the "jpda start"
    rem                   command is executed. If used, JPDA_TRANSPORT, JPDA_ADDRESS,
    rem                   and JPDA_SUSPEND are ignored. Thus, all required jpda
    rem                   options MUST be specified. The default is:
    rem
    rem                   -Xdebug -Xrunjdwp:transport=%JPDA_TRANSPORT%,
    rem                       address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%
    rem
    rem $Id: catalina.bat 609438 2008-01-06 22:14:28Z t $
    rem ---------------------------------------------------------------------------rem Guess CATALINA_HOME if not defined
    set JAVA_OPTS=-Xms64m -Xmx256m
    set CURRENT_DIR=%cd%
    if not "%CATALINA_HOME%" == "" goto gotHome
    set CATALINA_HOME=%CURRENT_DIR%
    if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
    cd ..
      

  3.   


    图就是使用jfreechart做的。。
      

  4.   


    呵呵,我也是这么想滴,所以将修改jvm的内存配置放在最后,实在没办法了,我就不得不这么干了继续顶,希望做过这方面的,碰到过这方面的,处理过方面的过来瞅瞅,没办法,大家也可以讨论讨论
      

  5.   


    打个比方,比如用户要查2009-09-16 00:00:00到2009-09-18 00:00:00的数据,我用时间(timestamp)order by后,用存储过程分页,假设一次取一天的数据,那取一次页面上显示的就是一天数据的走势,他要想看到他所查所有数据的走势就需要多张页面,当然也就是查询多次,这样的话2天的数据就不能在同一张图上反应出来,我就卡在这了。
      

  6.   

    建议使用内存映射文件。建立一个能容纳3W个数据的内存映射文件,然后把数据放入,用的时候从这个内存映射文件上进行读取。
    包含一下:
    import java.nio.*;
    import java.nio.channels.*;
    具体如下:
     建立:
    FileInputStream in=new FileInputStream(filename);
    FileChannel channel=in.getChannel();MappedByteBuffer buffer=channel.map(FileChannel.MapMode.READ_WRITE,0,length);
     使用:
    buffer.get(int number);//读
    buffer.set(int number);//写注:filename是一个String,为临时文件的名称。length为int,等于3W个数据的大小
      

  7.   


    public List<AudioIndexBean> getAllBystrs(String startTime, String endTime,
    String str) {
    Connection conn=super.getConnection();
    CallableStatement cs=null;
    ResultSet rs = null;
    AudioIndexBean audio = null;
    List<AudioIndexBean> list = new ArrayList<AudioIndexBean>();
    try {
    cs = conn.prepareCall("{call sp_select_new_audio(?,?,?)}");// 调用存储过程
    // 传参
    cs.setString(1, startTime);
    cs.setString(2, endTime);
    cs.setString(3, str);
    Boolean b = false;
    b = cs.execute();
    while (b) {
    rs = cs.getResultSet();
    while (rs.next()) {
     audio = new AudioIndexBean();
    audio.setRtp_start_time(rs.getLong("rtp_start_time"));
    audio.setRtp_end_time(rs.getLong("rtp_end_time"));
    audio.setSrc_ip(rs.getString("src_ip"));
    audio.setDst_ip(rs.getString("dst_ip"));
    audio.setYnsrc_id(rs.getLong("ynsrc_id"));
    audio.setSrc_port(rs.getInt("src_port"));
    audio.setDst_port(rs.getInt("dst_port"));
    audio.setDisorder(rs.getInt("disorder"));
    audio.setHit(rs.getDouble("hit"));
    audio.setPacketlossrate(rs.getDouble("packetlossrate"));
    audio.setAvr_jitter(rs.getDouble("avr_jitter"));
    audio.setMax_jitter_time(rs.getLong("max_jitter_time"));
    audio.setAvr_jitter(rs.getInt("max_jitter"));
    audio.setMos(rs.getDouble("mos"));
    audio.setR(rs.getDouble("r"));
    audio.setMaxlossnum(rs.getInt("maxlossnum"));
    audio.setNode_id(rs.getInt("node_id"));
    audio.setDirect(rs.getInt("direct"));
    audio.setIp(rs.getString("ip"));
    audio.setPort(rs.getInt("port"));
    audio.setMediatype(rs.getInt("mediatype"));
    audio.setStatustype(rs.getInt("statustype"));
    audio.setErrorcode(rs.getInt("errorcode"));
    audio.setStatus(rs.getString("status"));
    audio.setPlanid(rs.getInt("planid"));
    audio.setCaseid(rs.getInt("caseid"));
    audio.setSn(rs.getInt("sn"));
    audio.setUtimestamp(rs.getLong("utimestamp"));
    list.add(audio);
    }
    b = cs.getMoreResults();
    }
    // System.out.println("cost:" + (System.currentTimeMillis() - t));
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    log.error("错误信息:"+e.getMessage());
    }finally
    {
    try {
    rs.close();
    cs.close();
    conn.close();
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    } return list;
    }上面是我取数据的方法,哪位给看下还能怎么优化下,需不需要在用完连接之后
    rs=null;
    cs=null;
    conn=null;
    谢谢!
      

  8.   

    "用的eclipse么?如果是的话,请在window/preferences/java/installed JREs/edit(你正在使用的jdk)/Default VM Arguments那栏中
    输入-Xms128m -Xmx384m即可。
    前面是指定最小的内存,后面是指定最大内存。具体根据需求调整。
    绝对好使~"这个修改的效果应该和1楼,2楼给我的修改方法修改的效果是一样的吧。
      

  9.   

    晕 这么多的数据啊,分开取吧,用10个list取出来,再做排序吧
      

  10.   

    写一个存储过程来处理走势图,传出排序后的结果,输入参数为起始日期和结束日期不行么?因为这么多数据,取出来只是为了做走势图,完全可以让过程传出一个一维数组,每个时间点保存为一个数字。排序用oracle分析函数很容易实现。
      

  11.   

    写个简单的例子好了,假设有表T,里面有5列A,B,C,D,E,其中E是日期类型,根据A,B,C,D排序。过程可以写成这样:
    create type order_cursor is ref cursor;create or replace procedure pro( start_dt in date
                                   , end_dt   in date
                                   , o_cur    out order_cursor
                                   )
    is 
       v_sql varchar2(2000) := null; 
    begin
       v_sql := 'select E, row_number() over(order by a,b,c,d) rn from T';
       open o_cur for v_sql;
    end pro;
    /甚至你还可以先分组再排序,比如按A分组,按B,C,D排序,则v_sql写成:
    v_sql := 'select A,E, row_number() over(partition by a, order by b,c,d) rn from T';这类问题其实可以先和数据库开发人员交流下的
      

  12.   

    select E, row_number() over(order by a,b,c,d) rn from T where e between start_dt and end_dt;rn返回的是number类型,对应java的Integer就可以了,不要说3W,就是300W,也是很快的事情啊
      

  13.   

    解决方法 1、扩大 tomcat和JDK的缓存。
    2、用读文件流的方法吧
      

  14.   

    可以AudioIndexBean audio中做走势图不需要的属性不赋值减少下内存的占用。
    或者数据库取出来的值不要一次都存入list中,先存入1W的数据,等1W的数据处理完成在向list里存入1W的数据,直到都处理完成。
      

  15.   

    你一次将结果取出来 目的是做什么 计算结果后传入JFREECHAR 做展示么, 比如聚合运算等,这些操作在数据库里面应该也可以完成。为什么不在数据库运算完成后在取出来么?
      

  16.   

    你可以修改jvm的内存大小。。具体办法google了。