JRD(1)
β¨ JRD(1) β java-runtime-decompiler π
okay bestie, sit down, hydrate, because we're about to talk about JRD β the Java Runtime Decompiler. yes, that one. she's iconic, she's powerful, and she's about to make you feel things about bytecode. π¦
πΈ NAME πΈ
JRD β Java Runtime Decompiler. that's it. that's the whole name. short, sweet, main character energy. π
π SYNOPSIS π
so here's the vibe. every single invocation starts the same way β you run the launcher, either ./start.sh or start.bat, and then optionally yeet -verbose at it to get the receipts. from there, the shapes she takes are:
(./start.sh|start.bat) [-verbose] # launches GUI
(./start.sh|start.bat) [-verbose]
(-help|-h|-completion|-R|-hex|BOOT|SYSTEM|-overwrite|-init|-removeoverrides|-addclass|-addclasses|-addjar|-listoverrides|-listclassloaders)
(./start.sh|start.bat) [-verbose]
(-listclasses|-listdetails|-bytes|-base64bytes|-deps|-compile|-decompile|-patch|-api|-listjvms|-listplugins|-listbytecodeversions|-listdetailsversions|-search)
[-saveas [-savelike]]
(./start.sh|start.bat) [-hex] [file, file...] launches standalone hex
(or text) editor/diff. Mighty diff. -hex suggests, how to open `file,
file...`
(./start.sh|start.bat) [-fs] <class:path> will launch temporary
filesystem based decompiler
no cap, that's the whole map. she's giving "many moods, one binary." π
π OPTIONS π
β Standard options β
the classics. the staples. the ones you'll actually type at 2am.
-help,-hβ prints this help text. that's it, that's the whole job. she's helpful and she knows it. π«Ά-verboseβ every exception and a handful of debugging strings get printed out to standard error. basically: she tells you everything, even the stuff you didn't ask for. not me turning the volume all the way up. π-versionβ prints the version project name, the version, and the build timestamp. the full birth certificate. π-configβ prints the path to the main config file. and if you're in verbose mode? she prints the file itself too. (yes the original really has that double period at the end, I'm keeping her exactly as she is, no editing my girl.) π-hexβ switches all binary operations into hex-readable format. all of them. including patching. so like, everything binary becomes hex-coded. π₯-fs <class:path>β opens jrd in the local filesystem with the classpath you set. filesystem mode, no JVM required, she's flexible like that. π¦-classloader <classloader identification>β plot twist: in a jvm there can be multiple classes of each FQN, each one loaded by a different classloader. this regex lets you specify which classloader(s) you want to operate on. choose your fighter. π-listjvmsβ lists all the local Java processes and their PIDs. a whole roster of little guys. β¨-listpluginsβ lists all currently configured decompiler plugins and their statuses. who's working, who's slacking. πΈ-listagentsβ JRD keeps a record of all local agents and drops them once they become inaccessible. use this to list the known agents. you can also append-versionsto also get the version of each agent (which may be incompatible or not ours at all β shady). π-listoverrides <PUC>β lists all currently overwritten classes. π-removeoverrides <PUC> removalRegexβ removes all matching overwrites of classes. bye bestie, you're gone. π§-listclasses <PUC> [<CLASS REGEX>...]β lists all loaded classes of a process, optionally filtered. heads up: only-savelike exactor-savelike defaultare allowed as saving modifiers here. no improvising. β-listclassloaders <PUC> [classRegex]β lists and counts all the classloaders visible by the agent. she's counting. π-listdetails <PUC> [<CLASS REGEX>...]β like-listclassesbut she spills more tea about each class. more details, more drama. π-listbytecodeversions <PUC> [<CLASS REGEX>...]β lists all classes along with their bytecode version. she's slow though. like, slow. be patient with her. π-listdetailsversions <PUC> [<CLASS REGEX>...]β lists all classes with details and bytecode version. also slow! double the info, double the wait. π-search <PUC> <CLASS REGEX>... searchedSubstring true/falseβ (with/without details) will search for an ascii/utf8 substring in the regex-subset binaries of a remote vm. want to search in decompiled classes instead? usegrep. and yes, you can misuses-hexto include bytecode level β the original literally says "misuses," I'm not touching it. π-base64bytes <PUC> <CLASS REGEX>...β prints the Base64 encoded binary form of the requested classes of a process. pretty, encoded, slay. β¨-bytes <PUC> <CLASS REGEX>...β prints the binary form of the requested classes of a process. raw bytes, no filter. π₯-deps <PUC> <CLASS REGEX>...β prints all the deps of the selected class(es). she knows who's connected to who. π-patch <PUC> <PLUGIN>xor<ADDITIONAL-SOURCE/CLASS-PATH (-hex) (-R)β okay this one's a whole saga, so buckle up:- you may ignore the plugin/path param in
-hexmode. you can apply a patch from STD-IN to classes in<PUC>. the patch can be on source, or on binary if-hexis provided. - the header (
+++/---) must contain the dot-delimited FQN of the class. everything before/(or\) is stripped..class$/.java$is omitted. - see the gui for the examples.
- if a plugin is specified, the runtime classpath is decompiled, patched, compiled (it is not (de)compiled with
-hex) and uploaded. - if a plugin is not specified, then source from additional-source-path is patched, compiled and uploaded.
- if
-hexis set, then binary from additional-class-path is patched and uploaded. in both cases, the class is INIT before all. - this is a bit different from the gui, where patch is patching just one file.
- in cli it can contain several files, and is moreover a direct shortcut to init, bytes, (decompile,) patch, (detect bytecode level, compile,) upload.
- as a patch tool,
-Rwill invert the patch. π - for debugging,
-savelike dircan be used to save the patched and compiled output.-savelike fqncan be used to save patched sources. π
- you may ignore the plugin/path param in
-compile [-p <PLUGIN>] [-cp <PUC>] [-r] <PATH>...β compiles local files against the runtime classpath specified by-cp.- use
-pto utilize some plugins' (like jasm or jcoder) bundled compilers. π οΈ - use
-rfor recursive search if<PATH>is a directory. - if the argument of
-saveasis a valid PID or URL, the compiled code will be attempted to be injected into that process. π - if multiple PATHs were specified but there's no
-saveas, the process fails. no saveas, no service. π - use:
-Dofio.github.mkoncek.cplc.log-to-provider=any subset ofADDING_CLASS,IGNORE_ARRAYS,IGNORE_LAMBDAS,INTERESTING,SKIPPING_OVERto see what CPLC reolver is doing. warning: CPLC have issues with default (none). π
- use
-decompile <PUC> <PLUGIN> <CLASS REGEX>...β decompiles and prints classes of a process using the specified decompiler plugin. and fun fact: Javap can be passed options by appending them without spaces β so'javap-v-public ...'executes as'javap -v -public ...'. sneaky, clever, obsessed. π-overwrite <PUC> <FQN> [<CLASS FILE>]β overwrites a class of a process with new bytecode. if<CLASS FILE>isn't set, standard input is used. πΈ-addclass <PUC> <FQN> <CLASS FILE>β adds a class. currently, she's unable to add a class unless all its dependencies are already in the running vm. sorry bestie, that's the rules. stdin is used if there's no file. π«Ά-addjar <PUC> <JAR FILE> [BOOT]β adds all classes from the jar into the selected VM. if you're adding system classes, yo have to specify BOOT. (yes, "yo." keeping it.) π-addclasses <PUC> (<CLASS FILE1>)^n [BOOT]β adds all classes into the jar, guesses their FQN, and sends them into the selected VM. if you're adding system classes, yo have to specify BOOT. β¨-addclasses <PUC> (<FQN1> <CLASS FILE1>)^n [BOOT]β adds all classes into the jar, sets their FQN, and sends them into the selected VM. if you're adding system classes, yo have to specify BOOT. π-init <PUC> <FQN>β tries to initialize a class in a running JVM. heads up: it has no effect in FS VMs. and because class loading is lazy, the class you need might be missing β e.g.java.lang.Override. π-attach <PID>β will only attach the agent to the selected pid, and prints out the port for future usage. π-agent <AgentLiveliness> <AgentLoneliness> <port>β controls how the agent is attached. this only makes sense in operations that attach to a PID.
possible values of AgentLiveliness:
ONE_SHOTβ agent will connect, do its job, and disconnect. in and out, no strings. π¨SESSIONβ agent will connect and will remain connected until the end of the session. ποΈPERMANENTβ agent will attach and will disconnect only manually or on the death of the target process. she's staying. forever. π
optional, defaults to SESSION for -overwrite, -patch, -attach and -compile with upload to VM. and to ONE_SHOT for read.
followed by one of AgentLoneliness:
SINGLE_INSTANCEβ the agent is allowed to attach to each process only once, unless FORCING is put to the following attachment (default). πANONYMOUSβ the agent will attach but will not set the flag about its presence. still, the property will be set. (weird.) πFORCINGβ the agent will attach but will skip the check for single instance. (sometimes useful.) πͺAFβ the agent will attach but will skip the check for single instance and will not set the flag about its presence. still, the property will be set. (super weird.) π
optional, defaults to SINGLE_INSTANCE.
you can also specify port, which is where the agent will listen β otherwise the default port is calculated. π’
JRD keeps a record of all permanent and session agents so they can be listed/reused/removed. this list is still checked for consistency. the file is /tmp/jrdAgents. π
and real talk: the -addclass, -addclasses, -addjar are not SESSION or PERMANENT because there is no way to unload them. π
-detach URL xor PORT xor PIDβ will close and detach a PERMANENT agent from the givenlocalhost:portor url. to detach from a PID, a valid mapping in the/tmp/jrdAgentsfile is needed. π§-api <PUC>β will print out the dynamic, real-to-time api which can be used to insert fields/methods into a running vm. living in the now. β¨-completion [<completion1, completion2,...>]β with no parameter, she'll print the available code completions. with a parameter of encoded completion names (delimited by,or), she'll print the details of that exact set of completion. π
πΈ Saving modifiers πΈ
-saveas <PATH>β all outputs will be written to PATH instead of to standard output. β¨-savelike <SAVE METHOD>β specifies how saving will behave. π
π NOTES π
okay bestie, housekeeping time, and this part is important so no skimming π«Ά
Every single option can be written with either one or two leading slashes ('-'). So yeah, -foo and --foo are both giving the same energy. Pick your fighter. β¨
When you're using <CLASS REGEX>, you gotta escape the dollar signs '$' that belong to inner classes and write them as '\$'. Otherwise that $ is gonna do what $ does and mean end-of-line, and your regex will be a whole different story. π Not the vibe you want, trust.
<FQN> is the fully qualified name of a class, exactly as the Java Language Specification Β§6.7 defines it. Fancy official business, we love a citation. π
<PUC> is short for PidUrlClasspath (iconic acronym, no notes) and it can be one of these three:
- a local process PID π₯οΈ
- a remote process URL, formatted like
'hostname:port'π - a classpath of JAR on the filesystem β heads up, the classpath separator here is
':'π
πΎ <SAVE METHOD> β the choose-your-own-adventure πΎ
'dir'β the result gets saved as<PATH>/fully/qualified/name.class. This is the default for .class binaries. π'fqn'β the result gets saved as<PATH>/fully.qualified.name.java. This is the default for .java sources. π'exact'β the result gets saved exactly to<PATH>. This is the default for everything else. π―'default'β saving just uses the defaults listed above. Easy. π
β οΈ WARNING β οΈ
bestie. read this part twice. I'm so serious. π¨
- JRD was designed to overwrite existing classes, with all the limits that hot swap has. Yes, all of them. It's giving "we knew what we were doing and we did it anyway." π
- It's also designed to add new classes that aren't present yet. β¨
- You can try to add an already existing class, as a little workaround for hotswap's limitations, but there is no guarantee that such a class will ever get picked up. So like... go ahead, but don't come crying to me, I warned you. ππ
That's the whole page, bestie β you made it to the end, absolutely ate that. ππ¦
This little masterpiece is dated 2025-10-23, and it lives in section JRD(1) of the manual. Stan a classic. ππ
π¦ where this page comes from
- fedora 43: java-runtime-decompiler 10.0-6.fc43 Β· GPL-3.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms