深入拆解 Java 虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
87446 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
模块四:黑科技 (3讲)
深入拆解 Java 虚拟机
15
15
1.0x
00:00/00:00
登录|注册

02 | Java的基本类型

Java基本类型的大小
Java的基本类型
Java虚拟机的boolean类型
Java基本类型

该思维导图由 AI 生成,仅供参考

如果你了解面向对象语言的发展史,那你可能听说过 Smalltalk 这门语言。它的影响力之大,以至于之后诞生的面向对象语言,或多或少都借鉴了它的设计和实现。
在 Smalltalk 中,所有的值都是对象。因此,许多人认为它是一门纯粹的面向对象语言。
Java 则不同,它引进了八个基本类型,来支持数值计算。Java 这么做的原因主要是工程上的考虑,因为使用基本类型能够在执行效率以及内存使用两方面提升软件性能。
今天,我们就来了解一下基本类型在 Java 虚拟机中的实现。
public class Foo {
public static void main(String[] args) {
boolean 吃过饭没 = 2; // 直接编译的话javac会报错
if (吃过饭没) System.out.println("吃了");
if (true == 吃过饭没) System.out.println("真吃了");
}
}
在上一篇结尾的小作业里,我构造了这么一段代码,它将一个 boolean 类型的局部变量赋值为 2。为了方便记忆,我们给这个变量起个名字,就叫“吃过饭没”。
赋值语句后边我设置了两个看似一样的 if 语句。第一个 if 语句,也就是直接判断“吃过饭没”,在它成立的情况下,代码会打印“吃了”。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了Java基本类型在Java虚拟机中的实现,重点关注了boolean类型在内存中的映射,以及整数类型和浮点类型的特性。文章首先介绍了boolean类型在Java虚拟机中被映射为整数类型,true被映射为1,false被映射为0。接着详细讨论了整数类型和浮点类型的取值范围、特性以及在程序中的应用。特别是对于浮点类型,文章详细介绍了IEEE 754浮点数格式,包括+0.0F、-0.0F、正无穷、负无穷和NaN的定义及特性。此外,还提到了在程序中进行浮点数比较时需要考虑的特性。文章还涉及了基本类型在栈帧和堆中的占用大小以及存取操作时的掩码操作。总的来说,本文通过具体的例子和技术细节,深入浅出地介绍了Java基本类型在Java虚拟机中的实现,对于想要深入了解Java基本类型的读者来说,是一篇值得阅读的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(125)

  • 最新
  • 精选
  • 丨落灬小莫
    当替换为2的时候无输出 当替换为3的时候打印HelloJava及HelloJVM 猜测是因为将boolean 保存在静态域中,指定了其类型为'Z',当修改为2时取低位最后一位为0,当修改为3时取低位最后一位为1 则说明boolean的掩码处理是取低位的最后一位

    作者回复: 对的!

    2018-07-23
    13
    339
  • Kyle
    老师,文中看你说到: “也就是说,boolean、byte、char、short 这四种类型,在栈上占用的空间和 int 是一样的,和引用类型也是一样的。因此,在 32 位的 HotSpot 中,这些类型在栈上将占用 4 个字节;而在 64 位的 HotSpot 中,他们将占 8 个字节。” 但是我记得boolean在内存中占1字节,char占2字节,这里是什么个意思?

    作者回复: 你说的是在堆里的情况。在解释器栈上是不一样的。至于原因吗,主要是变长数组不好控制,所以就选择浪费一些空间,以便访问时直接通过下标来计算地址。

    2018-07-23
    2
    69
  • LC
    老师可以讲下ASM、Unsafe和CAS的底层原理吗?这块儿一直是个拦路虎,谢谢!

    作者回复: ASM你指的是那个字节码工程包吗?是的话那就是一个提供了字节码抽象的工具,允许用Java代码来生成或者更改字节码。JDK里也会用到ASM,用来生成一些适配器什么的。我印象中代码覆盖工具JaCoCo也是用ASM来实现的。 Unsafe就是一些不被虚拟机控制的内存操作的合集。具体想要了解哪个API? CAS可以理解为原子性的写操作,这个概念来自于底层CPU指令。Unsafe提供了一些cas的Java接口,在即时编译器中我们会将对这些接口的调用替换成具体的CPU指令。

    2018-07-23
    3
    58
  • 曲东方
    Unsafe.putBoolean和Unsafe.puByte是native实现 putBoolean和putByte也是通过宏SET_FIELD模板出的函数 #define SET_FIELD(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ *(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x) unsafe.cpp中定义宏做truncate #define truncate_jboolean(x) ((x) & 1) #define truncate_jbyte(x) (x) #define truncate_jshort(x) (x) #define truncate_jchar(x) (x) #define truncate_jint(x) (x) #define truncate_jlong(x) (x) #define truncate_jfloat(x) (x) #define truncate_jdouble(x) (x) 综上:unsafe.Put*不会对值做修改 ------------------------------------------------------------------------------------ getBoolean和getByte也是通过宏GET_FIELD模板出的函数 #define GET_FIELD(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset) 综上,unsafe.Get*不会对值做修改 ------------------------------------------------------------------------------------ 验证: unsafe.putByte(foo, addr, (byte)2); // 设置为: 2 System.out.println(unsafe.getByte(foo, addr)); // 打印getByte: 2 System.out.println(unsafe.getBoolean(foo, addr)); // 打印getBoolean: true unsafe.putByte(foo, addr, (byte)1); // 设置为: 1 System.out.println(unsafe.getByte(foo, addr)); // 打印getByte: 1 System.out.println(unsafe.getBoolean(foo, addr)); // 打印getBoolean: true ------------------------------------------------------------------------------------ 疑问: if(foo.flag)判断,使用getfield Field flag:"Z",执行逻辑等于:0 != flag if(foo.getFlag())判断,使用invokevirtual Method getFlag:"()Z",执行逻辑等于: 0 != ((flag) & 1) 求大神帮忙解答 -------------------------- 附getFlag jasm码: public Method getFlag:"()Z" stack 1 locals 1 { aload_0; getfield Field flag:"Z"; ireturn; } https://gist.github.com/qudongfang/49635d86882c03e49cff2b0f7d833805

    作者回复: 研究得非常深入! Unsafe.putBoolean会做掩码,另外方法返回也会对boolean byte char short进行掩码

    2018-07-23
    2
    38
  • Geek_dde3ac
    你好,在内存中都是0,那么是如何区别是哪种类型数据的呢?

    作者回复: 内存中是不做区分的。Java程序想要把它解读成什么类型,它就是什么类型。

    2018-07-23
    2
    33
  • 落叶飞逝的恋
    其实那个boolean的true虚拟机里面为1,也就是if(true==吃了没)其实可以替换成if(1==2)这样理解吧

    作者回复: 对的!

    2018-07-24
    21
  • dong
    感觉"吃饭了"例子,弄得有点饶了。也有些地方语句的起承转合不是很通顺,个人理解。

    作者回复: 谢谢建议

    2018-07-27
    18
  • 别处
    以下两个引至本文内容: 1、在 Java 虚拟机规范中,boolean 类型则被映射成 int 类型。 2、在 HotSpot 中,boolean 字段占用一字节, 问题:一个是int类型,一个是一个字节(32位系统的话就是byte类型),是没讲透还是错误?

    作者回复: 多谢指出。严格来说,前者指的是计算的时候被映射成int类型,后者指的是存储到堆中是一个字节。

    2018-07-24
    16
  • Invincible、
    为什么我不能让boolvalue=2或者3……

    作者回复: 因为javac不支持这种操作,它把boolean是用int实现的这种虚拟机的实现细节给隐藏起来了,从而使得在语言层面没有这种会引起歧义的值。

    2018-11-29
    12
  • 星星
    long,double,float三种类型存入操作数栈有做转化操作吗?还是做浮点运算会有特殊处理,本文没有提及呀。

    作者回复: 同样会加载至操作数栈上,但都当成各自类型来计算,而不是像其他几种,被当成int来计算

    2018-09-25
    6
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部