java的BitSet使用不当引发OutOfMemory

java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2858)
at java.util.BitSet.ensureCapacity(BitSet.java:155)
at java.util.BitSet.expandTo(BitSet.java:170)
at java.util.BitSet.set(BitSet.java:265)


项目中大量使用了BitSet,在一次小需求中,我将原始的数据到处到临时数据库,并且做了一些初始化,项目run起来的会后要去加载库中所有数据到内存。
其中有BitSet bitSet=new BitSet();bitSet.set(X),这么一行代码,这个X是从数据库加载的,表中大概有几千条数据,一加载就内存溢出,后来终于分析到是因为我在初始化DB的时候将X都赋值为该条记录id,因为是开发库,id已经是亿以上的数字了,导致X都是几亿几亿的,而原来是1千以下,再来.set(X),就很耗用内存了,用visulaVM工具分析发现long型数组占用了45%的堆内存,仔细了解一下BitSet数据存储方式就明白了.

它是大小可动态改变, 取值为true或false的位集合。用于表示一组布尔标志。
默认占64个bit。不够用时会自动扩展64的整数倍.

补充说明一下,我当时的场景大概的原理如下:
/**
 * BitSet导致使用不当导致堆内存溢出
 * @author bingyin.gby
 * @version $Id: Test.java, v 0.1 2014年5月23日 下午1:52:27 bingyin.gby Exp $
 */
public class Test {
    private static List<BitSet> bitSetList = new ArrayList<BitSet>();

    /**
     * 问题原因:因为数据库中的key_index设置过大导致内存泄露,
     * 我系统中得到的BitSet是要保留在内存中,以便下一次直接使用。
     * 因为key_index最初我们库中都是比较小的,所以无问题,在一个
     * 开发库中把所有key_index值更新为它自己的id,而恰好这个库中的id是比较大的,就引发了这个问题
     * @param args
     */
    public static void main(String[] args) {
        long totalSize = 0;
        for (int key_index = 300000; key_index < 305000; key_index++) {
            BitSet bitSet = new BitSet();
            try {
                bitSet.set(key_index);
                bitSetList.add(bitSet);
                totalSize += bitSet.size() / 8 / 1024;
                System.out.println("累计:" + totalSize + "kb");
            } catch (Throwable e) {
                System.out.println(key_index + "累计:" + totalSize / 1024 + "mb导致了内存溢出");
                System.exit(1);
            }
        }

    }
}



补充说明:
定义
一个大小可动态改变, 取值为true或false的位集合。用于表示一组布尔标志。
位的值为布尔型,初始大小为64bit,初始值均为“false”
0000000000000000000000000000000000000000000000000000000000000000 共64位。
如果要存储数字5,则需要:00005……. 0共64位
如果要存储数字100,则需要:00000…….100….0共128位

常用方法
void set(int bitIndex):将bitIndex位置的值设为“true”或者给定的值
void or(BitSet other): other同该字位集进行或操作,结果作为该字位集的新值。
void and(BitSet other): other同该字位集进行与操作,结果作为该字位集的新值。
boolean equals(BitSet bs):比较两个BitSet是否相等。

你可能感兴趣的:(java,jvm,bitset,OutOfMemory)