`

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是否相等。
1
1
分享到:
评论
5 楼 demoxshiroki 2015-04-28  
for循环中每次都实例一个BitSet做演示用的?
4 楼 bingyingao 2014-05-23  
qindongliang1922 写道
bingyingao 写道
qindongliang1922 写道
它会取>id最大的,而且是64的倍数 的整数,作为容量,bit存储,很省内存的,40亿的数字,才400M内存不到,楼主的OOM,具体是个怎么情况?

我上面补充了代码再现了我的情况

你这key_index 也没多大啊,才305000

305000还不大?305000/8/1024=38kb

就是说下面这样一个BitSet占38Kb,5000个就是190MB,这个量级已经极有可能把堆占满了
BitSet bs=new BitSet();
bs.set(305000);
3 楼 qindongliang1922 2014-05-23  
bingyingao 写道
qindongliang1922 写道
它会取>id最大的,而且是64的倍数 的整数,作为容量,bit存储,很省内存的,40亿的数字,才400M内存不到,楼主的OOM,具体是个怎么情况?

我上面补充了代码再现了我的情况

你这key_index 也没多大啊,才305000
2 楼 bingyingao 2014-05-23  
qindongliang1922 写道
它会取>id最大的,而且是64的倍数 的整数,作为容量,bit存储,很省内存的,40亿的数字,才400M内存不到,楼主的OOM,具体是个怎么情况?

我上面补充了代码再现了我的情况
1 楼 qindongliang1922 2014-05-12  
它会取>id最大的,而且是64的倍数 的整数,作为容量,bit存储,很省内存的,40亿的数字,才400M内存不到,楼主的OOM,具体是个怎么情况?

相关推荐

    浅谈Java BitSet使用场景和代码示例

    Java BitSet 使用场景和代码示例 Java BitSet 是 Java 中的一个重要类,它实现了一个按需增长的位向量。BitSet 的每一个组件都有一个 boolean 值,用非负的整数将 BitSet 的位编入索引。可以对每个编入索引的位进行...

    对java的BitSet的多线程并发的探索

    这篇博文主要探讨了如何在多线程环境下正确地使用Java的BitSet。 首先,我们要理解BitSet的基本原理。BitSet内部以long数组存储位,每一位代表一个布尔值,0表示false,1表示true。由于long的基本操作(如按位或、...

    java bitset 源码解析.rtf

    java bitset 高级数据结构 源码解析 适合 0-3 年开发人员,进阶、面试必备知识!

    javabitset源码-javaewah:JavaBitSet类的压缩替代品

    bitset源码Java 这是 Java Bitset 类的字对齐压缩变体。 我们提供 64 位和 32 位类似 RLE 的压缩方案。 它可用于实现位图索引。 它所依赖的 EWAH 格式用于运行 GitHub 的 git 实现。 字对齐压缩的目标不是实现最佳...

    java 原生包 BitSet 源码

    Java中BitSet类是Java集合框架的一部分,它是一种用于处理位操作的高级数据结构。BitSet可以看作是一个只存储布尔值的数组,但相比于原始的布尔数组,BitSet更加内存高效,因为它以64位的块(word)来存储多个布尔值...

    javabitset源码-JerrySoundCode:杰瑞声码

    bitset源码Java源码分析 基础集合列表 ArrayList (done) Vector (done) LinkedList (done) Stack (done) ReferenceQueue (done) ArrayDeque (done) Set HashSet (done) TreeSet (done) LinkedHashSet (done) BitSet ...

    javabitset源码-java_master:后端架构师技术图谱

    java bitset 源码 最后更新于20180424 (Toc generated by ) 数据结构 队列 非阻塞队列:ConcurrentLinkedQueue(无界线程安全),采用CAS机制(compareAndSwapObject原子操作)。 阻塞队列:ArrayBlockingQueue(有界...

    BitSet 源码分析.txt

    基于JDK1.8的BitSet 源码分析, 描述了实现的原理 个方法的含义 虽然没有写出实际的测试代码 但是只要是细度了我的这个分析 在使用的时候就不是问题了

    javabitset源码-Java8-learning:学习Java8新特性

    bitset 源码 对于Java开发者来说,Java8的版本显然是一个具有里程碑意义的版本,蕴含了许多令人激动的新特性,如果能利用好这些新特性,能够大大提升我们的开发效率。Java8的函数式编程能够大大减少代码量和便于维护...

    bitset用法 bitset用法

    在这段代码中,我们使用了`bitset`的多个功能,包括初始化、设置位、计数等。通过这个例子我们可以看到`bitset`在实际应用中的灵活性和效率。 总之,`bitset`是一个功能强大的工具,能够帮助我们有效地处理二进制...

    javabitset源码-myleetcode:所有LeetCode问题的记录

    java bitset源码 目前进度(171/237) LeetCode做题笔记 Add two numbers:给定一个数集合和一个数,已知集合中有两个数的和是给定数,求这两个加数的index 方法1:暴力,n^2时间复杂度,不推荐 方法2:快速排序nlogn...

    C语言头文件 BITSET

    C语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC语言头文件 BITSETC...

    动态Bitset源代码

    在C++的STL中实现由一个bitset类模板,其用法如下: std::bitset&lt;64&gt; bs; 也就是说,这个bs只能支持64位以内的位存储和操作;bs一旦定义就不能动态增长了。本资源附件中实现了一个动态Bitset,和标准bitset兼容。 /*...

    java基础之BitSet - 副本.md

    java基础之BitSet - 副本

    javabitset源码-montysolr:Solr天体物理数据系统

    在标题提及的 "javabitset源码-montysolr:Solr天体物理数据系统" 中,我们可以推测这个项目可能是在Solr(一个流行的全文搜索引擎)中使用BitSet来处理天体物理数据。下面我们将深入探讨Java BitSet以及它如何应用于...

    RoaringBitmap, 在Java中,一个更好的压缩 bitset.zip

    RoaringBitmap, 在Java中,一个更好的压缩 bitset RoaringBitmap Bitsets,也称为位图,通常用作快速数据结构。 不幸的是,他们可以使用太多的内存。 为了补偿,我们经常使用压缩位图。咆哮位图是压缩位图,它比传统...

    javabitset源码-all-kinds-book:java大数据sparkflinkredishivehbasekafka面试题数据结构

    bitset 源码 all-kinds-book 主要包含 java 大数据 数据仓库 数据分析 第三方组件 面试题 数据结构与算法 设计模式 软件设计 等文档 ,可以访问我们的官网查看更多内容 [人在地上跑 牛在天上飞](#人在地上跑 牛在...

    javabitset源码-Study:学习

    java bitset源码 Study 少有人走的路 数据结构 队列 集合 链表、数组 字典、关联数组 栈 树 二叉树 完全二叉树 平衡二叉树 二叉查找树(BST) 红黑树 B,B+,B*树 LSM 树 BitSet 常用算法 计数排序 桶排序 基数排序 ...

    使用bitset实现毫秒级查询(实例讲解)

    bitset是Java中的一种数据结构,通过使用bitset可以实现毫秒级查询。下面我们将详细讲解如何使用bitset实现毫秒级查询。 bitset的内部实现是long数组,每一个位的默认值为false(0)。bitset的长度可以按需增长,...

Global site tag (gtag.js) - Google Analytics