吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 441|回复: 1
上一主题 下一主题
收起左侧

[会员申请] 申请会员ID:xhmlwaf

[复制链接]
跳转到指定楼层
楼主
吾爱游客  发表于 2024-9-18 11:40 回帖奖励 |自己
1、申 请 I D:xhmlwaf
2、个人邮箱:331379635@qq.com
3、原创技术文章:java后端服务在线(不重启)用arthas工具修改代码

一.为什么要在线修改代码

一般在线修改代码是为了排查问题,而在不重启的情况下修改代码有他的必要性
1.重启会导致当前环境发生变化,导致问题无法复现。
2.用户正在使用服务,重启服务会导致用户体验不好。


二.Arthas在线修改代码的原理


我们知道,java在启动后,如果代码没有明确去动态加载类,一般是不会重新去加载的。
例如有以下代码可以加载一个类
[Java] 纯文本查看 复制代码
String driverName = "com.mysql.jdbc.Driver";
Class clazz = Class.forName(driverName);

这个代码会加载指定的类:com.mysql.jdbc.Driver

那怎么在运行过程中重新加载修改后的类

1.这里用到了javaagent机制

Jdk5增加了一个包java.lang.instrument,提供了对Jvm底层组件的访问能力,Instrument要求在运行前利用命令行参数或者系统参数设置代{过}{滤}理类,VM启动完成之后(绝大多数类加载前)初始化。


开发基于instrument的应用,需要这么几个步骤:


步骤1:编写premain函数

步骤2:jar文件打包,制定Premain-Class

步骤3:使用-javaagent参数启动


Jdk6以后,针对这点进行了改进,开发者可以在main函数执行之后再启动自己的Instrument应用,入口是agentmain函数。arthas就是通过这个实现的。


Instrumentation 接口的关键代码
[Java] 纯文本查看 复制代码
public interface Instrumentation {
    /**
     * 注册一个Transformer,从此之后的类加载都会被Transformer拦截。
     * Transformer可以直接对类的字节码byte[]进行修改
     */
    void addTransformer(ClassFileTransformer transformer);
    
    /**
     * 对JVM已经加载的类重新触发类加载。使用的就是上面注册的Transformer。
     * retransformation可以修改方法体,但是不能变更方法签名、增加和删除方法/类的成员属性
     */
    void retransformClasses(Class<?>... classes) throws UnmodifiableClassException;
    
    /**
     * 获取一个对象的大小
     */
    long getObjectSize(Object objectToSize);
    
    /**
     * 将一个jar加入到bootstrap classloader的 classpath里
     */
    void appendToBootstrapClassLoaderSearch(JarFile jarfile);
    
    /**
     * 获取当前被JVM加载的所有类对象
     */
    Class[] getAllLoadedClasses();
}


Arthas通过Instrumentation API注册一个ClassFileTransformer,这个Transformer可以在类加载到JVM时,对类的字节码进行修改。例如,Arthas可以在方法的开始和结束时插入自定义的监控代码,从而实现对方法执行时间的监控。



三.Arthas在线修改代码的流程


1.启动arthas并attach到目标jvm上


[Bash shell] 纯文本查看 复制代码
java -jar  arthas-boot.jar PID

这里的PID可以通过top命令查看


这里的原理不细说,有需要的自己去了解下,Attach API是Java 6引入的一个接口,允许一个Java进程动态附加到另一个运行中的Java进程。Arthas利用Attach API将自身的Java Agent动态附加到目标JVM上,进而实现对目标应用的监控。通过Attach API,Arthas可以在无需重启目标应用的情况下,动态加载和卸载自己的监控代码。


2.导出目标类代码
[Bash shell] 纯文本查看 复制代码
jad --source-only com.xxx.xxxx.KafkaDispositionConsumer > /tmp/java/KafkaDispositionConsumer.java

导出的是源码,.java格式,这意味着我们可以直接修改编辑它。

3.修改目标类代码
这里的修改按自己的需要修改,但是注意一下两点:
不能添加类变量(成员变量和静态变量都不行)
不能添加方法


可以做的就是在方法中间进行修改


4.重新编译修改后的代码
这里有条件的,可以在开发环境编译好class文件再拿过来使用。
如果没有条件,例如代码无法传出去,也可以使用arthas的编译功能(有几率失败)
mc -c 类加载器的ClassLoaderHash /tmp/java/KafkaDispositionConsumer.java

这里类加载器的ClassLoaderHash,可以通过以下命令获取
sc -d com.xxx.xxxx.KafkaDispositionConsumer   
我们需要使用这个类原有的加载器来编译修改的文件。

5.重新加载修改后的文件
上一步的过程会输出字节码文件路径
redefine 上一步输出的类路径。

通过以上操作后,就可以实现不重启的情况下修改线上代码。












发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
Hmily 发表于 2024-9-23 17:12
抱歉,未能达到申请要求,申请不通过,可以关注论坛官方微信(吾爱破解论坛),等待开放注册通知。

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-23 22:03

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表