【发布时间】:2013-05-09 12:32:50
【问题描述】:
我编写了一个小型 java 程序,它使用简单的 JDBC 调用从 DB2 数据库加载数据。我正在使用选择查询来获取数据并为此使用 java 语句。我已正确关闭语句和连接对象。我正在使用 64 位 JVM 进行编译和运行程序。
查询返回 5200 万条记录,每行有 24 列,在 Unix(具有多处理器环境)中加载完整数据大约需要 4 分钟。我使用 HashMap 作为数据结构来加载数据:Map<String, Map<String, GridTradeStatus>>。 GridTradeStatus bean 是一个简单的 getter/setter bean,其中包含 24 个属性。
程序所需的内存高得惊人。 Java 堆大小高达 5.8 - 6GB 以加载完整数据,而实际使用的堆大小保持在 4.7 - 4.9GB 之间。我知道我们不应该将这么多数据加载到内存中,但我的业务需求只是这样。
问题是,当我将表的全部数据放在一个平面文件中时,它的大小大致相当于 ~1.2GB。我想知道为什么我的 java 程序消耗的内存是其实际大小的 4 倍。
【问题讨论】:
-
Java 中的字符串使用 UTF-16,这意味着每个字符 2 个字节。因此,如果您的 txt 文件是正常的 8 位/字符编码,则会导致那里的 ram 使用率加倍。另外,如果使用 substring 方法,请记住,只要 substring 对象还活着,原始字符串 newer 就会被释放。
-
感谢您的评论。是否有可能指示 JVM 使用 UTF-8 编码?
-
不是直接的。 java.lang.String 将始终使用 UTF-16。但我确信谷歌搜索可以给你一个 java 字符串类,它使用 utf-8 或其他 8 位编码。
-
是的,非常感谢,在搜索了一段时间后,我在这里找到了一个 vmoption
-XX:+UseCompressedStrings(oracle.com/technetwork/java/javase/tech/…),它表示在字符串中使用了 byte[]。通过使用这个选项,我可以看到大约 500MB 的内存改进。 -
这里真正的问题是为什么要将 5200 万行加载到内存中。这是一种糟糕的做法,并且鉴于数据的增长,它迟早会完全停止工作。一次处理一行。