package com.cafe.test;import java.sql.*;
class Test{
      /**
     * @param args
     */
    /**
     * @param args
     */
    public static void main(String args[])
      {  
       int i=0;
          String RL = "jdbc:oracle:thin:@localhost:1521:orcl";
          String user ="cafe";//这里替换成你自已的数据库用户名
          String password = "pwd";//这里替换成你自已的数据库用户密码
          String sqlStr = "select * from main_info";          try{      //这里的异常处理语句是必需的.否则不能通过编译!    
              Class.forName("oracle.jdbc.driver.OracleDriver");
              System.out.println( "类实例化成功!" );
          
              Connection con = DriverManager.getConnection(RL,user,password);
              System.out.println( "创建连接对像成功!" );              Statement st = con.createStatement(
                      ResultSet.TYPE_SCROLL_INSENSITIVE,
                      ResultSet.CONCUR_READ_ONLY);
              System.out.println( "创建Statement成功!" );              //st.setMaxRows(10);
              ResultSet rs = st.executeQuery( sqlStr );
              System.out.println( "操作数据表成功!" );
              System.out.println( "----------------!" );
              System.out.println("FetchSize:"+rs.getFetchSize());
              //测试结果集是否支持滚动              while(rs.next())
              {
                  i=i+1;
              }
              System.out.println(i);
              rs.close();
              st.close();
              con.close();
          }
          catch(Exception err){
              err.printStackTrace(System.out);
          }
      }
}结果:
类实例化成功!
创建连接对像成功!
创建Statement成功!
操作数据表成功!
----------------!
FetchSize:10
Result set is scrollable
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.CharCommonAccessor.getBytes(CharCommonAccessor.java:491)
at oracle.jdbc.driver.OracleResultSetImpl.getBytes(OracleResultSetImpl.java:641)
at oracle.jdbc.driver.ScrollableResultSet.cacheRowAt(ScrollableResultSet.java:1461)
at oracle.jdbc.driver.ScrollableResultSet.isValidRow(ScrollableResultSet.java:1441)
at oracle.jdbc.driver.ScrollableResultSet.absolute(ScrollableResultSet.java:385)
at com.cafe.test.Test.main(Test.java:43)我的数据库中有百万以上的数据。如何解决内存溢出的问题。按理说getfetch得到的是10,说明resultSet每次更新10行,不应该内存溢出啊。

解决方案 »

  1.   

    上面的结果中没有Result set is scrollable 这句!
      

  2.   

    放到finally里面看看
    finally{
    rs.close();
            st.close();
            con.close();
    }
      

  3.   

    java.lang.OutOfMemoryError: Java heap space 解决方法 
    这个问题的根源是jvm虚拟机的默认Heap大小是64M,可以通过设置其最大和最小值来实现.设置的方法主要是几个.
    1.可以在windows 更改系统环境变量
    加上JAVA_OPTS=-Xms64m -Xmx512m
    2,如果用的tomcat,在windows下,可以在
    C:\tomcat5.5.9\bin\catalina.bat  中加上:
    set JAVA_OPTS=-Xms64m -Xmx256m
    位置在: rem Guess CATALINA_HOME if not defined  这行的下面加合适.
    3.如果是linux系统
    Linux  在{tomcat_home}/bin/catalina.sh的前面,加 
    set JAVA_OPTS='-Xms64 -Xmx512'
      

  4.   

    把容器的初始内存和最大使用内存设大。
    具体做法要根据你的web容器来定。百度上可以找到正确的配置方法。
      

  5.   

    一次拿10条,并不是说拿过来之后就放掉了,而是放在ResultSet中一直跟数据库通信,不死掉才怪呢
      

  6.   

    oracle 虽然快啊,但是百万数据,还是不要一次取出来的好。
    如果是查询,可以用over()排序+ rownum分页;
    如果是一次全部更新,最好用存储过程来做。不论存储过程还是java代码,最好一次更新不要太多条,如果数据库的回滚空间设置不大或者服务器本身性能不咋的,数据库会出现 回滚日志全部占满的错误或服务器当掉。比如你100万要全部更新,你就1万1万的commit。当然如果你说要么全部更新要么全部不更新,那我也不知道怎么办了
      

  7.   


    2楼说的是jdbc释放连接的标准做法。否则你出错连接不关闭,你的应用很快就会当掉。
      

  8.   

    楼上的兄弟说调大内存的方法虽然可以解决这个问题,但如果数据量再大呢?我想知道有没有一种方法可以让jdbc取出数据后直接就释放掉这些数据?这样不过数据量多大都不会内存溢出,有没有地方可以对这种行为进行配置?
      

  9.   

    加上finally{
        rs.close();
            st.close();
            con.close();
    }
      

  10.   


    这个不能解决问题,现在程序还没有执行到要关闭的时候呢,现在程序是在rs.next()这就出现内存溢出了,问题出在数据库里的数据量太大,java把这些数据取出来放在内存里,用过的数据后没有释放。程序的逻辑还没要轮到最终释放连接句柄这一步骤呢。
      

  11.   

    支持三楼,还有可能是驱动的原因
    你可以用Eclipse analyzer分析一下
      

  12.   


    你不想多次连接数据库,可以采用连接保持,CallableStatement 或PreparedStatement 来获取一段一段的数据,用完关闭resultset的方法来做。
      

  13.   

    OutOfMemoryError内存溢出,关闭重启
      

  14.   

    修改你的sql:
    select * from main_info rownum>=N and rownum<M
    用循环分别代替那两个参数~ 避免以下导出数据过多~
      

  15.   

    经过修改把
    st = con.createStatement(
                          ResultSet.TYPE_SCROLL_INSENSITIVE,
                          ResultSet.CONCUR_READ_ONLY);
    改成
    Statement st = con.createStatement();就没有出现内存溢出的异常.
    莫非可滚动的结果集会把所有的数据取到内存里,而普通的结果集就回按fetchsize设置的值取,每次取出的数据都会覆盖原来的数据? 有没有高人,懂这里的内部机制的?
      

  16.   

    stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                    ResultSet.CONCUR_READ_ONLY);
    你让它支持scroll,所以它保存了中间结果……把ResultSet.TYPE_SCROLL_SENSITIVE改称ResultSet.TYPE_FORWARD_ONLY就可以了,
    这样游标resultset不能会滚,内存得以释放。1.TYPE_FORWORD_ONLY,只可向前滚动;2.TYPE_SCROLL_INSENSITIVE,双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来。3.TYPE_SCROLL_SENSITIVE,双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据。 
      

  17.   

    是你的数据量在数据库里面太大了,无法存到RESULTSET对象中
      

  18.   


    Statement st = con.createStatement(
                          ResultSet.TYPE_FORWARD_ONLY,
                          ResultSet.CONCUR_READ_ONLY);
      

  19.   

    请问大家,关于jdbc内部实现机制有没有详细的资料可以看,请大家推荐一下。
      

  20.   

    http://gotothework.javaeye.com/blog/219726楼主看这个,上面第一个链接第二页开始打不开了。
      

  21.   

    你要修改什么数据? 不能直接使用 update语句吗。
      

  22.   

    兄弟,百万级只是我用来测试造的数据。目前我还没有应用需求,只是我想研究学习一下jdbc的实现机制。