代码之家  ›  专栏  ›  技术社区  ›  Amit

超出开销限制

  •  3
  • Amit  · 技术社区  · 16 年前

    下面的代码在运行jdk1.6.0\u14但在jdk1.6.0\u20上运行良好的linux3.5enterprisebox上抛出OutofMemoryError我不知道为什么会发生这种情况。

    while (rs.next()) {
      for (TableMetaData tabMeta : metaList) {
    rec.append(getFormattedString(rs, tabMeta));
      }
      rec.append(lf);
      recCount++;
      if (recCount % maxRecBeforWrite == 0) {
        bOutStream.write(rec.toString().getBytes());
        rec = null;
        rec = new StringBuilder();
      }
    }
    bOutStream.write(rec.toString().getBytes());
    

    getFormattedString()方法如下:

    private String getFormattedString(ResultSet rs, TableMetaData tabMeta)
            throws SQLException, IOException {
    
        String colValue = null;
        // check if it is a CLOB column
        if (tabMeta.isCLOB()) {
            // Column is a CLOB, so fetch it and retrieve first clobLimit chars.
            colValue = String.format("%-" + clobLimit + "s", getCLOBString(rs,
                    tabMeta));
        } else {
            colValue = String.format("%-" + tabMeta.getColumnSize() + "s", rs
                    .getString(tabMeta.getColumnName()));
        }
        return colValue;
    }
    

    以下是异常跟踪:

    Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
            at java.util.Formatter$FormatSpecifier.justify(Formatter.java:2827)
            at java.util.Formatter$FormatSpecifier.print(Formatter.java:2821)
            at java.util.Formatter$FormatSpecifier.printString(Formatter.java:2794)
            at java.util.Formatter$FormatSpecifier.print(Formatter.java:2677)
            at java.util.Formatter.format(Formatter.java:2433)
            at java.util.Formatter.format(Formatter.java:2367)
            at java.lang.String.format(String.java:2769)
            at com.boa.cpal.cpal2repnet.main.CPALToReportNet.getFormattedString(Unknown Source)
    

    请注意,编写此代码的目的是查询具有巨大表的数据库,以读取结果集并创建具有特定格式的提取文件。

    2 回复  |  直到 16 年前
        1
  •  2
  •   Stephen C    14 年前

    -XX:+usegcoveredlimit-在抛出OutOfMemory错误之前,使用限制VM在GC中花费的时间比例的策略。(第6章介绍)

    所以,我最好的猜测是,您的应用程序只是在耗尽堆空间。正如@Andreas\u D的回答所说,缺省堆大小在jdk1.6.0\u 14和jdk1.6.0\u 20之间发生了变化,这可以解释不同的行为。您可以选择:

    • 升级到更高版本的JVM。( 更新-2012/06 即使是jdk1.6.0\u20现在也已经非常过时了。后来的1.6和1.7版本有许多安全补丁。)

    您还可以调整GC开销限制,但在生产服务器上这可能是个坏主意。

    如果这个特殊的问题只发生在服务器运行一段时间之后,那么可能是内存泄漏。

        2
  •  0
  •   Andreas Dolk    16 年前

    在客户机JVM中,已经修改了默认的Java堆配置,以提高当今富客户机应用程序的性能。初始堆大小和最大堆大小更大,与分代垃圾收集相关的设置得到更好的调整。

    请快速查看本文档中的详细信息 release notes 让我相信这就是为什么1.6.0\u20的问题更少的原因。


    代码的以下部分与注释不一致:

    // Column is a CLOB, so fetch it and retrieve first clobLimit chars.
    colValue = String.format("%-" + clobLimit + "s", getCLOBString(rs, tabMeta));
    

    colValue clobLimit CLOB中的字节,在

     System.out.println(String.format("%-5s", "1234567890"));
    

     1234567890
    

    要实现您在评论中所说的内容,您可以使用更简单的形式:

    colValue = getCLOBString(rs, tabMeta).substring(0, clobLimit);