In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
Today, I will talk to you about the comparison and usage of Java decompilation tools, which may not be well understood by many people. in order to make you understand better, the editor has summarized the following contents for you. I hope you can get something according to this article.
Preface
Java decompilation may feel unfathomable, but decompilation is not a particularly advanced operation. Java has strict requirements for the generation of Class bytecode files. If you are very familiar with the Java virtual machine specification and understand the role of some bytes in Class bytecode files, then understanding the principle of decompilation is not a problem. You can even read one or two Class files like the one below.
Generally speaking, decompilation is often used in reverse research and code analysis. However, in daily development, sometimes it is also very important to simply look at the decompilation of the dependent classes used.
Coincidentally, Java decompilation is also needed in recent work, so this article introduces the use of several common Java decompilation tools. At the end of the article, we will test them through the three dimensions of compilation speed, syntax support and code readability, and analyze the advantages and disadvantages of several tools.
Procyon
Github link: https://github.com/mstrobel/procyon
Procyon is not just a decompilation tool, it is actually a complete set of Java metaprogramming tools focused on the generation and analysis of Java code. It mainly includes the following parts:
Core Framework
Reflection Framework
Expressions Framework
Compiler Toolset (Experimental)
Java Decompiler (Experimental)
You can see that decompilation is just one of the modules of Procyon. Procyon was originally hosted by bitbucket, then migrated to GitHub, and according to GitHub's submission record, it hasn't been updated for nearly two years. However, there are other open source decompilers that rely on Procyon, such as * decompiler-procyon**, which are updated frequently. This tool will also be selected for decompilation testing.
Use Procyon org.jboss.windup.decompiler decompiler-procyon 5.1.4.Final
Write a simple decompilation test.
Package com.wdbyte.decompiler; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Iterator; import java.util.List; import org.jboss.windup.decompiler.api.DecompilationFailure; import org.jboss.windup.decompiler.api.DecompilationListener; import org.jboss.windup.decompiler.api.DecompilationResult; import org.jboss.windup.decompiler.api.Decompiler; import org.jboss.windup.decompiler.procyon.ProcyonDecompiler / * * Procyon decompilation test * * @ author https://github.com/niumoo * @ date 2021-05-15 * / public class ProcyonTest {public static void main (String [] args) throws IOException {Long time = procyon ("decompiler.jar", "procyon_output_jar"); System.out.println (String.format ("decompiler time:% dms", time)) } public static Long procyon (String source,String targetPath) throws IOException {long start = System.currentTimeMillis (); Path outDir = Paths.get (targetPath); Path archive = Paths.get (source); Decompiler dec = new ProcyonDecompiler (); DecompilationResult res = dec.decompileArchive (archive, outDir, new DecompilationListener () {public void decompilationProcessComplete () {System.out.println ("decompilationProcessComplete") } public void decompilationFailed (List inputPath, String message) {System.out.println ("decompilationFailed");} public void fileDecompiled (List inputPath, String outputPath) {} public boolean isCancelled () {return false;}}) If (! res.getFailures (). IsEmpty ()) {StringBuilder sb = new StringBuilder (); sb.append ("Failed decompilation of" + res.getFailures (). Size () + "classes:"); Iterator failureIterator = res.getFailures (). Iterator (); while (failureIterator.hasNext ()) {DecompilationFailure dex = (DecompilationFailure) failureIterator.next () Sb.append (System.lineSeparator () + ") .append (dex.getMessage ());} System.out.println (sb.toString ());} System.out.println (" Compilation results: "+ res.getDecompiledFiles (). Size () +" succeeded, "+ res.getFailures (). Size () +" failed. "); dec.close () Long end = System.currentTimeMillis (); return end-start;}}
Procyon outputs the progress of the number of decompiled files in real time when decompiling, and finally counts the number of Class files that have been decompiled successfully and failed.
.... May 15, 2021 10:58:28 afternoon org.jboss.windup.decompiler.procyon.ProcyonDecompiler$3 call message: Decompiling 2021 May 15, 2021 10:58:30 afternoon org.jboss.windup.decompiler.procyon.ProcyonDecompiler$3 call message: Decompiling 2021 May 15, 2021 10:58:37 afternoon org.jboss.windup.decompiler.procyon.ProcyonDecompiler$3 call message: Decompiling 750783 decompilationProcessComplete Compilation results: 2021 succeeded, 0 failed. Decompiler time: 40599msProcyon GUI
For Procyon decompilation, there is also an open source GUI interface based on this implementation on GitHub, which you can download if you are interested.
Github address: https://github.com/deathmarine/Luyten
CFR
GitHub address: https://github.com/leibnitz27/cfr
CFR official website: http://www.benf.org/other/cfr/( may need FQ)
Maven warehouse: https://mvnrepository.com/artifact/org.benf/cfr
CFR (Class File Reader) can support decompilation of Java 9, Java 12, Java 14, and other latest versions of Java code. And the code of CFR itself is written by Java 6, so you can basically use CFR in any version of Java program. It is worth mentioning that using CFR, you can even decompile JVM class files written in other languages back to Java files.
CFR command line usin
When using CFR decompilation, you can download the released JAR package and decompile it on the command line, or you can use it in your code in the way introduced by Maven. Let's start with how the command line runs.
Download the latest version of JAR directly from GitHub Tags. You can run directly to view help.
# View help java-jar cfr-0.151.jar-- help
If you are just decompiling some class.
# decompile the class file, output the result to the console java-jar cfr-0.151.jar WindupClasspathTypeLoader.class # decompiled class file, and output the result to the out folder java-jar cfr-0.151.jar WindupClasspathTypeLoader.class-- outputpath. / out
Decompile some JAR.
# decompile the jar file, and output the result to the output_jar folder ➜Desktop java-jar cfr-0.151.jar decompiler.jar-- outputdir. / output_jar Processing decompiler.jar (use silent to silence) Processing com.strobel.assembler.metadata.ArrayTypeLoader Processing com.strobel.assembler.metadata.ParameterDefinition Processing com.strobel.assembler.metadata.MethodHandle Processing com.strobel.assembler.metadata.signatures.FloatSignature
The decompiled results are written to the specified folder according to the package path of class.
Used in CFR code
Adding dependencies is not mentioned here.
Org.benf cfr 0.151
I don't actually see any specific examples of unit tests on the official website or on GitHub. But it doesn't matter, now that you can run it on the command line, you can write your own unit tests by directly looking at the decompiled Main method entry in IDEA to see how the command line is executed.
Package com.wdbyte.decompiler; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.benf.cfr.reader.api.CfrDriver; import org.benf.cfr.reader.util.getopt.OptionsImpl / * * CFRTest * * @ author https://github.com/niumoo * @ date 2021-05-15 * / public class CFRTest {public static void main (String [] args) throws IOException {Long time = cfr ("decompiler.jar", ". / cfr_output_jar"); System.out.println (String.format ("decompiler time:% dms", time)) / / decompiler time: 11655ms} public static Long cfr (String source, String targetPath) throws IOException {Long start = System.currentTimeMillis (); / / source jar List files = new ArrayList (); files.add (source); / / target dir HashMap outputMap = new HashMap (); outputMap.put ("outputdir", targetPath); OptionsImpl options = new OptionsImpl (outputMap) CfrDriver cfrDriver = new CfrDriver.Builder (). WithBuiltOptions (options). Build (); cfrDriver.analyse (files); Long end = System.currentTimeMillis (); return (end-start);}} JD-Core
GiHub address: https://github.com/java-decompiler/jd-core
JD-core official website: https://java-decompiler.github.io/
JD-core is a stand-alone Java library that can be used for Java decompilation, supporting bytecode decompilation from Java 1 to Java 12, including Lambda expressions, mode references, default methods, and so on. The well-known JD-GUI and Eclipse seamless integration decompilation engine is JD-core. JD-core provides some core decompilation functions, as well as separate Class decompilation methods, but if you want to decompile the entire JAR package directly in your own code, you still need some modifications. If there are anonymous functions, Lambda, etc., in the code, you can decompile directly, but you also need additional consideration.
Using JD-core org.jd jd-core 1.1.3
In order to decompile the entire JAR package, I have made some simple modifications to the code to facilitate the last part of the comparison test, but this example does not take into account the internal class, Lambda and so on will compile multiple Class files, so it can not be directly used in production.
Package com.wdbyte.decompiler; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Enumeration; import java.util.HashMap; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.jd.core.v1.ClassFileToJavaSourceDecompiler Import org.jd.core.v1.api.loader.Loader; import org.jd.core.v1.api.printer.Printer; / * * @ author https://github.com/niumoo * @ date 2021-05-15 * / public class JDCoreTest {public static void main (String [] args) throws Exception {JDCoreDecompiler jdCoreDecompiler = new JDCoreDecompiler (); Long time = jdCoreDecompiler.decompiler ("decompiler.jar", "jd_output_jar") System.out.println (String.format ("decompiler time:% dms", time));}} class JDCoreDecompiler {private ClassFileToJavaSourceDecompiler decompiler = new ClassFileToJavaSourceDecompiler (); / / stores the bytecode private HashMap classByteMap = new HashMap (); / * Note: multiple Class files compiled by one Java class are not considered. * * @ param source * @ param target * @ return * @ throws Exception * / public Long decompiler (String source,String target) throws Exception {long start = System.currentTimeMillis (); / / decompress archive (source); for (String className: classByteMap.keySet ()) {String path = StringUtils.substringBeforeLast (className, "/") String name = StringUtils.substringAfterLast (className, "/"); if (StringUtils.contains (name, "$") {name = StringUtils.substringAfterLast (name, "$");} name = StringUtils.replace (name, ".class", ".java"); decompiler.decompile (loader, printer, className); String context = printer.toString () Path targetPath = Paths.get (target + "/" + path + "/" + name); if (! Files.exists (Paths.get (target + "/" + path) {Files.createDirectories (Paths.get (target + "/" + path));} Files.deleteIfExists (targetPath); Files.createFile (targetPath) Files.write (targetPath, context.getBytes ());} return System.currentTimeMillis ()-start;} private void archive (String path) throws IOException {try (ZipFile archive = new JarFile (new File (path) {Enumeration
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.