热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JVM——(21)字节码指令集与解析三(类型转换指令)

文章目录往期文章前言一、类型转换指令的概述二、类型转换指令的宽化类型转换精度损失问题补充说明三、类型转换指令的窄型转换转换规则精度损失问题补充说明往期文章JVM——(1)为什么学习

文章目录

  • 往期文章
      • 前言
      • 一、类型转换指令的概述
      • 二、类型转换指令的宽化类型转换
        • 精度损失问题
        • 补充说明
      • 三、类型转换指令的窄型转换
        • 转换规则
        • 精度损失问题
        • 补充说明
往期文章

JVM——(1)为什么学习虚拟机
JVM——(2)聊聊JVM虚拟机
JVM——(3)类加载子系统
JVM——(4)运行时数据区的概述与程序计数器(PC寄存器)
JVM——(5)运行时数据区的虚拟机栈
JVM——(6)运行时数据区的本地方法栈
JVM——(7)运行时数据区的堆空间
JVM——(8)运行时数据区的方法区
JVM——(9)对象的实例化与访问定位
JVM——(10)执行引擎
JVM——(11)String Table(字符串常量池)
JVM——(12)垃圾回收概述
JVM——(13)垃圾回收相关算法
JVM——(14)垃圾回收相关概念的概述
JVM——(15)垃圾回收器详细篇
JVM——(16)Class文件结构一(描述介绍)
JVM——(17)Class文件结构二(解读字节码)
JVM——(18)Class文件结构三(JAVAP指令)
JVM——(19)字节码指令集与解析一(局部变量压栈、常量变量压栈、出栈局部变量表指令)
JVM——(20)字节码指令集与解析二(算数指令)
JVM——(21)字节码指令集与解析三(类型转换指令)
JVM——(22)字节码指令集与解析四(对象创建与访问指令)
JVM——(23)字节码指令集与解析五(方法调用指令与方法返回指令)
JVM——(24)字节码指令集与解析六(操作数栈管理指令)

前言

本篇文章继续学习字节码指令集中的类型转换指令,看看具体指令是怎么操作数据类型转换?

一、类型转换指令的概述

类型转换指令可以将两种不同的数值类型进行相互转换

这些转换操作一般用于实现用户代码中的显式类型转换操作,或者用来处理字节码指令集中数据类型相关指令无法与数据类型一一对应的问题。

主要有以下两种类型转换:宽化类型转换与窄化类型转换

二、类型转换指令的宽化类型转换

Java虚拟机直接支持以下数值的宽化类型转换(widening numeric conversion,小范围类型向大范围类型的安全转换)。也就是说并不需要指令执行,包括:

  • 从int类型到long、float或者double类型。对应的指令为: i2l、i2f、 i2d。
  • 从long类型到float、double类型。对应的指令为:l2f、l2d
  • 从float类型到double类型。对应的指令为:f2d

简化为: int –> long –> float –> double

接下来我们针对于宽化类型转换的基本测试,请看以下示例代码

public class classcastTest{
//宽化类型转换
//针对于宽化类型转换的基本测试
public void upcast1(){
int i = 10;
long l = i;
float f = i;
double d = i;
float fl = l;
double d1 = l;
double d2 - fl;
}
}

接下来我们编译该代码,看看方法的字节码是用什么指令进行类型转换的?
《JVM——(21)字节码指令集与解析三(类型转换指令)》

精度损失问题

================================

宽化类型转换是不会因为超过目标类型最大值而丢失信息的,例如从int转换到 long,或者从int转换到double,都不会丢失任何信息,转换前后的值是精确相等的。

从int、long类型数值转换到float,或者long类型数值转换到double时,将可能发生精度丢失:可能丢失掉几个最低有效位上的值,转换后的浮点数值是根据IEEE754最接近舍入模式所得到的正确整数值。

接下来我们针对于精度损失问题的基本测试,请看以下示例代码

public class classcastTest{
//举例;精度损失的问题@Test
public void upcast2(){
int i = 123123123;
float f = i;
system.out.print1n(f);
}
}
//运行结果如下:
1.2312312E8

此时我们再看看long类型转换为double类型,是否也会有如此的问题?

public class classcastTest{
//举例;精度损失的问题@Test
public void upcast2(){
long l = 123123123123L;
double d = l;
ystem.out.print1n(d);
}
}
//运行结果如下:
1.2312312312312312E17

宽化类型转换实际上是可能发生精度丢失的,但是这种情况不会导致Java虚拟机抛出运行时异常

补充说明

================================

针对于从byte、char和short类型到int类型的宽化类型转换实际上是不存在的。

对于byte类型转为int 虚拟机没有做实质性的转化处理,只是简单地通过操作数栈交换了两个数据

而将byte转为long时,使用的是i21,可以看到在内部byte在这里已经等同于int类型处理,类似的还有short类型,这种处理方式有两个特点:

一方面可以减少实际的数据类型,如果为short和byte都准备一套指令,那么指令的数量就会大增,而虚拟机目前的设计上,只愿意使用一个字节表示指令,因此指令总数不能超过256个,为了节省指令资源,将short和byte当做int处理也在情理之中

另一方面由于局部变量表中的槽位固定为32位,无论是byte或者short存入局部变量表,都会占用32位空间。从这个角度说,也没有必要特意区分这几种数据类型。

三、类型转换指令的窄型转换

转换规则

================================

Java虚拟机也直接支持以下窄化类型转换:

  • 从int类型至byte、short或者char类型。对应的指令有: i2b、i2c、i2s
  • 从long类型到int类型。对应的指令有:l2i
  • 从float类型到int或者long类型。对应的指令有:f2i、f21
  • 从double类型到int、long或者float类型。对应的指令有: d2i、d2l、d2f

接下来我们针对于窄化类型转换的基本测试,请看以下示例代码

public class classcastTest{
///窄化类型转换基本的使用
public void downcast1(){
int i = 10;
byte b = (byte)i;
short s = (short)i;
char c = (char)i;
long 1 = 10L;
int i1 = (int)l;
byte b1 = (byte)l;
}
}

接下来我们编译该代码,看看方法的字节码是用什么指令进行类型转换的?
《JVM——(21)字节码指令集与解析三(类型转换指令)》

精度损失问题

================================

窄化类型转换可能会导致转换结果具备木同的正负号、不同的数量级,因此转换过程很可能会导致数值去失精度。

尽管数据类型窄化转换可能会发生上限溢出、下限溢出和精度丢失等情况,但是Java虚拟机规范中明确规雉数值类型的窄化转换指令永远不可能导致虚拟机抛出运行时异常

接下来我们针对于精度损失问题的基本测试,请看以下示例代码

public class classcastTest{
//窄化类型转换的精度损失@Test
public void downCast4(){
int i = 128;
byte b = (byte)i;
system.out.printin(b);
}
}
//运行结果如下:
-128

原因在于32位时的数据,转换数据时将高位砍掉只剩下byte的范围,就变成负数了
《JVM——(21)字节码指令集与解析三(类型转换指令)》

补充说明

================================

当将一个浮点值窄化转换为整数类型T(T限于int或long类型之一)的时候,将遵循以下转换规则:

  • 如果浮点值是NaN,那转换结果就是int或long类型的0
  • 如果浮点值不是无穷大的话,浮点值使用IEEE 754的向零舍入模式取整,获得整数值v

如果v在目标类型T(int或long)的表示范围之内那转换结果就是v。否则将根据v的符号转换为T所能表示的最大或者最小

当将一个double类型窄化转换为 float类型时,将遵循以下转换规则:

通过向最接近数舍入模式舍入一个可以使用float类型表示的数字。最后结果根据下面的规则判断:

  • 如果转换结果的绝对值太小而无法使用float来表示,将返回float类型的正负零。
  • 如果转换结果的绝对值太大而无法使用float来表示,将返回float类型的正负无穷大。
  • 对于double类型的NaN值将按规定转换为float类型的NaN值。

下面是本人的公众号:(有兴趣可以扫一下,文章会同步过去)
《JVM——(21)字节码指令集与解析三(类型转换指令)》

我是小白弟弟,一个在互联网行业的小白,立志成为一名架构师
https://blog.csdn.net/zhouhengzhe?t=1


推荐阅读
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
author-avatar
他w与他说
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有