当前位置:首页 > 开发 > 编程语言 > Java > 正文

java的BitSet使用不当引发OutOfMemory

发表于: 2014-05-11   作者:bingyingao   来源:转载   浏览次数:
摘要: 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 ja
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的BitSet使用不当引发OutOfMemory

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
最近使用第三方开源库jflvlib录制flv格式视频,测试过程发现,视频录制进程经常挂掉; java启动参数
最近使用第三方开源库jflvlib录制flv格式视频,测试过程发现,视频录制进程经常挂掉; java启动参数
最近使用第三方开源库jflvlib录制flv格式视频,测试过程发现,视频录制进程经常挂掉; java启动参数
修改eclipse.ini文件 -vmargs -Xms40m -Xmx512m =================================================
本文介绍的是Java里一个内建的概念,Finalizer。你可能对它如数家珍,但也可能从未听闻过,这得看你
个人觉得bitset很不错,特别是转化成二进制,还可以将0-1字符串转化成bitset,而bitset可以直接输出
vector是一个容器,可以看做是一个大小可变化的数组,所以其特性有: 1)大小可变 2)容器内的数据
我们知道,Sun JVM分代垃圾回收器把堆空间分成3块: Young Gen:年轻代,包括1个Eden区和2个Suvivor
转自:http://ayufox.iteye.com/blog/646125 我们知道,Sun JVM分代垃圾回收器把堆空间分成3块: Yo
转自:http://ayufox.iteye.com/blog/646125 我们知道,Sun JVM分代垃圾回收器把堆空间分成3块: Yo
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号