Java 如何监测静态变量值的变化?

2022-04-06 14:52:51 +08:00
 rock123

维护一个老系统,有个 Config 类,其中有个静态变量 DEBUG ,默认值为 0 ,定义如下:

public static int DEBUG;

目前正式环境这个值在某些情况下会被修改成 1 ,搜了下系统中代码调用,没发现可疑的重新赋值代码,想请教下大家,如何在不修改现有代码,不增加 setter 方法的情况下监控这个变量值,当值变化时触发一个回调,打印代码执行路径?

3493 次点击
所在节点    Java
33 条回复
panpanpan
2022-04-06 15:04:41 +08:00
有趣,等一个大佬
paragon
2022-04-06 15:09:28 +08:00
idea 把断点打在 field 上变化的时候就会停下
xylophone21
2022-04-06 15:14:03 +08:00
0o0O0o0O0o
2022-04-06 15:16:41 +08:00
了解不多,java 应该没办法 watch variable 吧?所以我的思路是动态替换掉这个类,以前破解 java 应用是利用 javaagent
zhazi
2022-04-06 15:19:21 +08:00
mbean?
MakHoCheung
2022-04-06 15:23:10 +08:00
是不是通过反射来改掉的?
ikas
2022-04-06 15:28:11 +08:00
用 java 调试相关的 api 估计可以
jdi ModificationWatchpointEvent
dncba
2022-04-06 15:29:19 +08:00
使用阿里的 阿尔萨斯 工具调试一把
gitdoit
2022-04-06 15:35:29 +08:00
oneisall8955
2022-04-06 15:36:37 +08:00
全局搜索 DEBUG 都没有?
liangkang1436
2022-04-06 15:36:50 +08:00
先配置远程调试,然后在本地的源码的属性上打断点,等进断点的时候看一下断点的调用栈即可
rock123
2022-04-06 15:44:44 +08:00
@paragon #2
@xylophone21 #3

感谢两位

电脑没装 eclipse ,没有测试,看了下 idea ,确实可以监控静态变量变化,把断点打在 field ,右键断点,取消勾选 suspend, Log 一行勾选 stack trace 选项,就可以在值变化时,控制台输出代码调用路径,且不阻塞代码。

不过问题背景是线上环境偶发的一个 bug ,目前还不知道怎么触发什么时间触发,部署在远程 linux 服务器,没有图形界面。所以得我电脑全天开远程 debug ,平时电脑还有其他操作,很担心对线上服务的稳定,性能造成影响。

最好是有办法可以在代码层面监控,再不济也得是第三方命令行工具部署服务器监控,实在没办法,我再试这个远程 debug 方式
cpstar
2022-04-06 15:57:38 +08:00
运行环境下,能重新 deploy Config 这个类么?如果能,那就重写 Config ,然后起一个线程一直输出这个值。如果不能,那没办法了。
rock123
2022-04-06 16:14:50 +08:00
@dncba #8 好像没有监控变量的功能,只看到有监控方法返回值的功能。 修改这个 DEBUG 是直接 Config.DEBUG = xxx ,没有方法调用的
AlisaDestiny
2022-04-06 16:16:57 +08:00
同推荐阿里的 arthas,在线调试神器
rock123
2022-04-06 16:18:41 +08:00
@cpstar #13 轮询方法不太好,因为不知道何时会触发,一直开着,时间间隔小了,日志太多,对系统也有影响,时间间隔大了,又有可能变化在时间片内,监测不到
nothingistrue
2022-04-06 17:30:04 +08:00
逐步骤监控变量的值还有办法,但是你想在值变化时做自动处理(打印些信息),你不动代码是不行的。这是个 public 成员,可以直接赋值,切面都加不上。

还是想办法做断点调试吧,一步一步的查看值的变化。当然你不能直接在线上搞远程调试,尤其是你还想长时间的监控。你这个是公共静态变量,一个断点暂停就可能让整个系统崩溃。能在本地环境复现问题然后在本地断点调试是最好的,如果不能或者不好复现,那么只能逐行看代码了。

Eclipse 有几个功能可以帮助你找到哪个代码会修改这个值:右键变量然后选择“call hierarchy”;选中变量再 Ctrl+H ,然后可以查找所有引用这个变量的地方。
cpstar
2022-04-06 17:35:04 +08:00
如果是改成写 public static final int 呢?哪里要改写,是不是会抛异常?另外在反射上,能否仍然改写呢?
zmal
2022-04-06 17:50:04 +08:00
1.用 arthas 应该是可以的。
2.把这个字段改成 final 并上线,通过流量复制手段复制线上服务请求,看报错堆栈。
但是代码真的能复杂到通过源码找不到一个 Config 类里的 static 变量是什么情况下被改变吗?有点怀疑。
hotcool100
2022-04-06 17:58:42 +08:00
继续找,或许在引入的 jar 里的类里面呢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/845239

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX