應用場景與商業價值
- 遊戲漢化:將海外遊戲 (英文/日文/韓文) 翻譯為中文,拓展中文市場
- 換皮/二次發布:替換遊戲內文字 (故事、公司名、品牌標識)、圖片、音效,低成本推出新版本
- 本地化適配:調整術語、文化梗、法規要求文字 (如版號、防沉迷提示)
文字存儲方式分類與處理策略
| 存儲方式 | 特徵 | 處理難度 | 工具/方法 |
| 硬編碼在 .class | 字串常量池 (Constant Pool) 中,編譯後嵌入位元碼 | ★★★★☆ | Java 反編譯器 + 十六進制編輯器 + 重編譯 |
| 獨立資源檔 | `/res/messages.txt`、`.properties`、XML、自訂格式 | ★☆☆☆☆ | 直接編輯/替換資源檔,重打包 |
| 資源檔加密/壓縮 | 自訂加密、Base64、ZIP、混淆器加密字串 | ★★★★★ | 需逆向加密算法,或 Hook 運行時解密點 |
| 圖片/圖集內嵌文字 | UI 文字繪製在圖片上 | ★★★☆☆ | 美術重繪/PS 修改,重打包資源 |
核心技術:.class 檔案字串常量池結構
Java 編譯器將字面值字串存入 **Constant Pool (常量池)**,結構:
CONSTANT_Utf8_info {
u1 tag = 1; // 標識 UTF-8 字串
u2 length; // 字節長度 (非字元數)
u1 bytes[length]; // 實際字節內容 (Modified UTF-8 編碼)
}
關鍵規則:中文字元佔 3 字節
- ASCII 字元 (英文、數字、符號):**1 字節**
- 中文/日文/韓文 (BMP 範圍):**3 字節** (Modified UTF-8 編碼)
- Emoji/補充平面字元:**4 字節**
**修改鐵律**:替換字串時,**新字串字節長度必須等於原字串字節長度**,否則需修改 `length` 欄位並調整後續常量池索引——極易導致類別檔損壞。
實戰流程:十六進制編輯器修改 .class 字串
工具鏈
- WinRAR / 7-Zip:解壓 JAR/JAD
- UEdit32 / HxD / 010 Editor:十六進制編輯 .class
- JDK (javac):編譯輔助類別產生目標字節碼
- Java 反編譯器 (JD-GUI, Fernflower, CFR):定位目標類別/字串 (輔助)
步驟 1:產生標準字節碼樣本
// A.java - 專用於產生目標中文字串的字節碼
public class A {
static {
String s = "你要替換的中文內容"; // 精確目標字串
System.exit(0);
}
}
javac A.java // 產生 A.class
步驟 2:定位目標 .class 與字串位置
- 解壓遊戲 JAR,用反編譯器找到包含目標文字的類別 (如 `GameStrings.class`、`StoryText.class`)
- 用十六進制編輯器開啟該 `.class`
- 搜尋原文字 (ASCII 直接搜尋;中文搜尋其 UTF-8 字節序列,或在反編譯器對照行號定位)
- 識別結構:`[Tag=01] [Length=高位][Length=低位] [Bytes...]`
步驟 3:驗證字節長度匹配

- 陰影區:字串實際字節內容
- 紅框+紫框:`length` 欄位 (大端序),十進制 = 字節長度
- **新舊字串字節長度必須相等**,否則需修改 `length` 並連鎖調整後續常量池偏移 (極度不建議手工操作)
步驟 4:複製替換
- 用十六進制編輯器開啟步驟 1 產生的 `A.class`
- 找到目標字串字節區 (同樣結構)
- **整段複製** (含 Tag、Length、Bytes) → 貼上覆蓋遊戲 `.class` 對應位置
- 儲存修改後的 `.class`
步驟 5:重新打包並測試
- WinRAR 開啟遊戲 JAR,以「替換」模式更新修改後的 `.class`
- 若修改 MANIFEST.MF/JAD,同步更新
- 傳輸至手機/模擬器測試,確認文字已替換、遊戲正常運行
進階技巧與避坑指南
技巧 1:等長替換原則 (最穩健)
- 翻譯時**嚴格控制字數**,使中文譯文 UTF-8 字節長度 = 原英文 UTF-8 字節長度
- 例:`"Game Over"` (9 字節) → `"遊戲結束"` (9 字節? 不,中文 3字×3=9字節 ✓)
- 不足時用全形空格 ` `、標點填充;超出時精簡措辭
技巧 2:利用反編譯器輔助定位
- JD-GUI 開啟 `.class`,搜尋關鍵字,查看對應行號/常量池索引
- 十六進制編輯器跳轉至對應偏移量 (需換算)
技巧 3:資源檔未加密時優先修改資源檔
- 解壓 JAR 檢查 `/res/`、`/META-INF/`、根目錄下的 `.txt`、`.properties`、`.dat`
- 直接修改資源檔 **無需動 .class**,風險極低、效率極高
避坑 1:修改 length 導致類別損壞
手工修改 `length` 需同步調整:
- 該常量池項目後續所有項目的偏移量
- 所有引用該常量池索引的指令 (如 `ldc #index`)
- 類別檔 `constant_pool_count` 及後續結構
**結論**:除非極其熟悉 Class File Format,**絕不修改 length**,堅持等長替換。
避坑 2:混淆器加密字串
- ProGuard/DexGuard/專用混淆器會加密字串常量,運行時解密
- 特徵:`.class` 中搜尋不到明文、字串區顯示亂碼/高熵值
- 對策:Hook 解密方法 (需動態分析)、或尋找未加密版本、或放棄漢化
避坑 3:簽名驗證
- 部分平台/遊戲啟動時驗證 JAR 簽名/校驗和
- 修改 `.class` 會導致簽名失效、校驗和不符
- 對策:重新簽名 (需私鑰)、Patch 驗證邏輯 (修改驗證類別)、或僅修改無簽名保護的資源檔
自動化工具化建議
大量字串替換時,手工十六進制編輯不可行。建議開發/使用:
- 字串提取器:掃描 `.class` 常量池,匯出所有字串至 CSV/Excel
- 翻譯管理表:原文、譯文、字節長度、等長標記、目標類別/偏移量
- 批量修補腳本:讀取管理表,自動對 `.class` 做等長字節替換、校驗
- 驗證器:修改後自動用 `javap -v` 驗證類別結構完整性
法律與道德邊界
- **授權漢化**:取得版權方書面授權,合法合規
- **換皮發布** : 確保擁有遊戲完整知識產權或授權,避免侵權
- **私人學習** : 僅供技術研究,勿散播修改後檔案
- **尊重原創** : 保留原作者署名、版權聲明,不移除授權資訊
總結
J2ME 遊戲漢化/換皮核心在於 **`.class` 常量池 UTF-8 字串的等長字節替換**。關鍵成功因素:
- 精準定位目標類別與字串 (反編譯器輔助)
- 嚴格遵守 **等長替換** 原則 (字節長度不變,不動 length)
- 利用輔助類別編譯產生標準字節碼樣本
- 優先修改無加密資源檔,降低風險
- 重打包、重簽名、實機測試全流程驗證
這項技術雖屬「逆向工程」範疇,但掌握 **Class File Format、Modified UTF-8、常量池結構** 等 JVM 底層知識,對 Java 開發者深入理解編譯原理、診斷疑難雜症、設計序列化協議、實現熱修復等高階能力極有裨益。