BigInteger 使用了多少空间?

Posted

技术标签:

【中文标题】BigInteger 使用了多少空间?【英文标题】:How much space does BigInteger use? 【发布时间】:2013-02-24 10:12:58 【问题描述】:

BigInteger 对象通常使用多少字节的内存?

【问题讨论】:

一个数组对象一般使用多少字节的内存? ;-) 给你:grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… 阅读:***.com/questions/9368764/… 至少两个最小尺寸的对象。我认为大多数平台上的最小对象大小是 32 字节。 【参考方案1】:

在 64 位 JVM 上使用 VisualVM 保留大小,这里有一些具体数字:

BigInteger 1 digit = 70B(例如:new BigInteger("9")) BigInteger 20 位 = 80B(例如:new BigInteger("12345678901234567890")) BigInteger 100 位 = 112B

比较:

Long(包装类)=24B(但 Long 限于 18-19 位) long(原始)= 8B

所以BigInteger 至少比Long 重3 倍,比long 重10 倍。所以只在真正需要时才使用 BigInteger!

【讨论】:

@BertKing 如前所述,我使用 VisualVM(但还有很多其他工具)进行堆转储【参考方案2】:

关注this 发帖:

BigInteger:
  int bitCount +4 bytes
  int bitLength +4 bytes
  int firstNonzeroIntNum +4 bytes
  int lowestSetBit +4 bytes
  int signum +4 bytes
  int[] mag +?

总共 20 个字节 + 整数数组。长度为 N 的整数数组的大小为 4N + 24(数组开销 + 4 字节/整数)。

总共有 4N + 44 个字节,具体取决于您的数字有多大。不要忘记对对象的引用也使用内存。

编辑:16 个额外字节作为对象开销,使其达到 4N + 60 个字节。对此添加填充(每个对象使用 8 个字节的倍数)我们会得到额外的 4 个字节。

这会产生 4N + 64 个字节。

【讨论】:

你还需要包含两个对象头——每个至少 8 个字节,可能是 16 个。 @HotLicks:你是对的,我已经添加了标题和填充。不过,想想看:你能解释一下你是如何得到两个标题而不是一个吗? 您会得到两个标头,因为数组必须是一个单独的对象(IBM iSeries 的“经典 JVM”除外)。 你指的是int[]数组吗?我相信我已经用分配给它的 24 个字节覆盖了它。 您不需要 int 字段的引用。但是您确实需要数组的引用,因为它是一个单独的对象。【参考方案3】:

BigInteger 在内部使用int[] 来表示您使用的巨大数字。 因此,它确实取决于您存储在其中的数字的大小。如果当前数字不能动态适应,int[] 将会增长。

要获取您的BigInteger 实例当前 使用的字节数,您可以使用Instrumentation 接口,尤其是getObjectSize(Object)

import java.lang.instrument.Instrumentation;

public class ObjectSizeFetcher 
    private static Instrumentation instrumentation;

    public static void premain(String args, Instrumentation inst) 
        instrumentation = inst;
    

    public static long getObjectSize(Object o) 
        return instrumentation.getObjectSize(o);
    

要说服自己,请查看source code,上面写着:

/**
 * The magnitude of this BigInteger, in <i>big-endian</i> order: the
 * zeroth element of this array is the most-significant int of the
 * magnitude.  The magnitude must be "minimal" in that the most-significant
 * int (@code mag[0]) must be non-zero.  This is necessary to
 * ensure that there is exactly one representation for each BigInteger
 * value.  Note that this implies that the BigInteger zero has a
 * zero-length mag array.
 */
final int[] mag;

【讨论】:

【参考方案4】:

Java 对象的大小取决于其字段。这些是 BigInteger 字段

final int signum;
final int[] mag;
private int bitCount;
private int bitLength;
private int lowestSetBit;
private int firstNonzeroIntNum;

我们可以将 BigInteger 实例的大小计算为

8 + 4 + (12 + mag.length * 4) + 4 + 4 + 4 + 4  ~= 40 + mag.length * 4 

见http://www.javamex.com/tutorials/memory/object_memory_usage.shtml

【讨论】:

您遗漏了标题大小。 为什么? BigInteger 为 8,int 数组为 12,看起来还可以 好的——你没有在你的列表中列出那些。

以上是关于BigInteger 使用了多少空间?的主要内容,如果未能解决你的问题,请参考以下文章

Java BigInteger类知识点总结

第五章Biginteger的部分实现

44java大数值剖析

Java中的大数处理类BigInteger和BigDecimar浅析

java BigInteger实现

连接Mysql时出现java.math.BigInteger cannot be cast to java.lang.Long问题