《自己动手写Java虚拟机》学习笔记(八)数组和字符串

第八章 数组和字符串

8.1数组概述

如果数组元素是基本类型,就称之为基本类型数组,否则,如果数组元素是引用类型,就称之为引用类型数组。基本类型数组肯定都是一维数组,如果引用类型数组元素也是数组,那么它就是多维数组。

在jvm中,数组类和普通的类是不同的。首先,普通的类从class问价加载,但是数组类由jvm在运行时生成。数组类名是左方括号+数组的类型描述符;数组的类型描述符就是类名本身。比如int[]的类名就是[I,Object[]的类名就是[Ljava/lang/Obejct;

其次,创建数组的方式和创建普通对象的方式不同。普通对象由new指令创建,然后由构造函数初始化。基本类型数组由newarray指令创建;引用类型数组由anewarray指令创建;另外还有一个专门的multianewarray用于创建多维数组。

最后,数组和普通对象存放的数据也是不同的。普通对象中存放的是实例变量,通过putfiled和getfiled存取。数组对象中存放的则是数组元素,通过<t>aload和<t>astore系列指令按索引存取。另外有一个arraylength指令,用于获取数组长度。

8.2 数组实现

和普通对象一样,数组也是分配在堆中的,通过引用来使用。

创建数组对象时,如果类不是数组类,就终止程序;否则要根据数组类型创建数组对象

这时我们要修改类加载器,让他可以加载数组类。

8.3 数组相关指令

newarray用来创建基本类型数组。它需要两个操作数。第一个操作数是一个uint8整数,在字节码中紧跟在操作码后面,表示要创建那种类型的数组。java虚拟机规范称呼这个值为atype,并规定了其有效值,具体可见jvm规范。第二个操作数是count,从操作数栈中弹出,表示数组长度。如果这个count小于0,则抛异常。否则根据atype值使用当前类的类加载器加载数组类,然后创建数组对象并推入操作数栈。

anewarray用来创建引用数据类型。他也需要两个操作数。第一个操作数是uint16索引,来自字节码。通过这个索引可以从当前类的运行时常量池中找到一个类符号引用,解析这个类符号引用就可以得到数组元素的类。第二个操作数是数组长度,从操作数栈中弹出。

arraylength用来获取数组长度。他只需要一个操作数,即从操作数栈顶弹出数组引用。如果数组引用是null,抛异常。否则取数组长度推入操作数栈顶。

<t>aload系列。以aaload为例,从操作数栈弹出第一个操作数:数组索引,然后弹出第二个操作数:数组引用。如果数组引用时null抛异常。如果索引小于0,或者大于数组长度抛异常。如果一切正常,按索引取出数组元素,推入操作数栈顶。

<t>astore系列。以iastore为例,三个操作数:赋给数组元素的值、数组索引、数组引用。依次从操作数栈中弹出。检查与<taload>一样。如果一切正常,则按照索引给数组元素赋值。

multianewarray创建多维数组。第一个操作数是uint16索引,通过这个索引可以从运行时常量池中找到一个类符号引用,解析这个引用就可以得到多维数组类,注意是数组类!第二个操作数是unit8整数,表示数组维度。这两个操作数在字节码中紧跟在指令操作码后面。还需要从操作数栈中弹出n个整数,分别代表每一维度的数组长度。如果他们中任意一个小于0,都跑出异常。

修改instanceof和checkcast指令。注意:①数组可以强制转化成为Object类型(因为数组类的超类是Object)。②数组可以强制转化成为Cloneable和Serializable类型(因为实现了这两个接口)。③如果TC和SC是同一个基本类型,或者TC和SC都是引用类型且SC可以强制转化为TC,则[]SC数组可以强制类型转化为[]TC数组。

8.4 字符串

在class文件中,字符串是以MUTF8格式保存的。在JVM运行期间,字符串是以java.lang.String(后面简称String)对象形式存在的。而在String对象内部,又是以UTF16格式保存的。

String类有两个实例变量。其中一个是value,类型是字符数组,用于存放UTF16编码后的字符序列。另一个事hash,缓存计字符串的哈希码。

字符串对象是不可变的,一旦构造好了之后,就无法再改变其状态(这里指的是value字段)。

为了节约内存,JVM内部维护了一个字符串池。String类提供了intern()方法,可以把自己放入字符串池。

实现的时候用了一个hack的方式。如果java字符串已经在池中,直接返回即可。否则创建一个java字符串,把它的value值设置成传来的字符数组,最后把java字符串放入池中。

完善ldc指令。如果ldc视图从运行时常量池中加载字符串常量,则先通过常量拿到Go字符串,然后把它转化成为Java字符串实例并把引用推倒操作数栈顶。

8.5 Go语言语法

interface{}类型很想C语言void*,该类型变量可以容纳任何类型的值。

Go字符串是UTF8格式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值