文档管理中心
指南鸿蒙编程语言白皮书鸿蒙编程语言适用场景

鸿蒙编程语言适用场景

ArkTS 是动态类型编程语言,主打易学易用、生态丰富、极简开发、持续创新四大特征;仓颉是静态类型编程语言,主打高性能、强安全、跨平台、智能化等特性。C/C++可通过跨语言互操作封装为ArkTS、仓颉扩展模块,提供给ArkTS、仓颉高效使用。ArkTS、仓颉和C/C++支持高性能互操作,形成优势互补。三者相辅相成,并与其他编程语言协同,共同支撑开发者鸿蒙生态应用开发。

结合当前鸿蒙应用开发者遇到的主要问题及场景,我们锚定高效开发、高性能、安全、跨平台、技术资产保护、AI辅助开发、智能化七大核心场景,以鸿蒙分布式操作系统的技术特性为基底,构建覆盖「开发-运行-安全-生态-沉淀」的全链路生产力闭环。这一选择既源于鸿蒙「万物互联」的战略定位,也直击传统开发模式中效率瓶颈、性能损耗、安全风险、多端割裂及历史资产投入浪费的核心痛点。

1 高效开发

1.1 ArkTS高效开发能力概述

  • 兼容TS高效语法:极简语法,ArkTS保留TS基本语法风格,兼容TS高效语法,显著提升代码的简洁性和健壮性,方便开发者根据场景灵活使用。
  • 基于TS的高效语法进一步增强效率
    • 扩展高频基础库,ArkTS基础类库提供了XML生成解析转换、二进制Buffer、多种容器类库、URL字符串解析和高精度浮点计算等能力,协助开发者简化开发工作,提升开发效率。
    • 扩展并发能力,针对TS/JS并发能力支持有限的问题,ArkTS对并发编程API和能力进行了增强,提供了TaskPool和Worker两种并发API供开发者选择。另外,ArkTS进一步提出了Sendable的概念来支持对象在并发实例间的引用传递,提升ArkTS对象在并发实例间的通信性能。
  • 支持声明式UI开发,ArkTS提供了声明式UI范式、状态管理支持等相应的语言基础能力,让开发者可以以更简洁、更自然的方式开发应用。
  • 继承TS/JS语言生态,ArkTS支持与标准TS/JS的高效互操作。开发者可以选择使用标准JS/TS进行代码复用或开发,更方便兼容现有生态。

适用场景

  1. 兼容TS高效语法示例

    ArkTS保留了TS大部分语法特性,兼容TS高效语法,提供了许多高效且简洁的语法特性,可以显著提升代码的可读性和开发效率。例如泛型、箭头函数、展开运算符等

    收起
    自动换行
    深色代码主题
    复制
    1. // 使用泛型编写可复用的代码
    2. function identity<T>(arg: T): T {
    3. return arg
    4. }
    5. const output = identity<string>('hello') // 类型推断为 string
    6. // 使用箭头函数,简化函数调用
    7. const add = (a: number, b: number) => a + b
    8. // 使用展开运算符,高效合并数组
    9. const arr1 = [1, 2]
    10. const arr2 = [...arr1, 3] // [1, 2, 3]

    全量ArkTS语法列表,参考ArkTS语言介绍

  2. ArkTS拓展高频基础库示例

    以线性容器为例,ArkTS提供以下常用的数据结构,充分考虑了数据访问的速度,实现便捷的操作。

    收起
    自动换行
    深色代码主题
    复制
    1. import { ArrayList } from '@kit.ArkTS' // 导入ArrayList模块
    2. let arrayList: ArrayList<string> = new ArrayList()
    3. arrayList.add('a') // 增加一个值为'a'的元素
    4. arrayList[0] = 'one' // 修改索引为0的元素
    5. console.info(`result: ${arrayList[0]}`) // 输出:result: one

    全量ArkTS基础库列表,参考ArkTS基础类库

  3. ArkTS拓展并发能力示例

    详见ArkTS高性能能力概述章节。

  4. 支持声明式UI开发示例

    ArkTS提供了声明式UI范式、状态管理支持等相应的语言基础能力,帮助开发者提升鸿蒙应用界面开发效率。

    收起
    自动换行
    深色代码主题
    复制
    1. // index.ets
    2. @Entry
    3. @Component
    4. struct Index {
    5. @State message: string = 'Hello World'
    6. build() {
    7. Row() {
    8. Column() {
    9. Text(this.message)
    10. .fontSize(50)
    11. .fontWeight(FontWeight.Bold)
    12. }
    13. .width('100%')
    14. }
    15. .height('100%')
    16. }
    17. }

    有关对ArkUI的支持,详情请参见ArkUI-声明式UI开发框架

  5. 继承TS/JS语言生态示例

    标准TS/JS三方库可以直接被ArkTS引用,供鸿蒙应用调用。当前OpenHarmony三方库中心仓已提供1000+TS/JS三方库,供开发者复用已有TS/JS资产。ArkTS引用TS/JS示例如下:

    收起
    自动换行
    深色代码主题
    复制
    1. // lib.ts
    2. export class Test {
    3. greetings(msg: string) {
    4. console.log(msg)
    5. }
    6. }
    7. // app.ets
    8. import { Test } from 'lib' // 和TS/JS语法一致,通过import关键字导入TS/JS中实体
    9. let t: Test = new Test() // 和TS/JS语法一致,通过new关键字创建类的实例
    10. t.greetings('hello world') // 和TS/JS语法一致,通过.访问类的实例方法

    全量三方库列表,参考OpenHarmony三方库中心仓

1.2 仓颉高效开发能力概述

  • 静态类型系统:仓颉是静态类型语言,程序中变量和表达式的类型均在编译期确定,并不会在运行期发生改变。静态类型系统能够在编译期发现程序中的错误,减少后期问题调试定位时间。
  • 简明语法:仓颉吸收了静态类型应用开发语言的优秀设计理念和语法特征,因此这些语言的开发者学习仓颉成本较低;同时,仓颉支持类型推断和丰富的语法糖,使编程简洁高效。此外,仓颉还提供元编程能力,允许开发者针对特定业务快速设计领域特定语言(DSL),进一步提升了仓颉的易用性。
  • 多范式支持:仓颉是一个典型的多范式编程语言,对过程式、面向对象和函数式编程都提供了良好的支持。开发者可以灵活选择或混合使用不同的编程范式,来满足不同开发场景的需求。
  • 丰富的标准库:仓颉提供了丰富、通用、性能卓越的标准库,包括集合类库、IO 库、数据库、网络库、安全库、OS 库、数学库、数据结构、排序算法、控制台读取写、正则表达式、time 库、命令行处理库、fs 库、sync 库等,助力开发者快速构建鸿蒙应用。
  • 快速成长的生态:仓颉已基于开源社区构建200个三方库,基本覆盖Top5000应用所需的高频三方库范围。同时仓颉针对鸿蒙应用开发的痛点场景,针对性优化了多个三方库,如MarkDown、protobuf、pako、bigint、lottie、formula-ffi、editor4cj等,这些库在功能和性能上都有较好的表现。

关于上述特性的详细介绍,请参见仓颉编程语言开发指南

适用场景

  1. 领域框架开发场景
    • 场景描述:开发者开发领域专用框架,作为中间件供更上层开发者使用。框架开发者期望能结合特定领域特征提供贴近业务语义的API,降低使用者的开发门槛。
    • 场景问题和诉求
      • 不同领域面对的问题可能千差万别,例如:
        • UI框架需要提供声明式UI能力,以描述组件层次结构,组件属性配置,UI状态绑定等;
        • 数据库框架需要表达查询条件和数据映射;
        • 响应式框架需要表达发布/订阅关系,数据操作流式编排及组合关系等;
        • 测试框架需要描述测试步骤和断言;
      • 框架开发者希望使用一门语言同时满足这些诉求:
        • 为特定领域设计贴近业务语义的API;
        • 封装底层复杂性,向使用者暴露简洁接口,避免使用者编写样板代码,专注业务;
        • 支持声明式/流式/链式等多种编程风格;
    • 解决方案:仓颉语言提供以下语言特性用于满足面向特定领域编程需求,同时下图中以UI DSL为例,介绍各个特性的基本用途:
      • 仓颉宏:提供元编程能力,以代码作为其输入,在编译期对代码进行分析、变换以及生成,适用于引入全新语法,以及为原生语法注入领域行为的场景。
        • 示例中@Component和@State为预定义的、分别用于 UI 组件声明和状态管理的宏,它们在编译期自动展开生成相应的 UI 组件注册和状态管理的代码,简化了 UI 开发的复杂度。
      • 尾随 Lambda:当函数最后一个参数为函数类型时,作为入参的Lambda 可置于圆括号()外且可省略 =>,使Lambda中嵌套代码块如同语言原生控制结构,适合表达领域层次关系,提升可读性与流畅度。
        • 示例中基于尾随 Lambda 特性,实现以声明式的语法来描述组件间的分层关系,比如 Column 作为 Text 和 Button 的父组件,决定了子组件以列(column)的方式布局。
      • 命名参数和参数默认值:参数可通过 ! 标记为命名参数并赋予默认值,调用时以 name: value 形式传参且可省略,使接口像自描述的配置声明,降低调用者学习和记忆成本。
        • 示例中在设置 margin 时,参数采用命名参数和参数默认值,本场景只需要设置 top 和 bottom,未设置的参数采用默认值。
      • 类型扩展:通过 extend 可在不修改原有类型源码的情况下为现有类型追加方法、属性、运算符重载乃至接口实现,便于为既有类型注入领域行为。
        • 示例中预先为整数类型扩展出带有长度单位的表达能力,因此可以写为 100.percent 等价于“100%”,而 50.vp 等价于“50 vp”,其相比只用整数,提供了类型校验的保障,语法简洁且可读性高。
      • 省略关键字:仓颉构造对象无需 “new”、语句间无需分号、函数体最后一行表达式即自动作为返回值(可省略return),显著减少语法噪音,让代码更贴近领域行为表达。
        • 示例中Column、Text、Button等示例构造不需写“new”。
        收起
        自动换行
        深色代码主题
        复制
        1. // 注:以下为模拟业务场景代码片段,部分函数未给出具体实现,仅供示意参考
        2. @Component
        3. class CustomView {
        4. @State var count: Int64 = 0
        5. ...
        6. func build() {
        7. Column {
        8. Text("${count} times")
        9. .align( Center )
        10. .margin(top: 50.vp, bottom: 50.vp)
        11. Button("Click")
        12. .align( Center )
        13. .onClick { evt =>
        14. count++
        15. }
        16. }.width(100.percent)
        17. .height(100.percent)
        18. }
        19. ...
        20. }

  2. 异步耗时业务开发场景
    • 场景描述:在移动应用开发中,网络请求、文件读写、数据库查询等耗时场景下,这些操作通常需要几百毫秒到数秒不等,如果在主线程同步执行,会导致 UI 界面卡顿。通常的做法是结合异步并发能力,把任务放到非主线程上执行,待数据返回后再切回主线程更新 UI。
    • 场景问题和诉求:
      • 回调地狱:使用传统回调方式组织异步代码时,嵌套层级深、代码可读性差、错误处理分散;
      • 并发控制复杂度高:多个异步任务并发执行时,处理多任务协同,比如等待所有任务完成、处理部分任务失败、避免竞态条件等,带来开发复杂度;
      • 共享数据安全诉求:多线程并发访问共享数据结构时,手动加锁容易遗漏、死锁或导致性能低下;
    • 解决方案:仓颉语言提供强大并发编程能力降低并发编程的门槛,使开发者能够以直观的方式编写高效、安全的并发代码,简化了异步业务开发的复杂度。
      • spawn + Future<T>:以同步风格编写异步逻辑,避免嵌套回调带来的“回调地狱”问题;
      • 协作式取消:通过 Future.cancel() 和 hasPendingCancellation 实现安全的任务取消;
      • SyncCounter:便捷的线程协调工具,等待多个并发任务全部完成;
      • synchronized 块:自动加锁/解锁,避免手动管理锁导致的忘记解锁的问题;
      • 并发安全集合:ConcurrentHashMap、阻塞队列(ArrayBlockingQueue/LinkedBlockingQueue)、非阻塞队列(ConcurrentLinkedQueue)等,开发者无需手动加锁即可保证线程安全;

  3. AI交互富文本开发场景
  • 场景描述:随着大模型技术革新与大范围应用,大量应用集成了智能对话功能,AI智能体成为下一代流量入口,其中新的交互(富文本+UI)体验是核心 。
  • 场景问题和诉求
    • 流式解析与动态渲染:流式解析Markdown内容并实时渲染,避免全量加载导致加载速度缓慢、滚动卡顿、响应时间长等性能问题。
    • 复杂元素支持: 需覆盖代码块、LaTeX公式、表格等,满足不同客户群体专业诉求。
    • 内容可扩展:提供不同内容的扩展能力,常见包括幻灯片、动画、视频等;
    • 样式可定制:支持自定义UI卡片以及支持DSL动态渲染卡片能力。
  • 解决方案:富文本融合了文字、表格、链接、图片、视频、代码、公式等多种元素,其解析过程涉及大量逻辑运算,仓颉凭借其在性能和并发处理方面的优势,通过打造高性能的仓颉版富文本库,为用户带来更流畅、更优质的使用体验。
    • 功能规格完备,为AI量身定制
      • 流式处理,为AI量身定制:引入高效的增量渲染技术,避免全量重绘,实现 Markdown 内容的实时更新与局部刷新,显著提升渲染性能与响应速度,优化用户交互体验;
      • UI 模块化架构:支持自定义UI卡片以及支持DSL动态渲染卡片能力。 遵循模块化设计原则,将 UI 页面进行组件化拆分,并严格分离 Markdown 解析与渲染逻辑,便于后续功能扩展与迭代;
      • 灵活配置体系:构建可定制的 config 配置系统,支持用户自由设置 Markdown 各类元素的样式属性,包括但不限于标题、列表、链接等,可灵活调整颜色、字体大小、排版等视觉效果,满足多样化的展示需求;
      • Commonmark 解析与插件化扩展:基于 Commonmark 标准解析器对 Markdown 文本进行精准解析,同时设计插件化架构,允许开发者根据业务需求灵活扩展解析功能,实现对自定义语法或特殊格式的支持。
      • Prism 代码块高亮:集成 Prism 代码语法高亮库,自动识别代码语言类型,并进行语法高亮渲染,提升代码展示的可读性与专业性。
      • LaTeX 数学公式渲染:引入 LaTeX 解析能力,支持数学公式解析和渲染,无论是行内公式还是独立公式块,均可实现高质量的数学符号与公式排版,满足学术、科研等场景的专业需求。
      • 提供AVIF图片格式解析库,提供高性能的图片编解码能力;
    • 快速集成:提供仓颉和ArkTS接口,可无感集成到鸿蒙应用中;接口丰富,满足开发者各类场景;
    • 性能卓越:底层使用仓颉开发,解析渲染丝滑流畅,数据量大也能满足满帧状态;
  • 仓颉支持富文本开发涉及以下库:

2 高性能

2.1 ArkTS高性能能力概述

常见的 TS/JS 运行时通常仅支持源码级的运行时解析,并采用解释器或 JIT 的执行模式。而 ArkTS 编译运行时则提供了更为多样的执行能力:它支持将 ArkTS、TS、JS 源代码预编译为字节码文件,运行时可直接加载字节码;同时支持 AOT、解释器和 JIT 的混合执行模式。其中 AOT 编译能显著提升应用的启动性能,使应用在启动时即基于优化后的本地机器码运行。

在模块加载机制上,TS/JS 默认采用预加载方式,即在应用启动时加载所有模块。同时,TS/JS 支持动态加载来延迟模块加载时机,但实现路径依赖异步语义,要求整个调用链保持异步风格,开发成本较高。为解决该问题,ArkTS 运行时引入了 自动延迟加载(lazy import)机制:只需在 import 语句中添加 lazy 关键字,即可使模块在首次使用时按需加载,支持同步与异步调用场景,无需改动业务逻辑结构。

此外,TS/JS 运行时通常为单线程架构,并仅提供基于消息传递的 Worker API。开发者在处理并发任务时需显式封装命令消息及其处理逻辑,使用繁琐。而ArkTS提供了 TaskPool API,允许开发者以函数方式直接提交并发任务,运行时自动调度至线程池执行。TaskPool 支持线程池的负载均衡与弹性扩缩容,极大简化了并发编程模型。

针对多线程通信性能问题,TS/JS 的单线程设计导致跨线程传输对象需复制,尤其在处理复杂对象时可能造成明显卡顿。而 ArkTS 引入了 Sendable 类型,支持线程间以引用方式共享对象。Sendable 对象在线程传递过程中无需拷贝,具备与 Java 等支持共享内存模型的语言类似的高效并发特性。

混合执行模式

ArkTS编译运行时的执行引擎包含解释器、JIT编译器和AOT编译器,支持混合模式的执行,在应用性能与系统资源之间取得平衡。如下图所示:

执行模式原理

  • 解释器:直接运行前端编译器生成的字节码。启动速度快、内存占用低,但执行性能相对较低。
  • JIT 编译器:在运行过程中通过 Profiler(性能分析器)收集热点信息,对频繁执行的代码进行即时优化,生成高质量的本地机器码(如上图 Optimized Code II)。具备高运行性能,但启动阶段需要“预热”。
  • AOT 编译器:在应用运行前,基于静态分析(如类型信息与历史热点信息)生成高质量的目标机器码(如上图 Optimized Code I)。其优势在于启动快、运行快,但会增加安装包体积与内存占用。

解释执行模式可以满足应用开发者一次编译,编出来的App包支持在鸿蒙多种设备运行。ArkTS的优化编译(包括AOT闲时编译和JIT编译)能支持更高性能的运行,同时也会使用更多的内存空间。

启动性能优化——动态加载与懒加载

为了解决大型、复杂应用开发过程中,部分代码编译时被多次拷贝导致包体积增大、文件依赖、代码与资源共享困难以及单例和全局变量污染等问题,同时为了方便开发者代码编写与功能维护,ArkTS支持应用模块化编译打包运行。

模块加载方式

默认情况下,模块的加载是静态加载,即在应用启动时,所有模块都会被加载。这种方式在大型应用中会导致启动时间变长,影响用户体验。

应用开发的有些场景中,有些模块被使用的可能性很低,或者并不需要立即被使用。针对这些模块,ArkTS提供了两种优化启动性能的方法:动态加载延迟加载

  • 动态加载:使用一个异步函数来动态导入模块,返回一个Promise对象,实现模块的异步加载,减少了启动时的加载量,提高了启动性能。
  • 延迟加载:import 关键字后面加上 lazy,模块会在第一次被使用时自动同步加载。

动态加载与延迟加载的对比:

展开

加载方式

启动性能优化

代码侵入性

控制粒度

使用建议

动态加载

⭐⭐⭐⭐

⭐⭐⭐⭐

精细控制

适用于加载时机明确、功能较独立的模块。

延迟加载

⭐⭐⭐⭐

自动触发

适用于快速实现懒加载、依赖较少的模块。

SmartGC——感知场景的内存回收

ArkTS运行时选择最为常见的基于对象追踪(即Tracing GC)算法。GC的性能通常以暂停时间、内存使用和吞吐率来衡量,而在GC的算法中又不能对这三项做到面面俱到,一般的GC算法只能针对其中一项或者两项做倾向性优化。ArkTS运行时针对鸿蒙应用场景做了精细化的GC策略调整,在不同的场景采取不同的策略和算法达到场景最优化选择

  • 在用户敏感的场景:GC以用户体验优先,即专注于暂停时间的最小化。
  • 在后台运行的场景:GC以吞吐率和内存使用优先,尽量回收内存以使得前台应用可以使用更充足的内存。

  1. 敏感场景

    在应用性能敏感场景,通过将GC触发水线临时调整到线程堆较大值来避免触发GC,避免GC可能导致的应用卡顿。

    当前支持的敏感场景包括:应用冷启动、应用滑动、应用点击页面跳转、超长帧。

  2. 闲时GC

    用算法检测应用空闲场景,根据检测到的空闲等级触发不同类型的压缩GC,尽量回收空闲应用内存。闲时GC既可以减少系统整体内存负载,同时确保应用再次进入敏感场景时内存保持最佳,间接提升性能,减少GC导致的应用丢帧。

  3. ArkTS GC机制说明

    ArkTS 运行时基于对象追踪技术实现对象生命周期的自动管理,并针对不同应用场景进行了策略优化,从而更好地满足实际业务对性能的需求。

    在 ArkTS中,强引用(Strong Reference)是默认的引用类型,会阻止对象被垃圾回收(GC);而弱引用(Weak Reference)不会阻止 GC,当对象仅存弱引用时会被自动回收。

    • 强引用 (Strong Reference)

      定义:最常用的引用类型。只要对象被任意强引用指向,它就被视为 “可达”,GC 绝对不会回收。

    • 弱引用 (Weak Reference)

      定义:一种 “非占有式” 引用。它允许你访问对象,但不保护对象不被 GC 回收。

      核心作用:解决内存泄漏,尤其适用于缓存、元数据、DOM 节点关联等场景。

      JS 实现:

      • WeakMap / WeakSet (ES6)
        • WeakMap:键(必须是对象)为弱引用,值为任意类型。键被回收后,整条记录自动消失。
        • WeakSet:成员(必须是对象)为弱引用。
        • 限制:不可枚举(无 keys()/values())、无 size、键 / 成员仅限对象。
      • WeakRef (ES2021)
        • 直接创建对单个对象的弱引用。
        • 使用 .deref() 方法获取原对象(可能返回 undefined,需判空)。
    • 强引用 vs 弱引用:核心区别
    展开

    特性

    强引用 (Strong)

    弱引用 (Weak)

    GC 影响

    阻止回收

    不阻止回收

    实现

    变量、对象、Map、Set

    WeakMap、WeakSet、WeakRef

    键 / 成员类型

    任意 (包括原始值)

    仅限对象 (不能是 string/number)

    可枚举

    ✅是 (可遍历)

    ❌否 (不可遍历)

    内存风险

    易泄漏 (循环引用)

    自动清理 (防泄漏)

    使用场景

    常驻数据、业务对象

    缓存、元数据、DOM 关联、临时映射

  4. 总结与最佳实践
    • 强引用:用于核心业务对象,确保数据稳定存在。
    • 弱引用:用于辅助、临时、关联数据。当主对象消失时,附属数据应随之销毁,自动释放内存。
    • WeakMap > WeakRef日常开发优先使用 WeakMap/WeakSet,更安全;WeakRef 需谨慎处理 deref() 空值,且不建议滥用。

ArkTS的并发能力

ArkTS提供的TaskPool和Worker均支持多线程并发能力。TaskPool的工作线程会绑定系统的调度优先级,并支持负载均衡(自动扩缩容)。相比之下,Worker需要开发者自行创建,不支持设置调度优先级。因此,性能方面TaskPool优于Worker,推荐在大多数场景中使用TaskPool。

在ArkTS并发模型中,普通对象所属的内存是隔离的,不会出现线程竞争同一内存资源的情况,开发者无需处理内存上锁相关的问题,提高开发效率。对普通对象的线程间通信,ArkTS采用了标准的Structured Clone算法(序列化和反序列化),此时需要进行深拷贝,性能开销可能较大。对此,ArkTS还提供了Sendable对象的共享能力来优化线程间通信开销。

  1. TaskPool

    TaskPool为应用程序提供多线程环境,降低资源消耗、提高系统性能,无需管理线程生命周期。其运作机制示意图如下:

    TaskPool支持开发者在宿主线程提交任务到任务队列,系统选择合适的工作线程执行任务,再将结果返回给宿主线程。接口易用,支持任务执行、取消和指定优先级,同时通过系统统一线程管理,结合动态调度及负载均衡算法,可以节约系统资源。系统默认启动一个任务工作线程,任务多时会扩容。工作线程数量上限取决于设备的物理核数,内部管理具体数量,确保调度和执行效率最优。长时间无任务分发时会缩容,减少工作线程数量。

  2. Worker

    Worker的主要作用是为应用程序提供一个多线程的运行环境,满足应用程序在执行过程中与宿主线程分离,在后台线程中运行脚本进行耗时操作,避免计算密集型或高延迟的任务阻塞宿主线程。

    每个Worker子线程和宿主线程拥有独立的实例,包含基础设施、对象、代码段等。因此,启动每个Worker存在一定的内存开销,需要限制Worker子线程的数量。Worker子线程和宿主线程通过消息传递机制通信,利用序列化反序列化机制完成参数对象的重建(注:Sendable对象直接引用共享)。

  3. Sendable

    ArkTS提供了Sendable对象类型,在并发通信时支持通过引用传递来解决并发通信开销大的问题。Sendable对象为可共享的,其跨线程前后指向同一个ArkTS对象。如果底层是Native实现,还需要考虑线程安全性。通信过程如下图所示:

    当多个并发实例尝试同时更新Sendable数据时,会发生数据竞争,例如ArkTS共享容器的多线程操作。因此,ArkTS提供异步锁机制来避免不同并发实例间的数据竞争,并提供了异步等待机制来控制多线程处理数据的时序。同时,还可以通过对象冻结接口将对象冻结为只读,从而避免数据竞争问题。Sendable对象提供了并发实例间高效的通信能力,即引用传递,适用于开发者自定义大对象需要线程间通信的场景,例如子线程读取数据库数据并返回给宿主线程。

    总结与选型建议

    展开

    并发能力

    适用场景

    性能优化建议

    生命周期管理

    推荐级别

    TaskPool

    任务型并发

    ⭐⭐⭐⭐

    自动

    ✅ 推荐

    Worker

    交互式后台服务,定时器等

    ⭐⭐⭐

    手动

    ⚠️ 特殊场景使用

    Sendable

    大对象跨线程传输

    ⭐⭐⭐⭐

    自动(GC回收)

    ✅ 大对象场景推荐

2.2 仓颉高性能能力概述

仓颉具有静态类型系统,且其源码被静态编译为直接执行的机器指令。这种静态编译执行方式具有更高的启动性能和安全性。借助仓颉编译器强大的静态分析能力,低效或有风险的代码在应用构建过程中识别,开发工具自动帮助或提示开发者优化代码,达成最佳应用体验。

静态类型和静态编译优化

仓颉编译器具有多层级优化能力,通过前端-后端-运行时融合的垂直分析优化技术,仓颉在计算机语言基准测试Benchmarks Game上展现了优越的基础性能

仓颉的静态编译先进技术包括:

  • 语言相关的high-level编译前端:前端检查仓颉源码的规范性和安全性,对其开展high-level语言相关优化(面向对象优化、去虚化、内联等),然后编译为低层级中间表示文件输出。
  • 多重优化Pass的编译后端:基于前端输出的低层级中间表示文件开展深入的静态分析和优化(逃逸分析、常量传播、内联、循环展开、循环不变量外提、向量化等),生成高效的可执行机器指令。
  • 仓颉对象在编译时具有确定类型,其对象布局在编译时确定,所以成员数据的访问语句在编译时能生成简洁高效的内存访问指令。
  • 仓颉的虚函数调用、接口函数调用通过仓颉编译器的去虚化技术可以转化为直接调用,显著减少调用开销;对于具有运行时多态的接口函数调用,仓颉编译器和运行时通过inline cache大幅提升其调用性能。
  • 仓颉值类型提供了更紧凑的数据排布和访问方式,值类型变量减少了间接寻址和cache miss,具有更好的空间局部性. SROA(Scalar Replacement of Aggregates)优化对值类型更友好。通过SROA,值类型变量的数据可被直接映射到物理寄存器,避免了内存访问操作。

仓颉语言用包组织源码,支持应用功能以包为粒度按需加载。

低时延高效率的自动内存管理

  1. 极低时延

    时延敏感性是鸿蒙移动应用的关键特征之一。造成应用时延高的因素有很多,从编程语言角度看,GC暂停耗时是关键因素之一。与现有的STW GC或近似并发GC(如下图)不同,仓颉的并发GC采用轻量同步机制,具有更短的GC暂停耗时,仓颉应用线程完成GC同步的平均耗时小于2毫秒,典型情况下完成一次GC同步的耗时在百微秒量级。仓颉并发GC可以帮助应用大幅减少GC暂停导致的丢帧,是时延敏感场景的优选编程语言,如:

    • 长列表、复杂页面快速滑动
    • 点击响应要求高的页面
    • 长列表、长图快速滑动
    • 视频直播

  2. 精简对象布局

    仓颉对象采用了精简的内存布局。对象内存中仅保留一个8字节的头记录其类型信息,其余数据都是有效内容,用仓颉语言开发的应用在运行时占用更少的内存。

  3. 优化内存峰值

    仓颉GC采用了内存整理(compact)技术,通过把存活对象搬移到指定的一块连续内存中,全部回收堆内存中的死亡对象及其中的内存碎片,减少了堆内存用量。仓颉GC采用的内存整理技术可实现内存块一边整理一边释放,降低GC过程中的内存峰值(如下图)。

  4. 紧凑的值类型

    仓颉的值类型也可以用于优化堆内存。值类型数据作为局部变量时占用的内存直接分配在函数栈空间里,在函数退出时随之释放。相比堆对象,值类型变量具有更高的内存分配和回收效率,内存回收更及时。通过在应用代码中合理地使用值类型,可以减少堆内存用量,降低GC负载。

    仓颉编译器也能通过逃逸分析识别出函数内的局部对象,像对待值类型变量一样把它分配在栈空间,开发者不需改动源码即可与手动改为值类型具有等同的内存优化效果。

    综上,仓颉自动内存管理技术具有时间空间多维度优势,是时延敏感场景和内存敏感场景(如内存受限的中低端设备)的优选编程语言。

简洁轻量的并发编程

仓颉采用数据共享的多线程模型,提供了轻量用户态线程和高效易用的无锁并发数据结构让并发编程变得轻松,将高效并发处理的能力直接置于开发者的手中。

在仓颉提供的轻量化线程模型中,开发者可以通过简单的 spawn 语法创建仓颉线程。与业界一些其他语言的使用 async/await 语法的并发模型不同,使用仓颉的轻量化线程模型,开发者无需在编程过程中手动标记(如用 async 标记异步函数并用 await 标记其调用点),也彻底杜绝了这些标记的“传染性”(包含 await 的函数必须标记为 async)导致的“函数染色”问题,大大降低了并发编程的复杂性。

在运行层面,仓颉线程是用户态线程,与传统的操作系统线程相比,其实现完全在用户空间进行,不依赖操作系统的线程管理,这从根本上减少了线程创建和销毁的开销,在性能上具有明显优势。在线程调度上,仓颉使用了 M:N 线程模型,即 M 个仓颉线程在 N 个 native 线程(通常即为操作系统线程)上调度执行,其中 M 和 N 不一定相等。每个仓颉线程都受到底层 native 线程的调度执行,并且多个仓颉线程可以由一个 native 线程执行。每个 native 线程会不断地选择一个就绪的仓颉线程完成执行。仓颉线程的调度支持抢占,如果仓颉线程在执行过程中发生阻塞(例如等待互斥锁的释放),那么 native 线程会将当前的仓颉线程挂起,并继续选择下一个就绪的仓颉线程。发生阻塞的仓颉线程在重新就绪后会继续被 native 线程调度执行。

对于仓颉线程间的数据共享和同步,仓颉也提供了一系列简洁易用的机制来确保线程安全,主要包括:

  • 原子操作:不可分割的操作序列,其执行过程要么完全完成,要么完全不执行,不会因线程调度或中断导致中间状态
  • 互斥锁和 synchronized 机制:对临界区加以保护,使得任意时刻最多只有一个线程能够执行临界区的代码
  • 条件变量:协调仓颉线程间的同步,允许仓颉线程在条件不满足时主动挂起,并在条件满足后被唤醒
  • 线程局部变量:每一个仓颉线程都有它独立的一个存储空间来保存这些线程局部变量,每个仓颉线程可以安全地访问他们各自的线程局部变量,而不受其他仓颉线程的影响

    更进一步,仓颉提供了基于细粒度并发算法实现的无锁并发对象,而用户通过调用并发对象的接口来操作多线程共享内存,从而实现:

  • 无锁编程体验:用户通过接口调用实现高效的共享内存并发访问。
  • 并发安全保障:仓颉并发对象的接口可保证无数据竞争,核心接口具有并发原子性。
  • 提升性能:仓颉并发对象的设计使用细粒度并发算法。
  • 保证并发原子性:仓颉并发对象的核心方法具有并发“原子性”,即从用户视角来看,该方法调用执行不会被其它线程打断。

关于并发模型相关特性的更详细介绍,请参见仓颉编程语言开发指南

适用场景

  1. UI 界面刷新场景
    • 场景描述:UI数据源发生变化,需要对新的数据源进行解析并刷新UI,如滑动长页面或者长列表,地图实时更新等场景。
    • 场景问题和诉求:当UI数据源发生变更时,如果新数据等计算耗时任务在UI线程执行,会阻塞UI线程刷新UI并导致卡顿、丢帧等问题。
    • 解决方案:仓颉提供了基于轻量线程的并发能力,以及线程间的内存共享能力。利用轻量线程并发能力,使主线程专注于UI渲染等任务,将数据处理、网络通信、数据传输等操作分发到仓颉轻量线程,实现并行化加速。同时通过数据缓存技术,减少I/O频率。下面是一个使用仓颉实现并发发送网络请求并将获取的图片数据解析成用于展示的 PixelMap的案例。
      • 在自定义组件(用于展示网络下载图片)的 aboutToApper 生命周期方法中发起网络请求获取图片数据;
      • 图片的下载路径保存在数组 picsUrl 中,数组中每个元素是一张图片的下载路径;
      • 因为每张图片的下载是一个独立的任务,因此每张图片的下载和解析都可以通过仓颉 spawn 表达式创建一个子线程任务去完成;
      • 如果一张图片已经存在本地缓存,那么直接从本地读取图片数据并更新 UI,否则从网络下载数据,解析成 PixelMap 实例后做 UI 更新。
    收起
    自动换行
    深色代码主题
    复制
    1. let picsUrl: Array<String> = ... // 每张图片的 url
    2. @Entry
    3. @Component
    4. class PicsViewDiskCache {
    5. @State
    6. var pixelMaps: ObservedArray<?PixelMap> =
    7. ObservedArray<?PixelMap>(Array<?PixelMap>(picsUrl.size, item: None))
    8. protected func aboutToAppear() {
    9. let client = getClient(poolSize: 20) // 创建网络请求客户端
    10. for (i in 0..picsUrl.size) {
    11. let filePath = Path(getFilePath(i))
    12. if (exists(filePath)) {
    13. // 已经做了文件缓存,直接从文件读
    14. let data = File.readFrom(filePath)
    15. // 将data转换成PixelMap
    16. let pixelMap = getPixelMapFromData(data)
    17. // 更新UI
    18. UpdateUI(pixelMap)
    19. return
    20. }
    21. let request = HttpRequestBuilder().url(picsUrl[i]).get().build()
    22. // 1. 下载图片:发送网络请求,请求图片数据
    23. let response = client.send(request)
    24. // 2. 解析:读取网络数据
    25. let data: Array<Byte> = getNetWorkData(response)
    26. // 3. 创建:根据网络图片数据创建 pixelMap 对象
    27. let pixelMap = getPixelMapFromData(data)
    28. // 4. UI 渲染:网络图片数据获取解析完毕,回主线程刷新 UI
    29. UpdateUI(pixelMap)
    30. // 5. 缓存到本地文件
    31. writeToFile(filePath, data)
    32. }
    33. }
    34. func build() {
    35. Column(10) {
    36. ForEach(pixelMaps,
    37. itemGeneratorFunc: { item: ?PixelMap, index: Int64 =>
    38. if (let Some(item) <- item) {
    39. Image(item).width(160).height(160)
    40. } else {
    41. // 如果 PixelMap 数据还未获取完成,先用占位图
    42. }
    43. },
    44. keyGeneratorFunc: {
    45. item: ?PixelMap, index: Int64 =>
    46. // 配置 item 的 key 值
    47. })
    48. }.width(100.percent)
    49. }
    50. }

  2. 应用冷启动场景
    • 场景描述: 开发者对应用启动时间有要求,期望优化应用启动时间。
    • 场景问题和诉求:应用包中的代码产物大小和数量是导致应用冷启动时间劣化的最大因素,编译产物大、数量多意味着应用在启动阶段需要加载更多数据,导致冷启动时间增加,此时需要合理地优化加载项。
    • 解决方案:仓颉编译器通过函数内联、冗余代码消除等编译优化能力,最大程度降低代码产物大小;同时提供应用级别的LTO(Link-time Optimization)能力,可以将应用内的多个编译产物合并,从而实现应用冷启动优化。

  3. 频繁与native层交互场景
    • 场景描述:使用一些跨平台框架,如ReactNative、小程序框架开发时,常常依赖系统native实现的模块以提升性能或者调用系统能力。
    • 场景问题和诉求:开发者要求程序能够低开销地兼容native层编程语言。
    • 解决方案:仓颉本身提供了与C语言高效的互操作能力,在仓颉侧使用 @C 和 foreign 标注的结构体和函数,其实现与 C 在二进制层面保持兼容,提供 inout 关键字,可将仓颉栈上的变量引用传递到 C 侧,减少跨语言拷贝,同时对于非阻塞性并且不会调用仓颉方法的C函数,还提供了@FastNative注解来消减跨语言调用时的运行时开销,实现低开销互操作。详细内容可参考仓颉与C/C++互操作章节。下面是一个利用仓颉来增强小程序性能的案例。

      小程序架构上重点涉及到两个模块。在JsBridge中加入仓颉api的派发逻辑,和在JSAPI中加入仓颉实现,仓颉具备高效的与C语言互操作的能力。C语言与仓颉代码互相调用只需要声明和使用,代码简单,执行快,不需要调用Napi协议接口,仓颉具备线程池能力。仓颉语言的JSAPI执行不占用主线程时间。仓颉线程间具备天然的内存共享能力,省去序列化和反序列化开销。这个架构可以让主线程聚焦处理Web渲染任务,而大量的系统请求通过仓颉的并发线程处理。

3 安全

3.1 ArkTS安全能力概述

ArkTS 不仅在语言层面引入了类型系统、空值安全等特性,在编译工具链和运行时的设计上也提供了额外的安全机制。其目标是在保障开发者效率的同时,降低运行时攻击面,提升系统整体可信度。

应用字节码文件的合法性校验

为了防止恶意篡改应用字节码并上传至应用市场,鸿蒙应用市场在上架审核阶段引入字节码合法性校验机制,具体包括:

  • 检查所有字节码文件是否符合 ArkTS 字节码规范。
  • 规避字节码级别的运行时崩溃或被利用行为。

    该机制削减了从分发渠道源头控制恶意应用流入用户终端的风险。

代码签名与运行时验签

ArkTS 对所有上架应用进行代码签名,并在运行时加载字节码前执行签名校验:

  • 签名机制:在打包阶段对应用内容进行数字签名,包含字节码文件。
  • 运行时校验:ArkTS 运行时在执行字节码前验证签名完整性。
  • 篡改防护:一旦检测到签名异常或字节码被篡改,应用将无法执行。

    这一机制防止了上线后应用注入代码或篡改行为。

3.2 仓颉安全能力概述

仓颉是静态类型语言,程序中所有变量和表达式的类型都是在编译期确定的,并且禁止隐式类型转换,即在程序运行过程中不会发生改变,能够在编译期尽量早的发现程序中的错误,提升程序安全性。

仓颉在编译和运行时支持多种安全检测,如数组越界、除0、整型溢出、移位检查等。以数组越界检查为例,支持编译时和运行时安全检查。

仓颉采用 tracing GC 技术,通过在运行时跟踪对象之间的引用关系,来识别活动对象和垃圾对象。垃圾收集(GC)是一种自动内存管理机制,它能够自动识别和回收不再需要使用的对象,将开发者从手工释放内存中解放出来,不仅可以提高开发效率,还能有效避免各种常见内存错误,提升程序的安全性。

仓颉支持运行时地址随机化、堆栈不可执行、控制流完整性等漏洞利用缓解机制,能有效避免运行时漏洞利用,让攻击者难以利用漏洞控制应用执行流并窃取、篡改应用客户数据。

适用场景

涉及金融交易对业务逻辑有安全要求的场景

  • 场景描述:在开发电商类、虚拟货币交易类、系统应用类等应用时,由于涉及金钱交易,或应用权限较高时,如果代码逻辑存在因内存管理不当,或数据大小校验不当造成堆栈内存溢出、整型溢出等安全漏洞,进而被攻击者利用,最终攻击客户端并伪造交易请求,或获取系统应用权限造成更大损失。
  • 场景问题和诉求:开发者需要应用代码尽可能消除内存类、整形溢出类等安全问题,并保护应用不被攻击。
  • 解决方案:
    • 使用仓颉语言编写代码进行数据计算时,由于仓颉语言进行整型计算保护,可保证程序不会产生整型溢出等安全漏洞。
      收起
      自动换行
      深色代码主题
      复制
      1. func safeAdd(a: Int8, b: Int8): Int8 {
      2. a + b
      3. }
      4. main(): Int64 {
      5. let a: Int8 = 120
      6. let b: Int8 = 20
      7. try {
      8. let result = safeAdd(a, b)
      9. println("result = ${result}")
      10. } catch (e: OverflowException) {
      11. println("捕获到整型溢出: ${e}")
      12. println("说明仓颉没有发生静默回绕,而是抛出了异常。")
      13. }
      14. 0
      15. }
    • 仓颉语言使用运行时管理内存,无需开发者手动进行内存申请、释放,可保证不会产生内存类漏洞,如堆栈内存溢出、use-after-free、double-free等漏洞
      收起
      自动换行
      深色代码主题
      复制
      1. class Person {
      2. let name: String
      3. var age: Int64
      4. init(name: String, age: Int64) {
      5. this.name = name
      6. this.age = age
      7. }
      8. func sayHello() {
      9. println("你好,我是 {name}, 今年 {age} 岁。")
      10. }
      11. }
      12. func makePerson(name: String, age: Int64): Person {
      13. Person(name, age)
      14. }
      15. main(): Int64 {
      16. let p1 = Person("张三", 20)
      17. p1.sayHello()
      18. let p2 = makePerson("李四", 25)
      19. p2.sayHello()
      20. println("程序结束时,对象内存由仓颉自动管理,无需手动释放。")
      21. 0
      22. }

4 跨平台

4.1 ArkTS跨平台能力概述

ArkTS 依托平台无关的方舟字节码分发格式、适配多开发平台(鸿蒙、Windows、Linux、MacOS)的编译及调试调优工具链,以及支持在主流操作系统(鸿蒙、Android、iOS、Windows、Linux、MacOS)上运行的语言运行时,实现了 ArkTS 代码在不同开发平台的编译、分发,以及在多个主流运行系统上的跨平台运行。

在后续演进规划中,ArkTS 将通过多后端机制对接不同运行平台或系统原生开发语言的运行环境,旨在使 ArkTS 代码在各平台上的开发与运行体验达到最优,实现与平台原生语言代码的高效交互及平台 API 的无损调用。

4.2 仓颉跨平台能力概述

仓颉语言将跨平台能力作为语言、编译器、运行时和工具链协同设计目标之一,在保证开发体验、运行效率和工程可维护性的前提下,为开发者提供统一而可扩展的跨平台方案。仓颉提供三方面跨平台能力:跨平台编译、跨平台生态复用以及跨平台调试。

仓颉编译器面向主流平台提供编译与交叉编译能力,当前能力覆盖鸿蒙、Android、iOS、MacOS、Windows、Linux 等目标场景。仓颉提供条件编译宏和 common/specific 代码组织机制,支持开发最大限度的共享代码。

  1. 多平台编译运行能力:仓颉工具链多平台构建和调试工具链,交叉编译结果可在多移动平台运行如下图。

  2. 平台条件编译能力:仓颉分别提供条件编译宏和 common/specific 组织模式,为开发者提供函数级和文件级的跨平台支持。
    • 条件编译宏:仓颉支持编译标记 @When[...] 对导入和声明进行条件编译。该机制基于 os、arch、env、backend等内置条件变量,对不同平台选择不同分支。开发者可以在同一份源码中用代码显式区分平台差异,编译时自动生成对应平台的产物。
    • common/specific:仓颉提供了 common 和 specific 两类声明来组织跨平台代码。common定义共享声明及公共实现,承载平台无关的业务逻辑、领域模型和抽象接口;specific定义面向具体平台的实现,承载系统 API、设备能力和平台框架接入。详细使用说明见仓颉编程语言开发指南

  3. 跨平台调试能力

    仓颉提供了统一的多端调试工具cjdb,以统一的方式支撑多平台程序的调试工作。cjdb 基于 lldb 演进而来,面向仓颉程序提供源码级调试能力。cjdb 功能覆盖断点、代码执行控制、信息查看、内存操作等调试场景。并在单步、协程调试上进行了调试体验改进。

适用场景

  1. 跨平台工具库场景
    • 场景描述:不同平台有各自的系统工具库(如日志)。当业务代码需要跨鸿蒙、Android、iOS三端运行时,开发者期望能够以文件为单位组织代码,隔离各平台实现逻辑:各平台共享同一套接口契约,底层实现则充分释放平台特性。不同平台的代码彼此解耦,通过条件编译按需引入。
    • 场景问题和诉求:
      • 跨平台维护困难:每新增一个平台,都要重新适配完全不同的底层接口,缺乏统一的中间层抽象,导致平台扩展成本高、复用率低。
      • 代码耦合严重:调用方被迫感知当前运行平台,手动分派日志实现,违反了平台无关的设计原则,使业务逻辑与平台绑定过深。
    • 解决方案:基于仓颉的编译型跨平台能力,为多端实现统一的日志接口。定义common层公共接口,在各平台实现platform层具体逻辑:
      收起
      自动换行
      深色代码主题
      复制
      1. // log.cj
      2. package cjmpfoundation
      3. public common func log(tag:String, msg: String): Unit
      4. public common func logE(tag:String, msg: String): Unit
      5. // android/platform_utils.cj
      6. package cjmpfoundation
      7. foreign {
      8. func __android_log_print(prio: Int32, tag: CString, fmt: CString): Int32
      9. func FfiLogUtils(tag: CString, msg: CString): Unit
      10. }
      11. public platform func log(tag:String,msg:String): Unit {
      12. unsafe {
      13. let cTag = LibC.mallocCString(tag)
      14. let cMsg = LibC.mallocCString(msg)
      15. FfiLogUtils(cTag, cMsg)
      16. LibC.free(cTag)
      17. LibC.free(cMsg)
      18. }
      19. }
      20. public platform func logE(tag:String,msg:String): Unit {
      21. unsafe {
      22. let cTag = LibC.mallocCString(tag)
      23. let cMsg = LibC.mallocCString(msg)
      24. __android_log_print(6, cTag, cMsg)
      25. LibC.free(cTag)
      26. LibC.free(cMsg)
      27. }
      28. }
      29. // ios/platform_utils.cj
      30. package cjmpfoundation
      31. foreign {
      32. func FfiLog(logString: CString): Unit
      33. }
      34. public platform func log(tag: String, msg: String): Unit {
      35. unsafe {
      36. let cStr = LibC.mallocCString(tag + " : " + msg)
      37. FfiLog(cStr)
      38. LibC.free(cStr)
      39. }
      40. }
      41. public platform func logE(tag: String, msg: String): Unit {
      42. unsafe {
      43. let cStr = LibC.mallocCString(tag + " : " + msg)
      44. FfiLog(cStr)
      45. LibC.free(cStr)
      46. }
      47. }

  2. 电商场景
    • 场景描述:如图所示,某电商平台采用自研开发框架,需同时维护iOS、Android、鸿蒙三个端的后端业务逻辑。各端独立开发、分别迭代,导致同一业务逻辑存在多份实现。

    • 场景问题和诉求:
      • 性能敏感:电商场景对计算响应速度要求高,希望接近原生体验
      • 跨平台维护难:三端各自维护一套代码,人力成本高,希望实现一码多端
    • 解决方案: 基于仓颉编译型跨平台能力,实现高性能跨三端统一
      • 代码共享:通过 common/specific 机制,共享业务逻辑代码,三端统一维护
      • 性能原生:仓颉直接编译为目标平台原生代码,三端均获得接近原生的运行性能

5 技术资产保护

5.1 ArkTS技术资产保护能力概述

ArkTS为开发者提供了源码混淆工具ArkGuard,其主要针对ArkTS、TS和JS语言提供基础混淆功能,将代码中的变量名、函数名、类名、文件名等替换为简短无意义的名称,增加通过逆向产物猜测其用途的难度。

ArkGuard混淆能力

ArkGuard支持基础的名称混淆,不支持控制混淆、数据混淆等高级混淆功能,已有名称混淆选项汇总如下表:

展开

功能

选项

属性名称混淆

-enable-property-obfuscation

字符串属性名称混淆

-enable-string-property-obfuscation

顶层作用域名称混淆

-enable-toplevel-obfuscation

导入导出名称混淆

-enable-export-obfuscation

文件名混淆

-enable-filename-obfuscation

5.2 仓颉技术资产保护能力概述

仓颉提供了外形混淆、数据混淆、控制流混淆等多种混淆技术用于保护开发者的软件资产,提升攻击者逆向攻击仓颉软件的难度。攻击者可采用逆向工程技术对程序进行攻击,并获取程序的符号名、路径信息和行号信息、特征字符串和特征常数,以及控制流信息。仓颉混淆技术可以对这些信息进行混淆和隐藏,让攻击者难以借用这些信息辅助理解程序的运行逻辑。

  • 外形混淆
    • 符号混淆:通过使用随机名称生成算法,将符号名替换为无关的随机字符串,隐藏符号信息。
    • 路径信息混淆:将函数路径信息统一替换为字符串SOURCE,隐藏函数路径信息。
    • 行号混淆:统一将行号替换为0,隐藏行号信息。
    • 函数重排:随机重新排列函数顺序,隐藏函数二进制编译特征。
  • 数据混淆
    • 字符串加密:编译时将字符串进行加密,隐藏字符串信息。
    • 常量混淆:将普通常量运算替换为等价的、更难理解的算数运算,以此隐藏常量特征。
  • 控制流混淆
    • 虚假分支:在程序中插入虚假分支,生成不透明谓词作为分支跳转条件,对抗静态符号执行求解器,隐藏分支信息。
    • 控制流平坦化:将函数基本块组织为switch-case 形式,隐藏基本块之间的跳转关系。

仓颉混淆详细介绍请见《仓颉编程语言白皮书》

适用场景

金融行业对业务逻辑有保密要求场景

  • 场景描述:在开发银行类、股市或基金交易、电商应用时,需要在本地执行的安全策略如果泄露可能造成服务端安全策略泄露,甚至本地机密文件泄露,例如应用需要对请求参数进行编排,并叠加密钥进行哈希计算,得到的哈希值会上传服务端,服务端进行同样的编排和哈希计算校验哈希值是否正确,以鉴别客户端合法性。
  • 场景问题和诉求:如果本地代码逻辑被逆向,攻击者可轻易复制参数编排逻辑,并窃取密钥以及哈希算法,从而伪造合法的哈希值,最终欺骗服务端进行黑灰产;此时需要对本地代码逻辑进行加固和保护。
  • 解决方案:
    • 使用外形混淆,随机生成符号名称,将符号名替换为无关的随机字符串,隐藏符号信息。

    混淆前符号信息示例

    混淆后符号信息示例

    • 使用数据混淆,编译时将敏感字符串进行加密,程序初始化时动态解密,隐藏敏感字符串信息。

    混淆前敏感字符串示例

    混淆后敏感字符串示例

    • 使用控制流混淆,将函数基本块组织为switch-case形式,隐藏基本块之间的跳转关系,增加逆向难度。

    混淆前程序控制流示例

    混淆后程序控制流示例

5.3 技术资产保护建议

与其他代码混淆工具一样,ArkTS及仓颉的混淆工具只能在一定程度上增加逆向工程的难度,并不能彻底阻止逆向工程,对于源码安全有高要求的开发者,建议考虑使用应用市场提供的应用加密功能或者三方安全加固等安全措施来保护代码。

6 AI辅助开发

鸿蒙ArkTS、仓颉作为新兴应用开发语言,目前开源训练语料储备较为匮乏,致使主流业界大模型对ArkTS、仓颉代码的适配与生成能力普遍偏弱。

尽管 ArkTS 语法体系与 TypeScript 高度相近,但其公开可用语料体量尚不足 TypeScript 的百分之一,这就导致大模型在代码生成时,极易默认沿用 TypeScript 语法逻辑输出内容。而 TypeScript 中大量与 ArkTS 规范不兼容的语法特性,也由此成为鸿蒙 AI Coding 场景下,ArkTS 开发出现语法错误的核心诱因。仓颉语法与其他静态语言语法相近,但公开可用语料同样不足。

短期内无法完成ArkTS、仓颉语料库 2 至 3 倍量级的快速扩容,通过工程化路径优化代码生成精度是必要措施。

经调研广大鸿蒙生态开发者的实际体验,AI 辅助应用开发过程中有三类突出痛点:

1、代码生成环节问题较多,尤以语法错误最为突出,致使项目无法正常构建,需多轮人机协同修改,部分缺陷无法通过 AI 自主修复;

2、程序构建完成并部署至终端设备或模拟器后,频繁出现界面展示错乱、交互逻辑异常等缺陷,人工测试核验重复性强、耗时久;

3、自测试的问题整改依赖开发者手动输入自然语言指令引导 AI 修复,持续陷入编码改错、编译打包、真机测试的低效迭代流程。

鸿蒙应用特性开发与缺陷修复阶段,AI 可有效提升代码编写速率,但多轮纠错调试、人工测试验证、二次修复等流程存在效率阻滞,致使端到端开发效率提升遇阻,开发者普遍反映实际增效效果并不明显。

实现应用落地、完成功能特性迭代,是开发者核心开发目标。开发者初衷本是借助 AI 提升开发效率,可当前在通用 AI辅助工具上的开发流断点,反而拉长整体开发周期。即便最终能够完成功能开发,整体开发体验也大打折扣。

站在全流程开发视角来看,理想开发模式应实现开发旅程的自动化闭环:开发者提交开发需求后,AI 自动完成代码生成,联动语法校验工具智能排查并修复语法问题;无误代码可自动编译构建 HAP 安装包,同步推送至模拟器完成部署,自动开展功能校验与兼容性测试;一旦检测出异常问题,即刻反向回流至代码生成与修改环节,启动迭代优化。经过多轮自动化自验证与迭代修正,直至精准达成特性的开发目标。

鸿蒙将与开发者共同努力,让应用全流程 Agentic 智能开发的理想模式成为现实。实现开发者仅需明确业务需求,即可交由 AI 自主闭环完成代码编写、语法纠错、模拟器/真机自验证、问题整改等全链路工作,直至需求开发完成,最终由开发者确认验收的目标。在大幅提升代码生成正确率的同时,最大限度减少人工干预,压缩开发耗时,全面优化开发者体验。

7 智能化

7.1 仓颉智能应用开发能力

仓颉通过元编程能力和 DSL 能力构建 Agent DSL 能力,兼顾细粒度控制与开放扩展,构建动态、意图驱动的AI计算范式。包括单 Agent 编程开发、多 Agent 协同、支持 MCP 协议等。

  1. Agent 核心要素的语言级支持:现代 AI Agent 的开发通常围绕模型、提示词、规划和工具四大核心要素展开。
    • 模型:通过提供统一的模型调用方式,屏蔽不同模型接入时的差异,降低开发者接入成本。
    • 提示词:将传统的文本提示词提升为语言的一等公民,开发者可以结构化地定义 Agent 的行为模式、目标与预期输出。
    • 规划:开发者可以声明式地定义 Agent 的执行流程。
    • 工具:支持无缝接入外部工具与服务,包括仓颉模块和现有 Agent 工具生态(如 MCP 服务),都能自然融入 Agent 执行流程。

  2. 多 Agent 协同:仓颉Agent DSL 引入了一套简洁直观的流式语法,用于描述 Agent 之间的交互关系与协作模式。如下:
    • 线性协同:适用于阶段化的处理流程,例如数据依次经过三个 Agent 的流水线处理。
    • 主从式协同:适用于层次化组织结构,例如一个主 Agent 负责任务分解与结果整合,子 Agent 则专注于特定子任务
    • 自由协同:适用于基于共享上下文的松耦合交互,例如多个 Agent 可以自由发言、响应事件,并在统一上下文中交换信息。

  3. 安全与输出可控:仓颉 Agent DSL 通过语言类型机制对 Agent 输出进行结构化约束,使输出结果可预测、可验证与可治理,为高可信智能应用提供基础保障。
    • 类型化输出:通过类型系统定义 Agent 输出 Schema,确保结构稳定、字段明确。
    • 约束与校验:支持对输出进行类型约束与校验,避免不符合预期的数据进入后续流程。
    • 语义控制:结合 DSL 能力,对输出内容进行范围、枚举等语义级约束。

适用场景

鸿蒙智能应用开发场景

  • 场景描述:面向鸿蒙智能应用开发,需实现自然语言交互、任务理解与系统能力调用等功能。
  • 场景问题和描述:开发者需要将 Agent 能力嵌入应用,实现从“功能驱动”向“意图驱动”的智能化升级(如应用内智能助手、设备控制、日程管理等),但面临 Agent 应用开发复杂度高的问题。
  • 解决方案:仓颉 Agent DSL 支持声明式定义 Agent、工具调用和任务规划,开发者只需指定模型、工具、执行策略及行为提示词,即可简洁实现智能体。

在应用内定义一个具备任务理解和工具调用的“鸿蒙日程助理Agent”的示例如下:

收起
自动换行
深色代码主题
复制
  1. @agent[
  2. model: "deepseek:deepseek-v3.2",
  3. description: "鸿蒙应用内的智能日程助理",
  4. tools: [scheduleToolManager],
  5. executor: "react"
  6. ]
  7. class ScheduleAssistant {
  8. @prompt("你是一个日程助理,负责理解用户需求,并生成规范的日程处理结果。")
  9. }
  10. let assistant = ScheduleAssistant()
  11. // 用户输入:明天上午 10 点提醒我参加项目评审
  12. let result = assistant.run("明天上午10点提醒我参加项目评审")

搜索
请输入您想要搜索的关键词