概述

纸上得来终觉浅,绝知此事要躬行,今天就动手实现一个jdk自带的工具javap

  • 阅读本文可以带你完整的自己实现javap的全部功能
  • 本文只提到了核心代码,完整代码git地址请访问:https://github.com/lzc-alioo/itstack-demo-jvm
  • 项目访问入口类是com.lzc.wuxin.Jad1,com.lzc.wuxin.Jad2,将分别代表javap,javap -v的实现逻辑,如果你在运行过程中有任何问题欢迎留言,看到后一定为你解答,同时如果你发现代码的缺陷,也欢迎提交issue或者直接提交pr。
  • 本文的创作是建立在github中一个已经开源的项目基础上进行的,源项目地址为:itstack-demo-jvm (https://github.com/fuzhengwei/itstack-demo-jvm)

准备工作

用来测试的java文件 HelloWorld.java

package com.lzc.wuxin.demo;public class HelloWorld {private final static byte abc = -14;private final static Byte abc2 = Byte.valueOf((byte) -15);private static int lzc;public static void main(String[] args) {int lzc2 = 2;int lzc3 = 3;int lzc4 = lzc2 + lzc3;}}

javap VS jad1

javap效果

javap com.lzc.wuxin.demo.HelloWorld
Compiled from "HelloWorld.java"
public class com.lzc.wuxin.demo.HelloWorld {public com.lzc.wuxin.demo.HelloWorld();public static void main(java.lang.String[]);static {};
}

jad1效果

Compiled from "HelloWorld.java" (反编译工具作者:Lzc)
public class com.lzc.wuxin.demo.HelloWorld {private static final byte abc = -14;private static final Byte abc2;private static int lzc;public HelloWorld();public static void main(String[]);static {};
}

jad1相应的源码

public static void deCompile(Cmd cmd) {Classpath classpath = new Classpath(cmd.jre, cmd.classpath);ClassLoader classLoader = new ClassLoader(classpath);String className =  cmd.getMainClass().replace(".", "/");String simpleClassName = className.substring(className.lastIndexOf("/") + 1);System.out.println("Compiled from \"" + simpleClassName + ".java\" (反编译工具作者:Lzc)");Class clazz = classLoader.loadClass(className);StringBuilder buf = new StringBuilder();buf.append(clazz.deprecated ? "@Deprecated " : "").append(AccessFlagsUtil.getAccessFlagsStr(clazz.accessFlags)).append(className).append(" {\n");for (Field memberInfo : clazz.fields) {Object val = ValueUtil.getValue(memberInfo, clazz);buf.append("    ").append(memberInfo.deprecated ? "@Deprecated " : "").append(AccessFlagsUtil.getAccessFlagsStr(memberInfo.accessFlags)).append(FieldDescriptorUtil.getDescriptorStr(memberInfo.descriptor())).append(memberInfo.name()).append(Optional.ofNullable(val).map(tmp -> " = " + tmp).orElse("")).append(";\n");}buf.append("\n");for (Method memberInfo : clazz.methods) {//方法参数类型 方法返回值类型MethodInfo methodInfo = MethodDescriptorUtil.getMethodInfo(memberInfo);buf.append("    ").append(memberInfo.deprecated ? "@Deprecated " : "").append(AccessFlagsUtil.getAccessFlagsStr(memberInfo.accessFlags)).append(methodInfo.getValueType()).append(methodInfo.getMethodName()).append(methodInfo.getParamType()).append(";\n");}buf.append("}");System.out.println(buf.toString());
}

javap -v VS jad2

javap -v效果

javap -v com.lzc.wuxin.demo.HelloWorld
Classfile /Users/mac/work/gitstudy/itstack-demo-jvm/itstack-lzc/target/test-classes/com/lzc/wuxin/demo/HelloWorld.classLast modified 2022-4-17; size 711 bytesMD5 checksum 17e695fb34c8c10f716ac6e92c8609f1Compiled from "HelloWorld.java"
public class com.lzc.wuxin.demo.HelloWorldminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref          #5.#31         // java/lang/Object."<init>":()V#2 = Methodref          #32.#33        // java/lang/Byte.valueOf:(B)Ljava/lang/Byte;#3 = Fieldref           #4.#34         // com/lzc/wuxin/demo/HelloWorld.abc2:Ljava/lang/Byte;#4 = Class              #35            // com/lzc/wuxin/demo/HelloWorld#5 = Class              #36            // java/lang/Object#6 = Utf8               abc#7 = Utf8               B#8 = Utf8               ConstantValue#9 = Integer            -14#10 = Utf8               abc2#11 = Utf8               Ljava/lang/Byte;#12 = Utf8               lzc#13 = Utf8               I#14 = Utf8               <init>#15 = Utf8               ()V#16 = Utf8               Code#17 = Utf8               LineNumberTable#18 = Utf8               LocalVariableTable#19 = Utf8               this#20 = Utf8               Lcom/lzc/wuxin/demo/HelloWorld;#21 = Utf8               main#22 = Utf8               ([Ljava/lang/String;)V#23 = Utf8               args#24 = Utf8               [Ljava/lang/String;#25 = Utf8               lzc2#26 = Utf8               lzc3#27 = Utf8               lzc4#28 = Utf8               <clinit>#29 = Utf8               SourceFile#30 = Utf8               HelloWorld.java#31 = NameAndType        #14:#15        // "<init>":()V#32 = Class              #37            // java/lang/Byte#33 = NameAndType        #38:#39        // valueOf:(B)Ljava/lang/Byte;#34 = NameAndType        #10:#11        // abc2:Ljava/lang/Byte;#35 = Utf8               com/lzc/wuxin/demo/HelloWorld#36 = Utf8               java/lang/Object#37 = Utf8               java/lang/Byte#38 = Utf8               valueOf#39 = Utf8               (B)Ljava/lang/Byte;
{public com.lzc.wuxin.demo.HelloWorld();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 3: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       5     0  this   Lcom/lzc/wuxin/demo/HelloWorld;public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=4, args_size=10: iconst_21: istore_12: iconst_33: istore_24: iload_15: iload_26: iadd7: istore_38: returnLineNumberTable:line 10: 0line 11: 2line 12: 4line 13: 8LocalVariableTable:Start  Length  Slot  Name   Signature0       9     0  args   [Ljava/lang/String;2       7     1  lzc2   I4       5     2  lzc3   I8       1     3  lzc4   Istatic {};descriptor: ()Vflags: ACC_STATICCode:stack=1, locals=0, args_size=00: bipush        -152: invokestatic  #2                  // Method java/lang/Byte.valueOf:(B)Ljava/lang/Byte;5: putstatic     #3                  // Field abc2:Ljava/lang/Byte;8: returnLineNumberTable:line 6: 0
}
SourceFile: "HelloWorld.java"

jad2效果

Classfile       : /Users/mac/work/gitstudy/itstack-demo-jvm/itstack-lzc/target/test-classes/com/lzc/wuxin/demo/HelloWorld.classLast modified : 2022-04-17; size 711 bytesMD5 checksum  : 17e695fb34c8c10f716ac6e92c8609f1Compiled from : HelloWorld.java" (反编译工具作者:Lzc)
public class com.lzc.wuxin.demo.HelloWorldminor version: 0major version: 52flags        : public class
Constant pool:#0 = null#1 = MethodRef           #0.#0                         // java/lang/Object.<init>:()V          #2 = MethodRef           #0.#0                         // java/lang/Byte.valueOf:(B)Ljava/lang/Byte;#3 = FieldRef            #0.#0                         // com/lzc/wuxin/demo/HelloWorld.abc2:Ljava/lang/Byte;#4 = ClassRef            #0                            // com/lzc/wuxin/demo/HelloWorld        #5 = ClassRef            #0                            // java/lang/Object                     #6 = Utf8                abc                           #7 = Utf8                B                             #8 = Utf8                ConstantValue                 #9 = Integer             -14                           #10 = Utf8                abc2                          #11 = Utf8                Ljava/lang/Byte;              #12 = Utf8                lzc                           #13 = Utf8                I                             #14 = Utf8                <init>                        #15 = Utf8                ()V                           #16 = Utf8                Code                          #17 = Utf8                LineNumberTable               #18 = Utf8                LocalVariableTable            #19 = Utf8                this                          #20 = Utf8                Lcom/lzc/wuxin/demo/HelloWorld;#21 = Utf8                main                          #22 = Utf8                ([Ljava/lang/String;)V        #23 = Utf8                args                          #24 = Utf8                [Ljava/lang/String;           #25 = Utf8                lzc2                          #26 = Utf8                lzc3                          #27 = Utf8                lzc4                          #28 = Utf8                <clinit>                      #29 = Utf8                SourceFile                    #30 = Utf8                HelloWorld.java               #31 = NameAndType         #14:#15                       // <init>:()V                           #32 = ClassRef            #0                            // java/lang/Byte                       #33 = NameAndType         #38:#39                       // valueOf:(B)Ljava/lang/Byte;          #34 = NameAndType         #10:#11                       // abc2:Ljava/lang/Byte;                #35 = Utf8                com/lzc/wuxin/demo/HelloWorld #36 = Utf8                java/lang/Object              #37 = Utf8                java/lang/Byte                #38 = Utf8                valueOf                       #39 = Utf8                (B)Ljava/lang/Byte;
{private static final byte abc = -14;private static final Byte abc2;private static int lzc;public HelloWorld();descriptor:()Vflags: public class Code: stack=1, locals=1, args_size=1aload_0invoke_specialnopaconst_nullreturnLineNumberTable:line 3: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       5     0  this   Lcom/lzc/wuxin/demo/HelloWorld;public static void main(String[]);descriptor:([Ljava/lang/String;)Vflags: public class Code: stack=2, locals=4, args_size=1iconst_2istore_1iconst_3istore_2iload_1iload_2iaddistore_3returnLineNumberTable:line 10: 0line 11: 2line 12: 4line 13: 8LocalVariableTable:Start  Length  Slot  Name   Signature0       9     0  args   [Ljava/lang/String;2       7     1  lzc2   I             4       5     2  lzc3   I             8       1     3  lzc4   I             static {};descriptor:()Vflags: public class Code: stack=1, locals=0, args_size=0bipushunkowninvoke_staticnopiconst_m1put_staticnopiconst_0returnLineNumberTable:line 6: 0LocalVariableTable:Start  Length  Slot  Name   Signature
}

jad2相应的源码

    public static void deCompile(Cmd cmd) {String className = cmd.getMainClass().replace(".", "/");String simpleClassName = className.substring(className.lastIndexOf("/") + 1);ClassInfo classInfo = null;try {classInfo = new Classpath(cmd.jre, cmd.classpath).readClass2ClassInfo(className);} catch (Exception e) {e.printStackTrace();return;}System.out.println(StringUtils.rightPad("Classfile", 16) + ": " + classInfo.classFromPath);System.out.println(StringUtils.rightPad("  Last modified ", 16) + ": " + DateTimeUtil.toDateTimeString(classInfo.lastModified, "yyyy-MM-dd") + "; size " + classInfo.length + " bytes");System.out.println(StringUtils.rightPad("  MD5 checksum ", 16) + ": " + classInfo.md5);System.out.println(StringUtils.rightPad("  Compiled from ", 16) + ": " + simpleClassName + ".java\" (反编译工具作者:Lzc)");Classpath classpath = new Classpath(cmd.jre, cmd.classpath);ClassLoader classLoader = new ClassLoader(classpath);Class clazz = classLoader.loadClass(className);StringBuilder buf = new StringBuilder();buf.append(clazz.deprecated ? "@Deprecated " : "").append(AccessFlagsUtil.getAccessFlagsStr(clazz.accessFlags)).append(cmd.getMainClass()).append("\n");buf.append("  minor version: ").append(classInfo.classFile.minorVersion()).append("\n");buf.append("  major version: ").append(classInfo.classFile.majorVersion()).append("\n");buf.append("  flags        : ").append(AccessFlagsUtil.getAccessFlagsStr(clazz.accessFlags)).append("\n");System.out.print(buf.toString());buf.delete(0, buf.length());buf.append("Constant pool:\n");Object[] constants = clazz.constantPool().constants;for (int i = 0; i < constants.length; i++) {//   #1 = Methodref          #5.#34         // java/lang/Object."<init>":()Vbuf.append(StringUtils.leftPad("#" + i, 4)).append(" = ");buf.append(ConstantPoolUtil.readableConstant(constants[i]));buf.append("\n");}System.out.print(buf.toString());buf.delete(0, buf.length());buf.append("{\n");for (Field memberInfo : clazz.fields) {Object val = ValueUtil.getValue(memberInfo, clazz);buf.append("  ").append(memberInfo.deprecated ? "@Deprecated " : "").append(AccessFlagsUtil.getAccessFlagsStr(memberInfo.accessFlags)).append(FieldDescriptorUtil.getDescriptorStr(memberInfo.descriptor())).append(memberInfo.name()).append(Optional.ofNullable(val).map(tmp -> " = " + tmp).orElse("")).append(";\n");}buf.append("\n");for (Method method : clazz.methods) {//方法参数类型 方法返回值类型MethodInfo methodInfo = MethodDescriptorUtil.getMethodInfo(method);buf.append("  ").append(AccessFlagsUtil.getAccessFlagsStr(method.accessFlags)).append(methodInfo.getValueType()).append(methodInfo.getMethodName()).append(methodInfo.getParamType()).append(";\n");buf.append("    descriptor:").append(method.descriptor).append("\n");buf.append("    flags: ").append(AccessFlagsUtil.getAccessFlagsStr(clazz.accessFlags)).append("\n");buf.append("    Code: ").append("\n");buf.append("      stack=").append(method.maxStack).append(", locals=").append(method.maxLocals).append(", args_size=").append(method.argSlotCount()).append("\n");for (byte opcode : method.code) {Instruction inst = Factory.newInstruction(opcode);buf.append("        ").append(InstructionUtil.readableInstruction(inst).toLowerCase()).append("\n");}buf.append("      LineNumberTable:").append("\n");for (LineNumberTableAttribute.LineNumberTableEntry lineNumber : method.lineNumberTableAttribute.lineNumberTable) {buf.append("        line ").append(lineNumber.lineNumber).append(": ").append(lineNumber.startPC).append("\n");}buf.append("      LocalVariableTable:").append("\n");buf.append("        Start  Length  Slot  Name   Signature").append("\n");if(method.localVariableTableAttribute!=null && method.localVariableTableAttribute.localVariableTable!=null){for (LocalVariableTableAttribute.LocalVariableTableEntry localVar : method.localVariableTableAttribute.localVariableTable) {buf.append(StringUtils.leftPad(localVar.startPC + "", 13)).append(StringUtils.leftPad(localVar.length + "", 8)).append(StringUtils.leftPad(localVar.idx + "", 6)).append(StringUtils.leftPad(clazz.runTimeConstantPool.getConstants(localVar.nameIdx) + "", 6)).append("   ").append(StringUtils.rightPad(clazz.runTimeConstantPool.getConstants(localVar.descriptorIdx)+"" , 14)).append("\n");}}}buf.append("}");System.out.println(buf.toString());}

自己动手实现javap相关推荐

  1. 【性能优化方法论系列】三、性能优化的核心思想(1)

    性能优化方法论系列目录 <一.性能优化的本质> <二.性能优化方法论的思想源泉> <三.性能优化的核心思想(1)> <三.性能优化的核心思想(2)> & ...

  2. java 手编线程池_死磕 java线程系列之自己动手写一个线程池

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...

  3. JAVA课上动手动脑问题以及课后测试1,2总结

    课堂测试1      像二柱子那样,花二十分钟写一个能自动生成30道小学四则运算题目的 "软件" 2    (1)题目避免重复 (2)可定制(数量/打印方式) 设计思路 1)产生两 ...

  4. 5,ORM组件XCode(动手)

    本篇才真正是XCode教程第一篇.<速览>是为了以最简洁的语言最短小的篇幅去吸引开发者:<简介>则是对XCode组件和XCode开发模式的一个整体介绍,让开发者从宏观的角度去理 ...

  5. 开关面板如何自己印字_如何自己动手做一个智能开关

    现在的智能家居这么火,对于想自己动手的小伙伴们来说,都想自己去做一些家里使用 的智设备.现在的中国不缺卖唱卖惨的,缺的是能动手创造一些能实际使用的而不是哗众取宠的人,天天喊着要反击外国技术封锁.那么我 ...

  6. OpenCV和Python动手操作计算机视觉学习教程

    使用OpenCV和Python进行实际操作 面向初学者的OpenCV Python动手操作计算机视觉 你会学到: NumPy基础知识 基于OpenCV的人脸检测 使用OpenCV在图像和视频上绘制形状 ...

  7. 自己动手重新实现LINQ to Objects: 9 - SelectMany

    本文翻译自Jon Skeet的系列博文"Edulinq". 本篇原文地址: http://msmvps.com/blogs/jon_skeet/archive/2010/12/27 ...

  8. 一阶微分算子锐化图像_【动手学计算机视觉】第三讲:图像预处理之图像分割...

    本讲完整代码>> 前言 图像分割是一种把图像分成若干个独立子区域的技术和过程.在图像的研究和应用中,很多时候我们关注的仅是图像中的目标或前景(其他部分称为背景),它们对应图像中特定的.具有 ...

  9. 自己动手,打造轻量级VSCode/C#环境代替LinqPad

    .Net 的项目都挺重的,一直想找一个轻量级的 CSharp 环境,能像Python那样,选一个文件就能跑的.之前用的是 LinqPad,但它的缺点也很明显: (1)     不付费,自动完成不能用( ...

最新文章

  1. 如何优化网站结构才促使网站排名“节节高”?
  2. 学php需要哪些基础,学习php需要什么基础?(附php学习路线图)
  3. java a3 套打印_Java - apache PDFBox兩個A3論文到一個A2?
  4. 最佳实践:如何基于MNS和OSS实现无大小限制的消息传输
  5. WebStorm中Node.js项目配置教程(1)——创建项目
  6. LeetCode 208. Implement Trie (Prefix Tree)
  7. yii2在linux下面无法启用gii
  8. web前端的十种jquery特效及源码下载
  9. mybatis-plus中的select
  10. 华师本科网络英语 计算机统考,2020华中师大计算机考研经验帖(已上岸)
  11. 3.2、如何通过JLINK下载程序(附JLINK驱动)
  12. SQL查询语句的基本使用方法
  13. python打印菱形_python打印菱形
  14. 如何远程控制别人的无线鼠标
  15. Ubuntu桌面版高版本无法更新软件:Unmet Dependencies
  16. 一加8T,一加8和一加8Pro有什么区别哪个好?分析优缺点?
  17. Paper reading (九十一):Bifidobacterium breve Bif195 Protects Against Small-Intestinal Damage
  18. I2C总线读取MPU6050
  19. 算法刷题(蓝)【基础篇+算法篇】【Python版】
  20. java png生成webp图片_jpg、png格式的图片转换成webp后颜色失真的问题

热门文章

  1. python之json序列化与反序列化
  2. Android 利用ReplacementSpan打造纯文本填空题(附源码)
  3. java黄油刀_使用ButterKnife (黄油刀报错)
  4. 从SRCNN到EDSR,总结深度学习端到端超分辨率方法发展历程
  5. AI时代已来,我们该如何培养创造力
  6. 5.19 go time实现延时功能
  7. 关于stimusoft report 报表一行记录有的高度高,有的高度低,错落的问题解决
  8. 【整理】蛋白样品制备方法学评估
  9. 集线器hub、交换机switch、路由器router 的区别
  10. excel分类_利用Excel快速进行SEO关键词分类