最近开始学习IntelliJ插件开发,于是就把之前维护的一款 反编译插件 重新实现了一个版本,并且加入了javap指令的支持,对于理解Java class文件有着不错的帮助。
源码: https://github.com/work-helper/class-decompile-intellij
JB插件地址: https://plugins.jetbrains.com/plugin/13914-class-decompile
插件的使用很简单,对着Java,Kotlin等JVM上语言文件或者是class文件点击右键,选择 Show Decompile Code
,即可反编译对应的class文件,如下图所示:
javap
是JDK自带的反编译工具,因此支持需要依赖 External Tools
功能支持,如下图所示在对应菜单中配置javap命令入口,插件则会自动调用对应的javap指令进行反编译。
反编译能够还原语法糖的实现,帮助你更好的理解编程语言的本质。比如kotlin下的 object class
,反编译后可以很好的理解单例实现。
object UserService { }
import kotlin.Metadata; @Metadata(mv={1, 1, 16}, bv={1, 0, 3}, k=1, d1={"。。。。"}) public final class UserService { public static final UserService INSTANCE; private UserService() { } static { UserService userService; INSTANCE = userService = new UserService(); } }
在插件javap指令参数配置上增加 -p -v
,那么反编译能够打印出对应的class文件信息,你可以很清楚的了解的class文件由哪几部分构成。
object UserService { }
public final class cn.mrdear.test.UserService minor version: 0 major version: 50 flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER Constant pool: #1 = Utf8 cn/mrdear/test/UserService #2 = Class #1 // cn/mrdear/test/UserService #3 = Utf8 java/lang/Object #4 = Class #3 // java/lang/Object #5 = Utf8 <init> ...... { public static final cn.mrdear.test.UserService INSTANCE; descriptor: Lcn/mrdear/test/UserService; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL private cn.mrdear.test.UserService(); descriptor: ()V flags: ACC_PRIVATE Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #8 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 8: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcn/mrdear/test/UserService; static {}; descriptor: ()V flags: ACC_STATIC Code: stack=2, locals=1, args_size=0 0: new #2 // class cn/mrdear/test/UserService 3: dup 4: invokespecial #26 // Method "<init>":()V // Field INSTANCE:Lcn/mrdear/test LineNumberTable: line 8: 0 } SourceFile: "UserService.kt" RuntimeVisibleAnnotations: 0: #13(#14=[I#15,I#15,I#16],#17=[I#15,I#18,I#19],#20=I#15,#21=[s#22],#23=[s#10,s#24,s#6,s#25])
反编译后能够查看到对应的字节码操作,了解 dup,ldc,invokespecial,astore_0
等相应字节码在JVM上起到的具体作用。
反编译前
object UserService { }
public final class cn/mrdear/test/UserService { // compiled from: UserService.kt @Lkotlin/Metadata;(mv={1, 1, 16}, bv={1, 0, 3}, k=1, d1={"。。。。 "class-decompile-intellij.main"}) // access flags 0x19 public final static Lcn/mrdear/test/UserService; INSTANCE // access flags 0x2 private <init>()V L0 LINENUMBER 8 L0 ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V RETURN L1 LOCALVARIABLE this Lcn/mrdear/test/UserService; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x8 static <clinit>()V L0 LINENUMBER 8 L0 NEW cn/mrdear/test/UserService DUP INVOKESPECIAL cn/mrdear/test/UserService.<init> ()V ASTORE 0 ALOAD 0 PUTSTATIC cn/mrdear/test/UserService.INSTANCE : Lcn/mrdear/test/UserService; RETURN MAXSTACK = 2 MAXLOCALS = 1 }
废话不多说,赶快去使用吧。
V2ray -- 使用Cloudflare CDN加速访问