自己动手实现javap
概述
纸上得来终觉浅,绝知此事要躬行,今天就动手实现一个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)> <三.性能优化的核心思想(2)> & ...
- java 手编线程池_死磕 java线程系列之自己动手写一个线程池
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...
- JAVA课上动手动脑问题以及课后测试1,2总结
课堂测试1 像二柱子那样,花二十分钟写一个能自动生成30道小学四则运算题目的 "软件" 2 (1)题目避免重复 (2)可定制(数量/打印方式) 设计思路 1)产生两 ...
- 5,ORM组件XCode(动手)
本篇才真正是XCode教程第一篇.<速览>是为了以最简洁的语言最短小的篇幅去吸引开发者:<简介>则是对XCode组件和XCode开发模式的一个整体介绍,让开发者从宏观的角度去理 ...
- 开关面板如何自己印字_如何自己动手做一个智能开关
现在的智能家居这么火,对于想自己动手的小伙伴们来说,都想自己去做一些家里使用 的智设备.现在的中国不缺卖唱卖惨的,缺的是能动手创造一些能实际使用的而不是哗众取宠的人,天天喊着要反击外国技术封锁.那么我 ...
- OpenCV和Python动手操作计算机视觉学习教程
使用OpenCV和Python进行实际操作 面向初学者的OpenCV Python动手操作计算机视觉 你会学到: NumPy基础知识 基于OpenCV的人脸检测 使用OpenCV在图像和视频上绘制形状 ...
- 自己动手重新实现LINQ to Objects: 9 - SelectMany
本文翻译自Jon Skeet的系列博文"Edulinq". 本篇原文地址: http://msmvps.com/blogs/jon_skeet/archive/2010/12/27 ...
- 一阶微分算子锐化图像_【动手学计算机视觉】第三讲:图像预处理之图像分割...
本讲完整代码>> 前言 图像分割是一种把图像分成若干个独立子区域的技术和过程.在图像的研究和应用中,很多时候我们关注的仅是图像中的目标或前景(其他部分称为背景),它们对应图像中特定的.具有 ...
- 自己动手,打造轻量级VSCode/C#环境代替LinqPad
.Net 的项目都挺重的,一直想找一个轻量级的 CSharp 环境,能像Python那样,选一个文件就能跑的.之前用的是 LinqPad,但它的缺点也很明显: (1) 不付费,自动完成不能用( ...
最新文章
- 如何优化网站结构才促使网站排名“节节高”?
- 学php需要哪些基础,学习php需要什么基础?(附php学习路线图)
- java a3 套打印_Java - apache PDFBox兩個A3論文到一個A2?
- 最佳实践:如何基于MNS和OSS实现无大小限制的消息传输
- WebStorm中Node.js项目配置教程(1)——创建项目
- LeetCode 208. Implement Trie (Prefix Tree)
- yii2在linux下面无法启用gii
- web前端的十种jquery特效及源码下载
- mybatis-plus中的select
- 华师本科网络英语 计算机统考,2020华中师大计算机考研经验帖(已上岸)
- 3.2、如何通过JLINK下载程序(附JLINK驱动)
- SQL查询语句的基本使用方法
- python打印菱形_python打印菱形
- 如何远程控制别人的无线鼠标
- Ubuntu桌面版高版本无法更新软件:Unmet Dependencies
- 一加8T,一加8和一加8Pro有什么区别哪个好?分析优缺点?
- Paper reading (九十一):Bifidobacterium breve Bif195 Protects Against Small-Intestinal Damage
- I2C总线读取MPU6050
- 算法刷题(蓝)【基础篇+算法篇】【Python版】
- java png生成webp图片_jpg、png格式的图片转换成webp后颜色失真的问题
热门文章
- python之json序列化与反序列化
- Android 利用ReplacementSpan打造纯文本填空题(附源码)
- java黄油刀_使用ButterKnife (黄油刀报错)
- 从SRCNN到EDSR,总结深度学习端到端超分辨率方法发展历程
- AI时代已来,我们该如何培养创造力
- 5.19 go time实现延时功能
- 关于stimusoft report 报表一行记录有的高度高,有的高度低,错落的问题解决
- 【整理】蛋白样品制备方法学评估
- 集线器hub、交换机switch、路由器router 的区别
- excel分类_利用Excel快速进行SEO关键词分类