java boolean占用内存大小说明

答案:4B或1B

详细

1、如果boolean是单独使用:boolean占4个字节。

2、如果boolean是以boolean数组形式使用:boolean占1个字节

解释

1、JVM没有提供boolean类型专用的字节指令,而是使用int相关指令来代替。

2、对boolean数组的访问与修改,会共用byte数组的baload和bastore指令。

分析结论

上面的第一个结论是说:boolean在底层实际调用int,那么既然int占4个字节,boolean页自然占4个字节。即 boolean类型占4个字节。

上面的第2个结论是说:boolean数组在底层会用byte指令,那么既然byte占1个字节,boolean数组中的boolean也就占1个字节,即,boolean数组中的boolean占1个字节。

扩展

1、因此,大多数对于boolean,byte,char和short类型数据的操作,实际都提升int,并使用int做为运算类型,所以他们占4个字节,实际上,虚拟机规范也只有4字节和8字节类型(long,float),boolean,char,short都是占了4字节。

2、对于在栈上(局部变量)的byte,char,short类型的数据,在内存中的确会占4字节,但这对于(数组)对象来说并不适用。

java各种类型对象占用内存情况分析

经典篇,有图有真相

为什么写这篇文章?

其实一般的程序猿根本不用了解这么深,只有当你到了一定层次,需要了解jvm内部运行机制,或者高并发多线程下,你写的代码对内存有影响,你想做性能优化。。。等等等等,一句话,当你想深入了解java对象在内存中,如何存储,或者每个对象占用多大空间时,你会感谢这篇文章

本文主要分析jvm中的情况,实验环境为64位window10系统、JDK1.8,使用JProfiler进行结论验证

很多描述以及 概念是基于你懂基本java知识的,如果你看起来有点吃力,要加油咯

基本数据类型占用

类型 占用空间
boolean、byte 1byte
short、char 2byte
int、float 4byte
long、double 8byte

接下来用JProfiler验证:

新建一个空对象,观察空对象内存占用

public class TestObject {
}

对象占用内存 16b,如图

结论:一般自建空对象占用内存 16b,16 = 12 + 4

在TestObj中新增一个 int 属性,观察对象内存占用

public class TestObj {
    private int i;
}

对象占用内存 16b,如图

结论:int 占用 4b, 4 = 16 -12

在TestObj中新增一个 long 属性,观察对象内存占用

public class TestObj {
    private long i;
}

对象占用内存 24b,如图

结论:long 占用 8b, 8 = 24 -12 - 4

其余基本类型可以参照以上自行验证,原理一样

包装类型占用

包装类(Boolean/Byte/Short/Character/Integer/Long/Double/Float)占用内存的大小等于对象头大小加上底层基础数据类型的大小。

类型占用空间Boolean、Byte16byteShort、Char16byteInteger、Float16byteLong、Double24byte 在TestObj中新增一个 Integer 属性,观察对象内存占用

类型 占用空间
Boolean、Byte 16byte
Short、Char 16byte
Integer、Float 16byte
Long、Double 24byte
public class TestObj {
   private Integer  i =128;
}

对象占用内存 32b,如图

结论:Integer 占用 16b, 16 = 32 - 16

特别的:-128~127 之间的封装类型,只占用 4b**

在TestObj中新增一个 Long 属性,观察对象内存占用

public class TestObj {
   private Long  l = new Long(1);
}

对象占用内存 40b,如图

结论:Long 占用 24b, 16 = 40 - 16

其余包装类型可以参照以上自行验证,原理一样

基本类型数组占用

64位机器上,数组对象的对象头占用24 bytes,启用压缩后占用16字节。比普通对象占用内存多是因为需要额外的空间存储数组的长度(普通16b-12b)。

对象数组本身的大小=数组对象头 + length * 存放单个元素大小

在TestObj中新增一个 char[] 属性,观察对象内存占用

public class TestObj {
   private char[] c = {'a','b','c'};
}

对象占用内存 40b,如图

结论:char[3] 占用 24b, 24 = 40 - 16,24 = 16 + 3 * 2 + 2

封装类型数组占用

封装类型数组比基本类型的数组,需要多管理元素的引用

对象数组本身的大小=数组对象头+length 引用指针大小 + length 存放单个元素大小

在TestObj中新增一个 Integer[] 属性,观察对象内存占用

public class TestObj {
    private Integer[] i = {128,129,130};
}

对象占用内存 80b,如图

结论:Integer[3] 占用 80b, 80 = 96 - 16 , 80 = 16 + 3 4 + 3 16 +4

String占用内存 在TestObj中新增一个空 String 属性,观察对象内存占用

public class TestObj {
    private String s = new String("");
}

对象占用内存 40b,如图

结论:String 本身占用 24b, 24 = 40 -16,另外,String的属性value还需要 16b,也就是说空””也需要16b

注意:这里为什么要写String s = new String(“”)?请自己思考,不写会怎么样?

答:如果写成String s = “”,是不会再堆中开辟内存的,也就看不到String占用的空间,你看到的将会是下面的,至于为什么,都是因为final

ArrayList, HashMap的内存占用

这些参考文章开头提到的那篇文章,下面给出计算公式:

一个ArrayList实例本身的的大小为

12(header) + 4(modCount) + 4(size) + 4(elementData reference) = 24 (bytes)

下面分析一个只有一个Integer(1)元素的ArrayList实例占用的内存大小。

ArrayList<Integer> testList = Lists.newArrayList();
testList.add(1);

根据上面对ArrayList原理的介绍,当调用add方法时,ArrayList会初始化一个默认大小为10的数组,而数组中

保存的Integer(1)实例大小为16 bytes。

则testList占用的内存大小为:

24(ArrayList itselft) + 16(elementData array header) + 10 * 4(elemetData reference) + 16(Integer) = 96 (bytes)

JProfiler中的结果验证了上述分析:

2. HashMap内存占用

这里分析一个只有一组键值对的HashMap, 结构如下:

Map<Integer, Integer> testMap = Maps.newHashMap();
testMap.put(1, 2);

首先分析HashMap本身的大小。HashMap对象拥有的属性包括:

/**
   * The table, initialized on first use, and resized as
   * necessary. When allocated, length is always a power of two.
   * (We also tolerate length zero in some operations to allow
   * bootstrapping mechanics that are currently not needed.)
   */
  transient Node<K,V>[] table;

  /**
   * Holds cached entrySet(). Note that AbstractMap fields are used
   * for keySet() and values().
   */
  transient Set<Map.Entry<K,V>> entrySet;

  /**
   * The number of key-value mappings contained in this map.
   */
  transient int size;

  /**
   * The number of times this HashMap has been structurally modified
   * Structural modifications are those that change the number of mappings in
   * the HashMap or otherwise modify its internal structure (e.g.,
   * rehash).  This field is used to make iterators on Collection-views of
   * the HashMap fail-fast.  (See ConcurrentModificationException).
   */
  transient int modCount;

  /**
   * The next size value at which to resize (capacity * load factor).
   *
   * @serial
   */
  // (The javadoc description is true upon serialization.
  // Additionally, if the table array has not been allocated, this
  // field holds the initial array capacity, or zero signifying
  // DEFAULT_INITIAL_CAPACITY.)
  int threshold;

  /**
   * The load factor for the hash table.
   *
   * @serial
   */
  final float loadFactor;

HashMap继承了AbstractMap<K,V>, AbstractMap有两个属性:

transient Set<K>        keySet;
 transient Collection<V> values;

所以一个HashMap对象本身的大小为:

12(header) + 4(table reference) + 4(entrySet reference) + 4(size) + 4(modCount) + 4(threshold) + 8(loadFactor) + 4(keySet reference) + 4(values reference) = 48(bytes)

接着分析testMap实例在总共占用的内存大小。

根据上面对HashMap原理的介绍,可知每对键值对对应一个Node对象。根据上面的Node的数据结构,一个Node对象的大小为:

12(header) + 4(hash reference) + 4(key reference) + 4(value reference)+ 4(next pointer reference) = 28 (padding) -> 32(bytes)

加上Key和Value两个Integer对象,一个Node占用内存总大小为:32 + 2 * 16 = 64(bytes)

JProfiler中结果:

下面分析HashMap的Node数组的大小。

根据上面HashMap的原理可知,在不指定容量大小的情况下,HashMap初始容量为16,所以testMap的Node[]占用的内存大小为:

16(header) + 16 * 4(Node reference) + 64(Node) = 144(bytes)

JProfile结果:

所以,testMap占用的内存总大小为:

48(map itself) + 144(Node[]) = 192(bytes)

JProfile结果:

这里只用一个例子说明如何对HashMap进行占用内存大小的计算,根据HashMap初始化容量的大小,以及扩容的影响,HashMap占用内存大小要进行具体分析,不过思路都是一致的。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详谈java中boolean和Boolean的区别

    boolean是基本数据类型 Boolean是它的封装类,和其他类一样,有属性有方法,可以new, 例如: Boolean flag = new Boolean("true"); // boolean 则不可以! Boolean 是boolean 的实例化对象类,和Integer对应int一样自jdk1.5.0以上版本后,Boolean在"赋值"和判断上和boolean一样, 即是你: boolean b1 = true ; 或者 Boolean b2 = true

  • 计算一个Java对象占用字节数的方法

    本文实例讲述了如何计算(或者说,估算)一个Java对象占用的内存数量的方法.分享给大家供大家参考.具体分析如下: 通常,我们谈论的堆内存使用的前提是以"一般情况"为背景的.不包括下面两种情形:   某些情况下,JVM根本就没有把Object放入堆中.例如:原则上讲,一个小的thread-local对象存在于栈中,而不是在堆中. 被Object占用内存的大小依赖于Object的当前状态.例如:Object的同步锁是否生效,或者,Object是否正在被回收. 我们先来看看在堆中单个的Obj

  • 如何计算Java对象占用了多少空间?

    本文介绍了计算Java对象占用了多少空间的方法,分享给大家供大家参考,具体内容如下 一.对象头 对象的头部至少有两个WORD,如果是数组的话,那么三个WORD,内容如下: 1.对象的HashCode,锁信息等 2.到对象类型数据的指针 3.数组的长度(如果是数组的话) 二.规则 首先,任何对象都是8字节对齐,属性按照[long,double].[int,float].[char,short].[byte,boolean].reference的顺序存放,举个例子: public class Tes

  • java各种类型对象占用内存情况分析

    前言 其实一般的程序猿根本不用了解这么深,只有当你到了一定层次,需要了解jvm内部运行机制,或者高并发多线程下,你写的代码对内存有影响,你想做性能优化.等等等等,一句话,当你想深入了解java对象在内存中,如何存储,或者每个对象占用多大空间时,你会感谢这篇文章 本文主要分析jvm中的情况,实验环境为64位window10系统.JDK1.8,使用JProfiler进行结论验证 很多描述以及 概念是基于你懂基本java知识的,如果你看起来有点吃力,要加油咯 本片更偏重验证,更多理论,请参考:http

  • java boolean占用内存大小说明

    答案:4B或1B 详细 1.如果boolean是单独使用:boolean占4个字节. 2.如果boolean是以boolean数组形式使用:boolean占1个字节 解释 1.JVM没有提供boolean类型专用的字节指令,而是使用int相关指令来代替. 2.对boolean数组的访问与修改,会共用byte数组的baload和bastore指令. 分析结论 上面的第一个结论是说:boolean在底层实际调用int,那么既然int占4个字节,boolean页自然占4个字节.即 boolean类型占

  • java应用占用内存过高排查的解决方案

    故障:收到服务器报警,内存使用率超过80% 1.查看 使用dstat和top查看内存使用最高的应用 使用dstat 查到内存占用最高的是java应用,使用2253M内存,但是这台服务器跑了好几个java,具体哪个进程使用top看下资源情况 使用top 可以看到java应用整体内存使用率超过了70%,其中pid为16494的进程 一个应用占了28.7的内存 2.定位线程问题 使用ps查看16494的线程情况 命令:ps p 16494 -L -o pcpu,pmem,pid,tid,time,tn

  • PHP数组实际占用内存大小原理解析

    一般来说,PHP数组的内存利用率只有 1/10, 也就是说,一个在C语言里面100M 内存的数组,在PHP里面就要1G.下面我们可以粗略的估算PHP数组占用内存的大小,首先我们测试1000个元素的整数占用的内存: <?php echo memory_get_usage() , '<br>'; $start = memory_get_usage(); $a = Array(); for ($i=0; $i<1000; $i++) { $a[$i] = $i + $i; } $mid

  • Android图片占用内存全面分析

    曾经有一个朋友问过我一个问题, 一张512*512  150KB PNG格式图片和一张512*512 100KB 压缩比是8的JPG格式的图片,加载到内存中,也就是加载到一个Bitmap中,哪个占用的内存大? 这个问题似乎有点难回答,测试一下就知道了. 好了,按照要求我准备了三张图片, 1. 512*512px, 114KB, PNG 2. 512*512px, 138KB, JPG ,压缩比 12 3. 512*512px, 57KB, JPG,压缩比 8 接下来是写一个Demo,一个Bitm

  • java启动如何设置JAR包内存大小

    目录 java启动设置JAR包内存大小 给自己的jar包运行时分配内存大小 JVM的一些参数设置 总结 java启动设置JAR包内存大小 亲测可用! java -Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxPermSize=256M -jar a.jar -Xms256m -Xmx512m: 对象使用的内存,也称堆内存 PermSize 类使用的内存,也称永久内存 由于Spring-boot内置tomcat,默认内存占用可能很大,最好设置下jar启动占用的

  • python 基本数据类型占用内存空间大小的实例

    python中基本数据类型和其他的语言占用的内存空间大小有很大差别 import sys a = 100 b = True c = 100L d = 1.1 e ="" f = [] g =() h = {} i = set([]) print " %s size is %d "%(type(a),sys.getsizeof(a)) print " %s size is %d "%(type(b),sys.getsizeof(b)) print

  • 详解Java的堆内存与栈内存的存储机制

    堆与内存优化     今天测了一个项目的数据自动整理功能,对数据库中几万条记录及图片进行整理操作,运行接近到最后,爆出了java.lang.outOfMemoryError,java heap space方面的错误,以前写程序很少遇到这种内存上的错误,因为java有垃圾回收器机制,就一直没太关注.今天上网找了点资料,在此基础上做了个整理.  一.堆和栈 堆-用new建立,垃圾回收器负责回收 1.程序开始运行时,JVM从OS获取一些内存,部分是堆内存.堆内存通常在存储地址的底层,向上排列. 2.堆

  • java 中堆内存和栈内存理解

     Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用. 堆内存用于存放由new创建的对象和数组.在堆中分配的内存,由java虚拟机自动垃圾回收器来管理.在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存

随机推荐