鸿蒙PC迁移:Luyten Java 反编译工具鸿蒙PC适配全记录:从 Java Swing 桌面程序到 ArkTS 单机 HAP
一、写在前面
欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态:鸿蒙PC开发者社区:https://harmonypc.csdn.net/
项目开源项目:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_Luyten
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
这篇文章记录的是 Luyten 这个 Java 反编译 GUI 工具适配 HarmonyOS PC 的完整过程。
Luyten 原本是一个经典 Java Swing 桌面应用,它的定位非常明确:
打开
.jar、.zip、.class文件,查看包结构,并把 Java class 反编译成开发者可阅读的内容。
原版 Luyten 的核心能力来自 Procyon 反编译器,界面侧则使用 Swing、JTree、JTabbedPane、RSyntaxTextArea 等桌面组件。也就是说,它不是 Electron 项目,也不是 Web 项目,而是一个传统 Java 桌面工具。
这次适配的目标不是简单地让一个页面出现在鸿蒙 PC 上,而是要让它在 HarmonyOS PC 上形成一个不依赖外部服务的单机工具:
- 不依赖 Mac 上的 Java 进程;
- 不依赖 HTTP 后端;
- 不需要用户额外启动服务;
- 在鸿蒙 PC 上直接打开
.jar/.zip/.class; - 在应用内解析 ZIP/JAR、解析 Java class、展示结构树、代码视图、字节码和元信息;
- UI 尽量贴近原版 Luyten 桌面软件。
最终适配完成后,项目新增了一个 harmony_pc_standalone/ 鸿蒙工程。它使用 ArkTS / ArkUI 重建了 Luyten 的桌面布局,并实现了一套本地 class/JAR 解析流程。
当前版本已经实现:
- 打开
.jar、.zip、.class; - 解析 ZIP/JAR central directory;
- 支持 ZIP
stored和deflate压缩方式; - 解析 Java class 基础结构;
- 展示类名、父类、接口、字段、方法、属性、Code attribute;
- 展示伪 Java 源码、成员列表、字节码预览、元信息;
- 多 tab、搜索、Find Next、Find Previous、Find All;
- Save As、Save All;
- Recent Files;
- 主题和偏好持久化;
- 原版 Luyten 风格的菜单栏、Structure 树、Code 面板和底部状态栏。
需要说明的是,当前版本还不是完整 Procyon 级别 Java 反编译器。它已经完成了“打开文件、解析 class、展示结构和字节码”的核心流程,但方法体还原目前是结构化伪源码。完整的 bytecode -> CFG -> AST -> Java 源码还原,是后续继续深化的方向。

二、原项目分析:Luyten 是典型 Java Swing 反编译 GUI
原始 Luyten 项目根目录结构比较清晰:
Luyten-master/
├── pom.xml
├── README.md
├── src/
│ └── us/deathmarine/luyten/
│ ├── MainWindow.java
│ ├── MainMenuBar.java
│ ├── Model.java
│ ├── OpenFile.java
│ ├── FindBox.java
│ ├── FindAllBox.java
│ └── ...
└── harmony_pc_standalone/
README 中对项目的描述非常直接:
Java Decompiler Gui for Procyon
也就是说,原版 Luyten 的定位不是普通文本查看器,而是一个 Procyon 的 Java 反编译 GUI。
原项目里几个关键类分别承担不同职责:
MainWindow.java:主窗口,负责 JFrame、菜单、tab 容器、底部状态栏;MainMenuBar.java:顶部菜单,包括 File、Edit、Themes、Operation、Settings、Help;Model.java:核心界面模型,左侧 Structure 树、右侧 Code tab、JAR/class 打开逻辑;OpenFile.java:代码编辑区,基于 RSyntaxTextArea;FindBox.java/FindAllBox.java:查找和全局查找;DecompilerEngine.java:原项目中与 Procyon 反编译相关的能力。
原版界面的几个主要特征也很明确:
- 顶部是传统桌面菜单栏;
- 左侧是
Structure树; - 右侧是
Codetab; - 代码区域是只读编辑器;
- 底部有状态栏和进度条;
- 支持打开 JAR/class、切换主题、搜索、保存、导出。
这也决定了本次适配不能做成一个完全陌生的移动端页面。鸿蒙 PC 端最好保留桌面工具的工作流,让用户一眼能看出它还是 Luyten。

三、路线选择:不再依赖 Java 服务,改成鸿蒙 PC 单机 ArkTS 实现
适配 Luyten 时,最开始有几条路线可以选。
第一条路线是保留原 Java + Procyon,把鸿蒙端做成一个前端,背后仍然由 Mac 或某台机器上的 Java 服务反编译。这条路线验证快,但用户每次使用都需要额外启动服务,不符合“鸿蒙 PC 自己跑完整流程”的目标。
第二条路线是尝试把 Java Swing/AWT 搬到鸿蒙 PC。这个方向成本很高,因为 Swing 的窗口体系、菜单、文件选择器、文本编辑器、JTree、JTabbedPane 都不是鸿蒙 ArkUI 的组件模型。即使能保留一部分 Java 代码,桌面 UI 也要重新适配。
第三条路线是重新做一个 HarmonyOS PC 单机版本。也就是:
- 使用 ArkTS / ArkUI 实现界面;
- 用 ArkTS 本地读取文件;
- 用 ArkTS 解析 ZIP/JAR;
- 用 ArkTS 解析 class 文件;
- 在鸿蒙 PC 端直接展示结构树、代码、字节码和元信息。
最终选择的是第三条路线。
原因很简单:用户需要的是一个不依赖外力的鸿蒙 PC 应用。只要安装 HAP,就可以打开 .jar/.class,不需要 Mac 端 Java 服务,也不需要 HTTP 接口。
因此项目新增了:
harmony_pc_standalone/
├── AppScope/
├── build-profile.json5
├── oh-package.json5
└── entry/
├── build-profile.json5
├── oh-package.json5
└── src/main/
├── ets/
│ ├── entryability/
│ ├── pages/
│ │ └── Index.ets
│ └── parser/
│ ├── ByteReader.ets
│ ├── ClassParser.ets
│ ├── FileLoader.ets
│ ├── Inflater.ets
│ └── ZipParser.ets
└── resources/
└── rawfile/
└── demo.jar
这个目录就是本次适配后的鸿蒙 PC 单机工程。

四、核心实现一:本地读取 JAR/ZIP/class 文件
鸿蒙端打开文件使用的是系统 DocumentViewPicker。最初文件过滤器分成了两个选项:
fileSuffixFilters: ['Java archives|.jar,.zip', 'Java class|.class']
这个写法能用,但在真实鸿蒙 PC 文件选择器中暴露出一个问题:如果默认停留在 Java archives,进入一个只有 .class 文件的目录时,文件列表会显示为空,用户就会以为 class 文件不能选。
最终修复为只保留一个过滤项:
fileSuffixFilters: ['Java files|.jar,.zip,.class']
这样 .jar、.zip、.class 都会在同一个过滤条件下显示,不会再出现“目录里明明有 class,但打开后是空的”的问题。
读取文件后,流程会判断文件类型:
- 如果前四个字节是
CAFEBABE,按单个.class解析; - 否则按 ZIP/JAR 解析;
- 如果是 JAR/ZIP,读取 central directory;
- 找出所有
.classentries; - 建立左侧 Structure 树;
- 默认打开第一个 class。
其中 ZIP/JAR 解析主要在:
entry/src/main/ets/parser/ZipParser.ets
class 文件读取主要在:
entry/src/main/ets/parser/ClassParser.ets
文件读取封装在:
entry/src/main/ets/parser/FileLoader.ets
这一步完成后,应用已经能在鸿蒙 PC 上打开真实文件,而不是只加载内置 demo。

五、核心实现二:纯 ArkTS ZIP deflate 解压和 class 解析
JAR 本质上是 ZIP 文件。很多 JAR 里的 class entry 使用的是 deflate 压缩方式,也就是 compression method 8。
一开始尝试过使用系统 zlib 能力,但在真机运行时出现过对象异常。因此后续改成了纯 ArkTS 的 raw deflate 实现,核心文件是:
entry/src/main/ets/parser/Inflater.ets
这样处理后,JAR 中的 deflated class entry 可以直接在鸿蒙 PC 端解压,不再依赖 native zlib 流对象。
class 解析部分由 ClassParser.ets 实现,主要完成:
- 校验
CAFEBABEmagic; - 读取 minor / major version;
- 读取 constant pool;
- 解析 class name;
- 解析 super class;
- 解析 interfaces;
- 解析 fields;
- 解析 methods;
- 读取 method 的 Code attribute;
- 解码一部分 JVM bytecode 指令;
- 渲染 summary、members、bytecode、metadata;
- 生成结构化伪 Java 源码。
当前生成的 Java 视图类似:
package demo;
public class DemoHello {
private final String name;
public DemoHello(String arg0) {
// bytecode length: 10, maxStack: 2, maxLocals: 2
}
public String greet() {
// bytecode length: 10, maxStack: 1, maxLocals: 1
}
}
这说明类结构、字段、方法签名已经能还原出来。完整方法体反编译还需要继续做栈模拟、表达式还原、控制流还原和 AST printer,这是后续反编译核心深化的重点。
六、核心实现三:把前端做回原版 Luyten 的桌面样式
适配早期版本曾经做成过“分析器风格”的界面:左侧 class 列表,右侧 Source / Members / Bytecode / Metadata 切换。这个界面能用,但不像 Luyten。
后面重新对照原版 Luyten,把 UI 调整为桌面工具布局:
- 顶部菜单:
File、Edit、Themes、Operation、Settings、Help; - 左侧标题框:
Structure; - 右侧标题框:
Code; - 右侧支持 tab;
- 代码区使用 monospace 字体;
- 底部状态栏显示
Complete、加载状态和进度; - 主题支持默认和暗色;
- 应用标题改回
Luyten。
菜单功能也逐步补齐:
File -> Open File...File -> Close FileFile -> Save As...File -> Save All...File -> Recent FilesFile -> Clear Recent FilesEdit -> FindEdit -> Find NextEdit -> Find PreviousEdit -> Find AllThemes -> Default / DarkOperation -> Package Explorer StyleOperation -> Filter Out Inner Class EntriesSettings -> Java / Bytecode / Bytecode AST / Members
这里的重点不是追求一个全新的现代 UI,而是让原版 Luyten 用户来到鸿蒙 PC 版时还能识别出熟悉的使用路径:
打开 JAR/class -> 左侧选 class -> 右侧看代码 -> 搜索/保存/切换视图
七、搜索、保存、最近文件和偏好持久化
除了打开和解析 class,本次适配还补了桌面工具常用能力。
7.1 搜索
当前支持:
FindFind NextFind PreviousFind All
搜索栏可以输入关键字,显示匹配数量和当前匹配行号。Find All 会生成一个 Find Results tab,列出匹配的 tab、行号、列号和预览内容。
7.2 保存
当前支持:
Save As...:导出当前 tab;Save All...:导出当前已打开的所有 tabs。
Java 视图默认导出 .java,其他视图导出 .txt。保存走鸿蒙 PC 的 DocumentViewPicker.save(),由用户选择保存位置。
7.3 最近文件
打开外部文件后,会记录到 Recent Files。偏好写入鸿蒙本地 preferences:
preferences.getPreferencesSync(getContext(this), { name: 'luyten_preferences' })
保存的内容包括:
- 最近文件 URI;
- Package Explorer Style;
- Filter Out Inner Class Entries;
- Single Click Open;
- Dark Theme;
- 当前视图模式。
7.4 主题和视图模式
目前支持默认主题和暗色主题。代码视图支持:
JavaMembersBytecodeMetadata
其中 Java 是结构化伪源码,Bytecode 可以看到方法内的 JVM 指令预览,Metadata 可以看到 class 文件的结构信息。


八、构建、安装和真机运行
鸿蒙工程路径:
~/XM/Luyten-master/harmony_pc_standalone
构建命令:
cd ~/XM/Luyten-master/harmony_pc_standalone
~/ohos/command-line-tools/bin/hvigorw assembleHap --mode module -p module=entry -p product=default --no-daemon
签名后的 HAP 路径:
~/XM/Luyten-master/harmony_pc_standalone/entry/build/default/outputs/default/entry-default-signed.hap
查看连接设备:
/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc list targets
安装到鸿蒙 PC:
/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc install -r entry/build/default/outputs/default/entry-default-signed.hap
启动应用:
/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc shell aa start -b com.phototonic.viewer -a EntryAbility
本次适配过程中,最终验证结果是:
BUILD SUCCESSFUL
install bundle successfully
start ability successfully
九、适配过程中踩到的几个关键问题
9.1 Uint8Array 不能随便放进 @State
早期版本曾经把 Uint8Array 放进 ArkUI @State,真机上出现过运行时异常。后面改成普通字段:
private fileBytes: Uint8Array = new Uint8Array(0);
private zipEntries: Array<ZipEntryInfo> = [];
private isArchive: boolean = false;
界面真正需要响应刷新的数据,比如 class 列表、tree rows、open tabs,才保留为 @State。
9.2 系统 zlib 流对象在真机上不稳定
JAR 里的 class entry 常见压缩方式是 deflate。曾经尝试走系统 zlib,但真机上遇到对象异常。后面改成纯 ArkTS raw deflate 实现,避免依赖外部 native 流对象。
这也是本次单机能力能跑通的关键一步。
9.3 文件选择器过滤项会影响 class 可见性
如果文件选择器默认选中 Java archives,目录里的 .class 会被隐藏。最终只保留一个过滤项:
fileSuffixFilters: ['Java files|.jar,.zip,.class']
这样用户打开 class 文件时不会踩坑。
9.4 UI 不能偏离原版工具心智
一开始做成“分析器面板”时,功能能跑,但不像 Luyten。用户真正想要的是“原开源软件那种前端”。所以最终界面还是回到:
菜单栏 + Structure 树 + Code tab + 底部状态栏
这类桌面工具迁移到鸿蒙 PC 时,保留原有工作流比做一个全新页面更重要。
十、当前完成度和后续方向
当前版本已经完成了 Luyten 鸿蒙 PC 单机版的基础闭环:
打开 JAR/class
-> 解析 ZIP/JAR
-> 解压 class entry
-> 解析 class 文件
-> 显示 Structure
-> 打开 Code tab
-> 查看 Java 伪源码 / Members / Bytecode / Metadata
-> 搜索
-> 保存
-> 记录最近文件和偏好
这次适配最重要的收获是:对于传统 Java Swing 工具,不一定要把 Swing 原样搬上鸿蒙 PC。只要先把核心文件处理链路拆出来,再用 ArkTS 按鸿蒙 PC 的方式实现本地解析和桌面 UI,就可以在不依赖外部服务的前提下,先把一个开发者工具真正跑起来。
更多推荐




所有评论(0)