《零基础学 Java》 FAQ 之 9-Java里的各种数据类型占用多少内存空间

发布于: 21 小时前
《零基础学 Java》 FAQ 之 9-Java里的各种数据类型占用多少内存空间

来自@谭低调 同学的问题:引用占用多少内存?

@谭低调 同学在“34 | 认识引用类型(下)”里问了这么一个问题:

请问老师,Merchandise m1这个引用类型变量是多大呢?或者说为了存储实例的地址,需要给m1多大的内存?

简单版

简单来说,基本数据类型都是按照最小的、值域规定的范围使用的内存。比如byte,boolean都是1个字节。int和float是4个字节,long和double是8个字节

但是对于引用类型来说,32位的机器,引用类型要占用32个bit,也就是4byte。64位的,要占用8个byte。但是对于64位的虚拟机,可以开启引用压缩选项,让它也只占用4个byte。

如果有兴趣,可以看下的啰嗦版。

Java 程序员需要关心数据类型对内存的占用情况吗?

Java 用跑在虚拟机里,并且有一个严格得虚拟机规范,就是让程序员可以在不知道这这些底层细节的情况下,也能好好安心写程序。这个目标是非常正确的,甚至是对 Java 的成功都是非常关键的。

软件的世界就是这样,一个层次解决一个层次的问题,既然 JVM 已经屏蔽了底层细节信息,上层的 Java 代码就可以不必关心更下层的细节了。

但是不必了解,并非是了解了没用。不了解也能写出好代码,了解了之后在某些情况下可以写出更好的代码。尤其是在对程序关键点的数据结构设计和预估程序总体内存占用情况时,会有帮助。

JVM 规范没规定

JVM 规范从来没有规定每种数据类型占用多大的内存。它只是给出了每种数据类型的值域。严谨的不要不要的。既然规范没有说,那么肯定占用的内存就可以是不固定的喽。具体占用多少,得看规范得实现。

那么具体到某种实现,就是固定得了么?

JDK 实现:看位数

很多年前,主流的操作系统和 CPU 都是32位的。什么意思呢,就是 CPU 的指令能够处理的数,都是32位的,包括内存寻址,也是32位的。所以32位的系统下,可以使用的内存不能超过4G,因为32位的寻址空间只能表示这么大的内存地址范围。

后来出现了64位的操作系统和 CPU,寻址空间和 CPU 操作数都是64位了。Java 进程也是操作系统上的应用程序。我们知道程序都分64位版和32位版,JDK 也一样。

对于栈和堆的上的数据,可以分配的有基本数据类型和引用类型。

基本数据类型很简单,大部分JVM都会按照值域来分配最小的需要的内存,这个我们在前面已经介绍过。

引用类型:磨人的小妖精

引用类型作为一种非常特殊的类型,和内存寻址相关。所以,JDK 底层实现上一般会使用C/C++的 pointer 来封装成 Java 里的引用。那么它占用的内存就是和 JDK 是32位还是64位有关。如果是64位的 JDK,那么在上述的内存区域里,引用类型都是占用8个字节的内存。32位的 JDK 就占4个字节。

如果引用类型这么简单直接,就不是磨人的小妖精了。引用类型毕竟太多,而且绝大多数情况下用不了这么大空间,太浪费。所以 Oracle 的JDK就针对这种情况,开发了一个压缩指针的功能,主要针对 Java 内存堆小于32g的情况。这个 JVM 参数是-XX:+UseCompressedOops 下面是 Oracle 官方文档对这个参数的说明:

Enables the use of compressed pointers (object references represented as 32 bit offsets instead of 64-bit pointers) for optimized 64-bit performance with Java heap sizes less than 32gb.

引自 https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html


这篇文章来自极客时间推出的《零基础学Java》中的FAQ。除了在每节视频课下方回答大家的问题之外,针对大家提出的优质问题或者普遍问题,如果需要更大篇幅的文章解答,则会在FAQ中以文章的方式给出回答。带你零基础入门,夯实Java,课程地址:https://time.geekbang.org/course/intro/181

发布于: 21 小时前 阅读数: 17
用户头像

臧萌

关注

一线程序员,偶尔写写字 2017.10.20 加入

《零基础学 Java》 视频课作者 《Java入门1·2·3》作者

评论

发布
暂无评论
《零基础学 Java》 FAQ 之 9-Java里的各种数据类型占用多少内存空间