概述
本文介绍字节码文件中Method的name_off字段指向的字符串的命名规则,该规则从方舟字节码文件版本12.0.4.0开始生效。
入口函数
模块加载时被执行的函数,名称固定为func_main_0。
非入口函数
其他函数在字节码文件中的名称结构如下:
#前缀#原函数名
下面的章节将会详细介绍前缀和原函数名。
前缀
前缀包含函数定义时所在的作用域信息。包含以下几个部分:
- 作用域标签
- 作用域名称
- 重名序号
前缀的结构为
<作用域标签1><作用域名称1>[<重名序号>]<作用域标签2><作用域名称2><[重名序号]>...<作用域标签n><作用域名称n>[<重名序号>]<作用域标签n+1>
其中<>仅为便于阅读的分割标识,并不包含在实际的前缀中,[]表示可以为空。仅当出现重名作用域时才需要[<重名序号>],即[<重名序号>]可以为空。最后一个作用域标签是本函数所对应的标签。
作用域标签
作用域标签表示作用域的类型。作用域和对应的作用域标签如下表所示,其他的作用域不会被记录进函数名中:
作用域 | 作用域标签 | 说明 |
---|---|---|
类 | ~ | class关键字定义的作用域 |
实例函数 | > | 类的实例成员函数定义的作用域 |
静态函数 | < | 类的静态成员函数定义的作用域 |
构造函数 | = | 类的构造函数定义的作用域 |
普通函数 | * | 除了以上类型的其它所有函数定义的作用域 |
namespace/module | & | namespace或module关键字定义的作用域 |
enum | % | enum关键字定义的作用域 |
作用域名称
源代码中定义作用域时所使用的名称。匿名则为空字符串。为了降低字节码体积,方舟编译器会对较长的作用域名称进行优化,此时作用域名称以@十六进制数字的形式体现。这个数字代表作用域名称的字符串在一个字符串数组中的索引:在字节码文件中源代码对应的Class中有一个名为ScopeNames的field, 这个field的值是指向一个LiteralArray的偏移,这个LiteralArray存储的是一个字符串数组。十六进制数字就是代表作用域名称在这个数组中的索引。原函数名不会转换为索引。
例子:
function longFuncName() { // longFuncName的函数名为"#*#longFuncName",其中"longFuncName"是原函数名,不会转换为索引。
function A() { } // A的函数名"#*@0*#A",其中"@0"表示在其对应LiteralArray中,索引为0的字符串,此时这个字符串是"longFuncName"。即这个函数原本的名称为"#*longFuncName*#A"
function B() { } // B的函数名"#*@0*#B"
}
重名序号
如果源码中相同作用域下出现了同名的实体,同名的名称后会加上重名序号,重名序号以^十六进制数字的形式表示。出现重名时,第一个不编号即重名序号为空,从第二个开始编号,编号从1开始。
例子:
namespace A {
function bar() { } // bar的函数名为"#&A*#bar"
}
namespace A {
function foo() { } // foo的函数名为"#&A^1*#foo",其中"^1" 为重名序号
}
原函数名
原函数名代表函数在源代码中的名字,匿名函数则为空字符串。同样地,如果源码中相同作用域下出现了同名的函数,重名的名称后面会加上重名序号,包括匿名函数。
function foo() {} // 原函数名为"foo"
() => { } // 原函数名为""
() => { } // 原函数名为"^1"
特殊情况
- 如果匿名函数定义时被赋值给了一个变量,那么原函数名是变量名。比如下面的例子:
let a = () => {} // 原函数名为"a"
- 如果匿名函数在对象字面量中定义并且被赋值给了一个字面量属性:
- 如果属性名不包含\,.,那么它的原函数名则是这个属性名。
let B = { b : () => {} // 原函数名为"b" }
- 如果属性名包含\,.,为防止二义性,其原函数名会按照匿名函数命名。
let a = { "a.b#c^2": () => {} // 原函数名为"" "x\\y#": () => {} // 原函数名为"^1" }
开发者应尽量避免使用除字母、数字、下划线以外的字符命名函数,以免出现二义性
示例
namespace A { // namespace在字节码中的函数名为"#&#A"
class B { // 构造函数在字节码中的函数名为"#&A~B=#B"
m() { // 函数m在字节码中的函数名为"#&A~B>#m"
return () => {} // 匿名函数在字节码中的函数名为"#&A~B>m*#"
}
static s() {} // 静态函数s在字节码中的函数名为"#&A~B<#s"
}
enum E { // enum在字节码中的函数名为"#&A%#E"
}
}
namespace LongNamespaceName { // namespace在字节码中的函数名为"#&#LongNamespaceName"
class LongClassName { // 构造函数在字节码中的函数名为"#&@1~@0=#LongClassName"
longFunctionName() { // 实例函数在字节码中的函数名为"#&@1~@0>#longFunctionName"
}
longFunctionName() { // 函数在字节码中的函数名为"#&@1~@0>#longFunctionName^1"
function inSecondFunction() {} // 函数在字节码中的函数名为"#&@1~@0>@2^1*#inSecondFunction"
}
}
}
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
点击领取→【纯血版鸿蒙全套最新学习资料】(安全链接,放心点击)希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取~限时开源!!
鸿蒙(HarmonyOS NEXT)最新学习路线
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、(南向驱动、嵌入式等)鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
HarmonyOS Next 最新全套视频教程
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
大厂面试必问面试题
鸿蒙南向开发技术
鸿蒙APP开发必备
请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,才能在这个变革的时代中立于不败之地。