Humanize decompiled/obfuscated Java code with LLMs (OpenAI, DeepSeek, Ollama, etc.): better names + automatic Javadoc.
Java Humanify uses LLMs to generate more readable, semantic names for classes / methods / fields / local variables, and can automatically create Javadoc for classes / constructors / methods.
All rewrites are performed at the AST layer (JavaParser + Symbol Solver), ensuring the output remains semantically 1:1 equivalent to the input and stays compilable.
Decompiled / minified / obfuscated Java is hard to read:
package demo.mix;public final class a{private static final int[] O={0,1,1,2};private a(){}public static int h(String s){long x=0x811c9dc5L;if(s==null)return 0;int i=0,n=s.length(),j=O[2];while(i<n){char c=s.charAt(i++);x^=c;x*=0x01000193L;x&=0xffffffffL;j^=(c<<1);j^=j>>>7;if((i&3)==0)x^=(j&0xff);}return (int)x;}Java Humanify renames identifiers into human-friendly ones:
package demo.mix;
/**
* Computes a 32-bit hash for the input string using FNV-1a with additional state mixing.
*/
public final class HashCalculator {
private static final int[] O = { 0, 1, 1, 2 };
/** Private constructor for a utility class to prevent instantiation. */
private HashCalculator() {}
/**
* Calculates a 32-bit hash value for the input string using FNV-1a with additional state mixing.
*
* @param inputString the input string
* @return the computed hash value
*/
public static int calculateHash(String inputString) {
long storedValue = 0x811c9dc5L;
if (inputString == null) return 0;
int index = 0, stringLength = inputString.length(), hashState = O[2];
while (index < stringLength) {
char currentChar = inputString.charAt(index++);
storedValue ^= currentChar;
storedValue *= 0x01000193L;
storedValue &= 0xffffffffL;
hashState ^= (currentChar << 1);
hashState ^= hashState >>> 7;
if ((index & 3) == 0) storedValue ^= (hashState & 0xff);
}
return (int) storedValue;
}
}LLMs do not change your code structure.
They only provide naming / comment suggestions. Renaming is applied on the AST with symbol resolution; constructors/imports/file names are kept in sync.
- Pluggable LLMs: OpenAI / DeepSeek / Local (Ollama, OpenAI‑compatible endpoints).
- Semantic package/folder renaming (
package-refactor): rename obfuscated leaf package folders (e.g.,ui73,controls18,a,b2) to meaningful, lowercase segments (e.g.,view,controls,auth) and automatically rewritepackage/importlines. - Automatic Javadoc (
annotate): supports classes, enums, records, constructors, and methods; auto‑generates@param/@return/@throws.- Optional offline heuristic (
dummy): zero cost and no API key, but lower quality than LLMs.
- Optional offline heuristic (
- Signature‑safe renames: centered on classFqn / methodSig / fieldFqn; applied at the AST level; constructors/imports/file names updated accordingly.
- Controllable cost & throughput: batching (
--batch) + concurrency (--max-concurrent) + snippet truncation (--head/--tail/--maxBodyLen). humanify-apkone‑shot APK flow: give it an.apkand it will internally decode (apktool/jadx), deobfuscate/rename code, generate Javadoc, and output readable Java source — no extra tools to install.
analyze → suggest → apply → annotate
(generate snippets) (generate names) (AST apply) (auto Javadoc)
- analyze: scans source code to produce
snippets.json(configurable string‑literal capture and directory exclusion). - suggest: calls LLM/local/heuristics to convert
snippets.json→mapping.json(rename map). - apply: applies the mapping at the AST level, preserving semantics/references and writing to a new directory.
- annotate: generates/overwrites Javadoc (supports
--lang zh|en,--style concise|detailed).
The one‑shot command
humanifyruns these four steps in order on an existing source tree.
The one‑shot commandhumanify-apkfirst decompiles an APK into Java source, then runs the full pipeline automatically and gives you cleaned, renamed, documented code.
# OpenAI
export OPENAI_API_KEY=sk-xxxx
java -jar target/java-humanify-*.jar humanify --provider openai --model gpt-4o-mini samples/src samples/out# DeepSeek
export DEEPSEEK_API_KEY=sk-xxxx
java -jar target/java-humanify-*.jar humanify --provider deepseek --model deepseek-chat samples/src samples/out# Local (Ollama)
# Make sure the model is pulled: ollama run llama3.1:8b (or any model you prefer)
java -jar target/java-humanify-*.jar humanify --provider local --local-api ollama --endpoint http://localhost:11434 --model llama3.1:8b samples/src samples/out# APK mode (humanify-apk)
# Input: myapp.apk
# Output: samples/out containing deobfuscated, renamed, documented Java source
export OPENAI_API_KEY=sk-xxxx # or set DEEPSEEK_API_KEY, or use --provider local
java -jar target/java-humanify-*.jar humanify-apk --provider openai --model gpt-4o-mini myapp.apk samples/outExecution order of
humanify: 1) analyze → 2) suggest → 3) apply → 4) annotate
Execution order ofhumanify-apk: decode APK → analyze → suggest → apply → annotate
--lang/--style/--overwriteaffect the annotate phase.--provider dummyuses offline heuristics.
--package-refactor— Rename Obfuscated Packages/Folders
(If you want package/folder renaming inside the one‑shot flow, use the--rename-packagesswitch, which is equivalent to running thepackage-refactorsubcommand separately.)
Notes
- Run under version control (git). Commit first so you can revert.
- If you want Chinese Javadoc at other stages in the pipeline, set
--lang zhinannotate/humanify.
- OpenAI: requires
OPENAI_API_KEY. - DeepSeek: requires
DEEPSEEK_API_KEY. - Local: use
--provider localand specify--local-api openai|ollamaand--endpoint http://host:port.
To produce Chinese Javadoc, explicitly set
--lang zhand choose any ofopenai|deepseek|localproviders.
Issues and PRs are welcome:
- Use feature branches and keep changes small/testable.
- Follow the existing code style and project structure.
Licensed under Apache-2.0. See LICENSE.
java -jar java-humanify.jar analyze <srcDir> <snippets.json> [opts]
java -jar java-humanify.jar suggest <snippets.json> <mapping.json> [opts]
java -jar java-humanify.jar apply <srcDir> <mapping.json> <outDir> [--classpath ...]
java -jar java-humanify.jar annotate --src <dir[,dir2,...]> [--lang/--style/--overwrite ...]
java -jar java-humanify.jar humanify <srcDir> <outDir> [provider/model/annotate opts...]
java -jar java-humanify.jar humanify-apk <apkFile.apk> <outDir> [provider/model/annotate opts...]
java -jar java-humanify.jar package-refactor --src <dir> [provider/model/opts...]