1 | /** |
该 native 方法在我开发 Java Agent 的过程中进行了调试,发现对于满足实现关系的类,如果不是由相同的类加载器加载,则会返回 false。
1 | /** |
该 native 方法在我开发 Java Agent 的过程中进行了调试,发现对于满足实现关系的类,如果不是由相同的类加载器加载,则会返回 false。
关于上下文类加载器,之前一直只是了解,在开发过程中并未使用过,直到开发 Java Agent 时,才真正明白其作用,本文作简要记录。在 Java SPI 机制的核心类 ServiceLoader 中,有以下代码:
1 | /** |
MySQL JDBC 驱动在未配置流式读取或游标相关参数的情况下,默认会使用静态结果集进行数据的接收,其中源码位于 MysqlIO.java at release/5.1:
1 | private RowData readSingleRowSet(long columnCount, int maxRows, int resultSetConcurrency, boolean isBinaryEncoded, Field[] fields) throws SQLException { |
在 Redis 官网的数据类型介绍中对 Bitmap 部分有如下描述:
Bitmaps are not an actual data type, but a set of bit-oriented operations defined on the String type. Since strings are binary safe blobs and their maximum length is 512 MB, they are suitable to set up to 232 different bits.
可知,Redis 中的 Bitmap 由 String 实现,且因为 Redis 中的 String 是二进制安全的且最大长度为 512MB,所以支持存储 512 × 1024 × 1024 × 8 = 4294967296 = 232 个比特位。其中还提到仅需 512MiB 即可存储 40 亿用户的比特位信息。
我曾开发过基于 RoaringBitmap 的分布式去重服务,用于在线用户数去重统计及离线计算中的去重统计,本文基于 0.9.8 简要分析 RoaringBitmap 的底层数据结构。
Java 中基本类型 int 为有符号实现,可表示的范围为 [-2147483648, 2147483647],即整个范围段长达 42 亿之多,即使是仅使用正数部分也有 21 亿,对于大部分公司的用户维度的统计已经足够,所以我们选择基于 32 位 int 的 RoaringBitmap 进行分析。如果对基于 64 位 long 的 Roaring64Bitmap 实现感兴趣,可以自行查看源码:Roaring64Bitmap.java。
RoaringBitmap 的整体设计思想是把 32 位的 int 整数拆分为两个 16 位的部分进行存储,高 16 位的部分用于定位低 16 位的部分存储在哪一个 container,然后在对应的 container 中存储低 16 位值。可能上面的说法有一点抽象,我们使用最常用的 add 方法进行分析,add 方法用于将一个 int 类型的整数添加至 RoaringBitmap,其源码实现如下:
1 | /** |