范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

IDEA的debug怎么实现?有人知道吗

  初学 Java 时,我对 IDEA 的 Debug 非常好奇,不止是它能查看断点的上下文环境,更神奇的是我可以在断点处使用它的 Evaluate 功能直接执行某些命令,进行一些计算或改变当前变量。
  刚开始语法不熟经常写错代码,重新打包部署一次代码耗时很长,我就直接面向 Debug 开发。在要编写的方法开始处打一个断点,在 Evaluate 框内一次次地执行方法函数不停地调整代码,没问题后再将代码复制出来放到 IDEA 里,再进行下一个方法的编写,这样就跟写 PHP 类似的解释性语言一样,写完即执行,非常方便。
  但 Java 是静态语言,运行之前是要先进行编译的,难道我写的这些代码是被实时编译又"注入"到我正在 Debug 的服务里了吗?
  随着对 Java 的愈加熟悉,我也了解了反射、字节码等技术,直到前些天的周会分享,有位同事分享了 Btrace 的使用和实现,提到了 Java 的 ASM 框架和 JVM TI 接口。Btrace 修改代码能力的实现与 Debug 的 Evaluate 有很多相似之处,这大大吸引了我。
  分享就像一个引子,从中学到的东西只是皮毛,要了解它还是要自己研究。于是自己查看资料并写代码学习了下其具体实现。 ASM
  实现 Evaluate 要解决的第一个问题就是怎么改变原有代码的行为,它的实现在 Java 里被称为动态字节码技术。 动态生成字节码
  我们知道,我们编写的 Java 代码都是要被编译成字节码后才能放到 JVM 里执行的,而字节码一旦被加载到虚拟机中,就可以被解释执行。
  字节码文件(.class)就是普通的二进制文件,它是通过 Java 编译器生成的。而只要是文件就可以被改变,如果我们用特定的规则解析了原有的字节码文件,对它进行修改或者干脆重新定义,这不就可以改变代码行为了么。
  Java 生态里有很多可以动态生成字节码的技术,像 BCEL、Javassist、ASM、CGLib 等,它们各有自己的优势。有的使用复杂却功能强大、有的简单确也性能些差。 ASM 框架
  ASM 是它们中最强大的一个,使用它可以动态修改类、方法,甚至可以重新定义类,连 CGLib 底层都是用 ASM 实现的。
  当然,它的使用门槛也很高,使用它需要对 Java 的字节码文件有所了解,熟悉 JVM 的编译指令。虽然我对 JVM 的字节码语法不熟,但有大神开发了可以在 IDEA 里查看字节码的插件:ASM Bytecode Outline ,在要查看的类文件里右键选择 Show bytecode Outline 即可以右侧的工具栏查看我们要生成的字节码。对照着示例,我们就可以很轻松地写出操作字节码的 Java 代码了。
  而切到 ASMified 标签栏,我们甚至可以直接获取到 ASM 的使用代码。
  常用方法
  在 ASM 的代码实现里,最明显的就是访问者模式,ASM 将对代码的读取和操作都包装成一个访问者,在解析 JVM 加载到的字节码时调用。
  ClassReader 是 ASM 代码的入口,通过它解析二进制字节码,实例化时它时,我们需要传入一个 ClassVisitor,在这个 Visitor 里,我们可以实现 visitMethod()/visitAnnotation() 等方法,用以定义对类结构(如方法、字段、注解)的访问方法。
  而 ClassWriter 接口继承了 ClassVisitor 接口,我们在实例化类访问器时,将 ClassWriter "注入" 到里面,以实现对类写入的声明。 Instrument
  介绍
  字节码是修改完了,可是 JVM 在执行时会使用自己的类加载器加载字节码文件,加载后并不会理会我们做出的修改,要想实现对现有类的修改,我们还需要搭配 Java 的另一个库 instrument。
  instrument 是 JVM 提供的一个可以修改已加载类文件的类库。1.6以前,instrument 只能在 JVM 刚启动开始加载类时生效,之后,instrument 更是支持了在运行时对类定义的修改。 使用
  要使用 instrument 的类修改功能,我们需要实现它的 ClassFileTransformer 接口定义一个类文件转换器。它唯一的一个 transform() 方法会在类文件被加载时调用,在 transform 方法里,我们可以对传入的二进制字节码进行改写或替换,生成新的字节码数组后返回,JVM 会使用 transform 方法返回的字节码数据进行类的加载。 JVM TI
  定义完了字节码的修改和重定义方法,但我们怎么才能让 JVM 能够调用我们提供的类转换器呢?这里又要介绍到 JVM TI 了。 介绍
  JVM TI(JVM Tool Interface)JVM 工具接口是 JVM 提供的一个非常强大的对 JVM 操作的工具接口,通过这个接口,我们可以实现对 JVM 多种组件的操作,从JVMTM Tool Interface 这里我们认识到 JVM TI 的强大,它包括了对虚拟机堆内存、类、线程等各个方面的管理接口。
  JVM TI 通过事件机制,通过接口注册各种事件勾子,在 JVM 事件触发时同时触发预定义的勾子,以实现对各个 JVM 事件的感知和反应。 Agent
  Agent 是 JVM TI 实现的一种方式。我们在编译 C 项目里链接静态库,将静态库的功能注入到项目里,从而才可以在项目里引用库里的函数。我们可以将 agent 类比为 C 里的静态库,我们也可以用 C 或 C++ 来实现,将其编译为 dll 或 so 文件,在启动 JVM 时启动。
  这时再来思考 Debug 的实现,我们在启动被 Debug 的 JVM 时,必须添加参数 -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:3333,而 -agentlib 选项就指定了我们要加载的 Java Agent,jdwp 是 agent 的名字,在 linux 系统中,我们可以在 jre 目录下找到 jdwp.so 库文件。
  Java 的调试体系 jdpa 组成,从高到低分别为 jdi->jdwp->jvmti,我们通过 JDI 接口发送调试指令,而 jdwp 就相当于一个通道,帮我们翻译 JDI 指令到 JVM TI,最底层的 JVM TI 最终实现对 JVM 的操作。 使用
  JVM TI 的 agent 使用很简单,在启动 agent 时添加 -agent 参数指定我们要加载的 agent jar包即可。
  而要实现代码的修改,我们需要实现一个 instrument agent,它可以通过在一个类里添加 premain() 或 agentmain() 方法来实现。而要实现 1.6 以上的动态 instrument 功能,实现 agentmain 方法即可。
  在 agentmain 方法里,我们调用 Instrumentation.retransformClasses() 方法实现对目标类的重定义。
  另外往一个正在运行的 JVM 里动态添加 agent,还需要用到 JVM 的 attach 功能,Sun 公司的 tools.jar 包里包含的 VirtualMachine 类提供了 attach 一个本地 JVM 的功能,它需要我们传入一个本地 JVM 的 pid, tools.jar 可以在 jre 目录下找到。 agent生成
  另外,我们还需要注意 agent 的打包,它需要指定一个 Agent-Class 参数指定我们的包括 agentmain 方法的类,可以算是指定入口类吧。
  此外,还需要配置 MANIFEST.MF 文件的一些参数,允许我们重新定义类。如果你的 agent 实现还需要引用一些其他类库时,还需要将这些类库都打包到此 jar 包中,下面是我的 pom 文件配置。                                        org.apache.maven.plugins                 maven-assembly-plugin                                                                                            asm.TestAgent                             true                             true                             1.0                             all-permissions                                                                                            jar-with-dependencies                                                                 
  另外在打包时需要使用 mvn assembly:assembl 命令生成 jar-with-dependencies 作为 agent。 代码实现
  我在测试时写了一个用以上技术实现了一个简单的字节码动态修改的 Demo。 被修改的类
  TransformTarget 是要被修改的目标类,正常执行时,它会三秒输出一次 "hello"。 public class TransformTarget {     public static void main(String[] args) {         while (true) {             try {                 Thread.sleep(3000L);             } catch (Exception e) {                 break;             }             printSomething();         }     }       public static void printSomething() {         System.out.println("hello");     }   }
  Agent
  Agent 是执行修改类的主体,它使用 ASM 修改 TransformTarget 类的方法,并使用 instrument 包将修改提交给 JVM。
  入口类,也是代理的 Agent-Class。 public class TestAgent {     public static void agentmain(String args, Instrumentation inst) {         inst.addTransformer(new TestTransformer(), true);         try {             inst.retransformClasses(TransformTarget.class);             System.out.println("Agent Load Done.");         } catch (Exception e) {             System.out.println("agent load failed!");         }     } }
  执行字节码修改和转换的类。 public class TestTransformer implements ClassFileTransformer {       public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {         System.out.println("Transforming " + className);         ClassReader reader = new ClassReader(classfileBuffer);         ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);         ClassVisitor classVisitor = new TestClassVisitor(Opcodes.ASM5, classWriter);         reader.accept(classVisitor, ClassReader.SKIP_DEBUG);         return classWriter.toByteArray();     }       class TestClassVisitor extends ClassVisitor implements Opcodes {         TestClassVisitor(int api, ClassVisitor classVisitor) {             super(api, classVisitor);         }           @Override         public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {             MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);             if (name.equals("printSomething")) {                 mv.visitCode();                 Label l0 = new Label();                 mv.visitLabel(l0);                 mv.visitLineNumber(19, l0);                 mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");                 mv.visitLdcInsn("bytecode replaced!");                 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);                 Label l1 = new Label();                 mv.visitLabel(l1);                 mv.visitLineNumber(20, l1);                 mv.visitInsn(Opcodes.RETURN);                 mv.visitMaxs(2, 0);                 mv.visitEnd();                 TransformTarget.printSomething();             }             return mv;         }     } }
  Attacher
  使用 tools.jar 里方法将 agent 动态加载到目标 JVM 的类。 public class Attacher {     public static void main(String[] args) throws AttachNotSupportedException, IOException, AgentLoadException, AgentInitializationException {           VirtualMachine vm = VirtualMachine.attach("34242"); // 目标 JVM pid         vm.loadAgent("/path/to/agent.jar");     } }
  这样,先启动 TransformTarget 类,获取到 pid 后将其传入 Attacher 里,并指定 agent jar,将 agent attach 到 TransformTarget 中,原来输出的 "hello" 就变成我们想要修改的 "bytecode replaced!" 了。
  小结
  掌握了字节码的动态修改技术后,再回头看 Btrace 的原理就更清晰了,稍微摸索一下我们也可以实现一个简版的。另外很多大牛实现的各种 Java 性能分析工具的技术栈也不外如此,了解了这些,未来我们也可以写出适合自己的工具,至少能对别人的工具进行修改~
  不得不说 Java 的生态真的非常繁荣,当真是博大精深,查阅一个模块的资料时能总引出一大堆新的概念,永远有学不完的新东西。
  本人花费2个月时间,整理了一套JAVA开发技术资料,内容涵盖java基础,分布式、微服务等主流技术资料,包含大厂面经,学习笔记、源码讲义、项目实战、讲解视频。
  希望可以帮助一些想通过自学提升能力的朋友,领取资料,扫码关注一下
  记得转发+关注+私信
  私信回复【2022学习资料】
  领取更多学习资料

TCL发布Mini?LED战略?智屏力争做到全球第一中证网讯(记者万宇)8月26日,TCL实业举办了看见,更有远见TCLMiniLED战略发布会,TCL实业副总裁TCL电子CEO张少勇发布了TCLMiniLED战略和超大屏战略,他表ColorOS12将于9月13日发布?泄密者竟然是小布助手OPPO将要发布ColorOS12的消息,已经在网上流传了一段时间。此前,传闻表示它将于8月发布,不过最新的消息显示ColorOS12的发布可能会在9月。据微博网友爆料,该发布时间张固爱数码蓝牙耳机啥牌子好?五大平价好用的蓝牙耳机推荐作为数码评测专家,张固爱数码工作室近年来承接了不少蓝牙耳机的评测项目,所以对于各种价位型号的蓝牙耳机虽说不至于如数家珍,但是基本的了解还是有的。最近工作室被不少网友私信蓝牙耳机啥牌近期iqqo8与PRO版的区别iqqo8PRO也就在今天发布了那它已它的小弟iqqo8有何区别呢?今天我就简略分析一下给大家看如图看到两者的区别第一眼呢就是CPU,骁龙888也是今发布的大家也熟知了而PRO版大从Mi变Xiaomi雷军想吃下全球高阶手机市场非得去Mi化不可昨天报道了小米将会在未来换掉自成立沿用至今的Mi字logo,全面更换为Xiaomi字母标识,此事在网络上引发热议。不过,到底是只有手机产品如此,还是所有小米的产品都这样?未来还看不国产手机的寄生之路还能走多远?2021年7月16日,全球著名市场调研机构Canalys发布手机市场第二季度排名,小米公司在全球智能手机市场占有率达到17,超越苹果晋升全球第二,同比高速增长83。国货当自强。无论1500元以下的5G手机推荐第一页首先给大家介绍的就是来自于小米子品牌旗下红米NOTE10,该款机型当在的处理器是MTK天玑700处理器,该款处理器与天玑720对比,同样采用台积电7纳米制程工艺。Cpu上略强于天玑Apple计划将于2023年发布折叠手机iPhoneFlip不在Apple的近期计划中但计划会随着时间的推移而改变。虽然今年秋天你不会在iPhone13首次亮相的同时看到可折叠iPhone,但苹果无疑有兴趣用自己的设备挑还在发愁送什么礼物,不如送他一块EZON宜准R6运动手表写在开头每逢情人节纪念日生日,很多女生都在发愁给自己的男朋友老公送什么礼物好,今天水母为大家带来的就是一款很适合送给男朋友老公的好物,宜准EZON的户外运动手表R6。相较于传统的智年轻人只是偏爱无广告的APP光明网评论员本意为了方便老年人使用的APP老年模式,如今广受年轻人追捧。媒体报道称,随着中国60岁及以上网民群体比例的增长,互联网企业开始纷纷争夺老年用户,先后推出了页面更简洁字体vivoX70系列核心配置曝光,X50价格残暴命运悲惨成弃机vivoX60Pro推出已经半年多了。据最新消息,vivo下一代旗舰机型X70系列也准备浮出水面,预计9月上市。vivoX70系列的硬件配置也相当豪华。除了唯一的传感器特色vivo
发力无人配送,这家公司年内计划交付超两千台无人车记者于浩伴随着劳动力短缺成为热门议题,机器代人相关的诸多赛道正在展现出更多商业价值,无人配送就是其中之一。成立于2018年的新石器无人车是该赛道内的玩家之一。身为物流行业的老兵,余电动车发展方向经过十余年的行业发展,现阶段市场上的电动车越来越多,可选范围越来越广泛。作为行业内人员,因为每天接触汽车,每天想的也是汽车,从各种表相新闻到深入的技术分析,都有涉猎,所以对车的理解新的红米NOTE10PRO充电行,电量不耐用,你们怎么看?感谢您的阅读!首先看一下这一款手机,它的电池容量。红米note10Pro这款手机的电池容量为5000毫安时,并且拥有67W的快充。所以这款手机本身所拥有的电池容量还是相对比较充足的耳鸣怎么治疗为什么配助听器以后更严重了?您好,如果单纯的耳鸣没有听力下降的话,一般不建议佩戴助听器,助听器没有治疗耳鸣的效果,根据不同的情况个体差异的不同患者的耳鸣情况也是不一样的,对于出现耳鸣的患者一般都没有太好的治疗哪类用户会坚持购买使用华为手机?你会选择华为手机吗?我坚持买华为手机。我认为,对于手机,坚持使用一个品牌,对学习熟悉掌握运用这个手机极有好处。我換了几代手机,也使用的N年手机,始终是华为手机不变。加之华为手机是国产的,一旦遇到什么问13年诉讼终获胜,法院驳回欧盟对英特尔12亿美元反垄断罚款IT之家1月26日消息,据华尔街日报报道,当地时间周三,英特尔公司赢得了欧盟反垄断监管机构对其12亿美元罚款的诉讼,十多年前,英特尔被指控利用商业实力排挤竞争对手AMD。2009年麒麟990相当于高通的哪款处理器,还能够用几年?麒麟990采用台积电7nm工艺制作,8核心CPU设计,具体由2个2。86GHz的A76核心2个2。09GHz的A76核心4个1。86GHz的A55核心组成,GPU为MaliG76M国行AppleWatch支持心电图功能,它对我们的日常生活真的有用吗?手机作为互联网生活的入口,也已经有更多设备呈现智能化发展趋势,其中智能穿戴设备已经成为消费电子领域中占比很高的一环。我们最常见的智能手环手表,经过多年技术发展,已经不只满足于为用户诺基亚新1100渲染图1亿相机腰线直面屏,苹果劲敌爆款价格屠夫外界对诺基亚手机的印象主要还是停留在功能机时代,因为当时诺基亚发布了型号很多的功能机,而且销量也非常高,深受消费者的欢迎。比如诺基亚1100等机型,可以说售价便宜质量可靠,所以才会LED电视和OLED电视,别盲目购买,5点差异要弄清楚大家好,我是专注家居和装修知识分享的家居杂坛。喜欢的就点击一下关注吧!现在市场上的电视的种类非常的多。像很多朋友可能所熟知的就是传统的LED电视。但是大概从2013年开始,OLED让实体店人气重新旺起来新技术新模式加快应用,新服务新业态加速涌现让实体店人气重新旺起来近日,小朋友在银泰百货杭州西湖文化广场店参与非遗文化互动体验展。核心阅读实体店是商品流通的重要载体。很多实体店适应消