如何回收 jvm 内的静态变量,以达到伪重启的效果?

2017-03-06 17:14:13 +08:00
 smithtel

如题,目前所在的公司有几个在用的十分老久的系统,缓存都是用的静态变量,目前增改参数都是需要重启系统,而我们的系统过于臃肿,每次重启十分麻烦。
目前领导提出了新需求:一个按钮清除所有缓存。
讲道理我想辞职了,不过还是先努力一番,集思广益说不定就成了?
求各位大佬解惑,感激不尽。

生产环境版本: jdk 1.6

2253 次点击
所在节点    问与答
12 条回复
kaneg
2017-03-06 17:42:05 +08:00
你明确的需求是什么? 清除缓存还是修改参数?

如果要清除缓存,只要把相应的缓存变量清空即可,当然,前提条件这些缓存变量在你的控制范围内。
如果是增改参数,那就提供相应的接口,外部可以控制
simonlei
2017-03-06 18:35:13 +08:00
静态变量只是一个 ClassLoader 里面是静态的,换个新的 ClassLoader 就可以换静态变量了。 Eclipse 就是靠这种方式来达到动态加载 plugin 的。
不过要改造老旧的系统,达到这样的效果,我觉得也是个不小的工作量。
caixiexin
2017-03-06 19:55:31 +08:00
是静态变量还是 final 的静态变量呢,没有 final 的话,静态变量也能重新赋值不是?
smithtel
2017-03-06 19:55:59 +08:00
@kaneg 清除缓存,现在的问题就是并不清楚这写变量在哪,一个个去看代码,我觉得我要炸。
@simonlei 如果将所有的 ClassLoader 替换掉,会不会有问题呢?
smithtel
2017-03-06 19:56:59 +08:00
@caixiexin 关键是静态变量用的地方太多,很难去找,审查代码的话,几个大项目几十万行代码我觉得我能看到年中去。
kaneg
2017-03-06 20:41:44 +08:00
如果都找不到这些静态变量在哪里,就算把它们重置,那你怎么让它们重新初始化呢
SoloCompany
2017-03-06 20:55:08 +08:00
class loader 置换是有代价的,因为 permgen 很难被回收

即使你的业务代码足够简单,完全没有资源竞争(不需要 listen 端口,不需要独占打开文件),因为初始化总是避免不了,你所描述的问题(重启十分麻烦)大几率还是无法避不开,问题出现在你们自己业务代码上要比在 jvm 启动上的可能高的多

所以不要想什么捷径,该靠业务代码来 reload / 清 cache 的就别想着从外面解决

当然你也可以尝试一下使用反射遍历所有业务 class 的静态 field ,如果是某种类型的,就执行 clear 方法;当然如果你把 [某种类型] 理解为 Map 的话,当我没说过吧
odirus
2017-03-06 21:02:38 +08:00
虽然重启复杂,但楼主还是想想怎么把重启改成自动化吧,修改代码是大忌啊,特别是老旧、没文档的系统,一不小心就引出莫名其妙的 BUG ,多想想怎么自动重启,总比你修改代码来得直接把。
smithtel
2017-03-06 21:04:50 +08:00
@SoloCompany 啊啊啊,有很多业务代码是有持续的读写文件。不过最后这个方法倒是一个可行点,代码里面是有很多 list 和 map ,这是可以想办法去搞的。
des
2017-03-06 21:13:04 +08:00
同意 8 楼的,不如弄个一键重启
zhoujinjing09
2017-03-07 03:33:50 +08:00
用 spring 的 DI ,把静态类都变成单例,应该就能热重启了
smithtel
2017-03-07 16:35:10 +08:00
@zhoujinjing09 老系统,没有 spring
@odirus 重启并不复杂,麻烦的是权限并不属于开发,而是分属于多人,几个系统所属部分不一样,管理员也不一样。

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

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

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

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

© 2021 V2EX