2

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

 2 years ago
source link: https://www.v2ex.com/t/845239
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Java

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

  rock123 · 12 小时 25 分钟前 · 1131 次点击

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

public static int DEBUG;

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

26 条回复    2022-04-06 23:40:03 +08:00

panpanpan

panpanpan      12 小时 13 分钟前

有趣,等一个大佬

paragon

paragon      12 小时 8 分钟前

idea 把断点打在 field 上变化的时候就会停下

0o0O0o0O0o

0o0O0o0O0o      12 小时 1 分钟前 via iPhone

了解不多,java 应该没办法 watch variable 吧?所以我的思路是动态替换掉这个类,以前破解 java 应用是利用 javaagent

zhazi

zhazi      11 小时 59 分钟前

mbean?

MakHoCheung

MakHoCheung      11 小时 55 分钟前

是不是通过反射来改掉的?

ikas

ikas      11 小时 50 分钟前

用 java 调试相关的 api 估计可以
jdi ModificationWatchpointEvent

dncba

dncba      11 小时 49 分钟前

使用阿里的 阿尔萨斯 工具调试一把

oneisall8955

oneisall8955      11 小时 41 分钟前

全局搜索 DEBUG 都没有?

liangkang1436

liangkang1436      11 小时 41 分钟前 via Android

先配置远程调试,然后在本地的源码的属性上打断点,等进断点的时候看一下断点的调用栈即可

rock123

rock123      11 小时 33 分钟前

@paragon #2
@xylophone21 #3

感谢两位

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

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

最好是有办法可以在代码层面监控,再不济也得是第三方命令行工具部署服务器监控,实在没办法,我再试这个远程 debug 方式

cpstar

cpstar      11 小时 20 分钟前

运行环境下,能重新 deploy Config 这个类么?如果能,那就重写 Config ,然后起一个线程一直输出这个值。如果不能,那没办法了。

rock123

rock123      11 小时 3 分钟前

@dncba #8 好像没有监控变量的功能,只看到有监控方法返回值的功能。 修改这个 DEBUG 是直接 Config.DEBUG = xxx ,没有方法调用的

AlisaDestiny

AlisaDestiny      11 小时 1 分钟前 via Android

同推荐阿里的 arthas,在线调试神器

rock123

rock123      10 小时 59 分钟前

@cpstar #13 轮询方法不太好,因为不知道何时会触发,一直开着,时间间隔小了,日志太多,对系统也有影响,时间间隔大了,又有可能变化在时间片内,监测不到

nothingistrue

nothingistrue      9 小时 48 分钟前

逐步骤监控变量的值还有办法,但是你想在值变化时做自动处理(打印些信息),你不动代码是不行的。这是个 public 成员,可以直接赋值,切面都加不上。

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

Eclipse 有几个功能可以帮助你找到哪个代码会修改这个值:右键变量然后选择“call hierarchy”;选中变量再 Ctrl+H ,然后可以查找所有引用这个变量的地方。

cpstar

cpstar      9 小时 43 分钟前

如果是改成写 public static final int 呢?哪里要改写,是不是会抛异常?另外在反射上,能否仍然改写呢?

zmal

zmal      9 小时 28 分钟前

1.用 arthas 应该是可以的。
2.把这个字段改成 final 并上线,通过流量复制手段复制线上服务请求,看报错堆栈。
但是代码真的能复杂到通过源码找不到一个 Config 类里的 static 变量是什么情况下被改变吗?有点怀疑。

hotcool100

hotcool100      9 小时 19 分钟前

继续找,或许在引入的 jar 里的类里面呢

fxxkgw

fxxkgw      8 小时 43 分钟前

修改的地方估计被打成包了 所以单纯查关键词找不到 试试 grep 搜索下

likeunix

likeunix      7 小时 28 分钟前 via Android

还是 C#香

v2lf

v2lf      4 小时 50 分钟前

@cpstar 发射可以修改 final
"final fields can be changed via reflection and other implementation-dependent means."
但是要注意常量表达式赋值
“If a final field is initialized to a constant expression (§15.28) in the field declaration, changes to the final field may not be observed, since uses of that final field are replaced at compile time with the value of the constant expression.”

而且更改的话,会有线程安全问题

v2lf

v2lf      4 小时 49 分钟前

@v2lf 可以看下 System 类

lower

lower      3 小时 38 分钟前

@sky857412 这个好像不行,好像上还是在 setter 里面做记录……

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK